Programar em C/Mais sobre funções
Os argumentos argc e argv
editarA função main(), como dissemos antes, é uma função especial. Introduzimo-la como uma função sem parâmetros; no entanto, ela também pode receber parâmetros formais. No entanto, o programador não pode escolher quais serão. Eles devem ser os seguintes:
int main (int argc, char *argv[])
- argc (argument count) é um inteiro e possui o número de argumentos com os quais o programa foi chamado na linha de comando. Ele é no mínimo 1, pois o nome do programa é contado como sendo o primeiro argumento.
- argv (argument values) é um ponteiro para uma matriz de strings (conceitos que serão abordados mais à frente). Cada string desta matriz é um dos parâmetros da linha de comando. argv[0] sempre aponta para o nome do programa (que, como já foi dito, é considerado o primeiro argumento). É para saber quantos elementos temos em argv que temos argc.
Como pode se imaginar, os nomes dos parâmetros "argc" e "argv" podem ser mudados, mas por questão de padronização não se costuma modificá-los.
Exemplo: Escreva um programa que faça uso dos parâmetros argv e argc. O programa deverá receber da linha de comando o dia, mês e ano correntes, e imprimir a data em formato apropriado. Veja o exemplo, supondo que o executável se chame data:
data 19 04 99
O programa deverá imprimir: 19 de abril de 1999
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int mes;
char *nome_mes [] = {
"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho",
"Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
};
if(argc == 4) /* Testa se o número de parâmetros fornecidos está correto,
o primeiro parâmetro é o nome do programa, o segundo o dia,
o terceiro o mes e o quarto os dois últimos algarismos do ano */
{
mes = atoi(argv[2]); /* argv contem strings. A string referente ao mes deve ser transformada
em um numero inteiro. A funcao atoi esta sendo usada para isto:
recebe a string e transforma no inteiro equivalente */
if (mes<1 || mes>12) /* Testa se o mes e' valido */
printf("Erro!\nUso: data dia mes ano, todos inteiros");
else
printf("\n%s de %s de 19%s", argv[1], nome_mes[mes-1], argv[3]);
}
else printf("Erro!\nUso: data dia mes ano, todos inteiros");
}
Lista de argumentos
editarNa linguagem C é possível funções como "printf" onde o número de argumentos podem variar. As reticências ( ... ) indicam um numero variável de argumentos ou argumentos com tipos variável. Ex:
void f_erro(int n, char *fmt, ...);
Essa declaração indica que se deve fornecer pelo menos dois argumentos, um do tipo int e um do tipo char mais pode se fornecer argumentos suplementares. Ou seja, "não há limites para sua criatividade"! Ex:
f_erro( 3, "Erro: missão impossível "); f_erro( valor, "%s %d\n", mensagem, errno);
E necessário ter pelo menos um argumento antes dos pontos. Veja um exemplo incorreto.
void erreur(...);
O arquivo de cabeçalho stdarg.h declara um tipo va_list e define três macros para manipular uma lista de argumentos cuja quantidade e tipos são desconhecidos pela função.
va_start, va_arg et va_end (va como variable argument)
Sintaxe:
#include <stdarg.h>
void va_start(va_list ap, last); type va_arg(va_list ap, type); void va_end(va_list ap); void va_copy(va_list dest, va_list src);
Descrição:
va_start:
- A macro va_start inicializa ap para uso posterior por va_arg e va_end e deve ser chamada primeiro.
- O parâmetro last é o nome do último parâmetro antes da lista de argumentos variáveis, isto é, o último parâmetro o qual a função conheçe o tipo.
- Porque o endereço deste parâmetro pode ser usado na macro va_start, ele não deve ser declarado como uma variável register, ou como uma função ou como um array.
va_arg:
- A macro va_arg retorna o primeiro argumento variável e faz ap apontar o próximo argumento. O parâmetro ap é aquele inicializado por va_start. O parâmetro type é um nome de tipo. Pode-se apontar para um objeto de um tipo específico simplesmente adicionando um * ao tipo.
- O primeiro uso da macro va_arg após a macro va_start retorna o argumento após last. Chamadas sucessivas retornam os valores dos outros argumentos.
- Se não existe próximo argumento, ou se type não é compatível com o tipo do próximo argumento, erros aleatórios ocorrerão.
- Se ap é passado para uma função que usa va_arg(ap,type) então o valor de ap é destruído após o retorno da função.
va_end:
- Cada chamada de va_start deve ter uma chamada correspondente a va_end na mesma função. Após a chamada de va_end a variável ap é destruída. Várias chamadas com va_start e va_end aninhadas são possíveis. va_end pode ser uma macro ou uma função.
Exemplo 1
/* Calcula a soma de n inteiros */
/* o ultimo argumento deve ser 0 */
#include <stdio.h>
#include <stdarg.h>
int soma(int n1, ...) {
va_list pa;
int som, n;
som = n1;
va_start(pa, n1);
while( (n = va_arg(pa, int)) != 0)
som = som + n;
va_end(pa);
return som;
}
main() {
printf("1 + 3 + 5 + 7 + 9 = %d\n", soma(1,3,5,7,9,0));
printf("1 + 1 = %d\n", soma(1,1,0));
return 0;
}
/*-- resultado ----------------------------
1 + 3 + 5 + 7 + 9 = 25
1 + 1 = 2
---------------------------------------------------------*/
Exemplo 2
#include <stdio.h>
#include <stdarg.h>
void meu_printf(char *fmt, ...) {
va_list pa;
int n;
char *s, c;
float f;
va_start(pa, fmt);
while (*fmt != '\0') {
if ( *fmt == '%' ) {
/* (*++fmt) equivale a (*fmt = *fmt + 1 )*/
switch (*++fmt) {
case '%' : putchar('%'); break;
case 'c' : /* char*/
c = va_arg(pa, int);
putchar(c);
break;
case 'd' : /* int */
n = va_arg(pa, int);
printf("%d", n);
break;
case 'f' : /* float */
f = va_arg(pa, double); /* !!!!! */
printf("%f", f);
break;
case 's' : /* string */
s = va_arg(pa, char *);
for ( ; *s != '\0'; s++ )
putchar( *s );
break;
} /* end switch */
}
else
putchar( *fmt );
/*incrementa o ponteiro*/
fmt++;
}
va_end(pa);
}
int main() {
meu_printf("float = %f\n", (float) 1.2345);
meu_printf("int = %d char = %c String = %s\n", 123, 'A', "C is beautiful !" );
return 0;
}