diff --git a/aulas/09-args/README.org b/aulas/09-args/README.org index 3380341..696ff6b 100644 --- a/aulas/09-args/README.org +++ b/aulas/09-args/README.org @@ -161,3 +161,99 @@ int main(int argc, char **argv) { return 0; } #+end_src + +** Conversão de strings para números + +Como todos os argumentos são recebidos como strings, haverá situações em +que eles deverão ser convertidos para os valores numéricos correspondentes. + +*** Exemplo: programa =soma.c= + +#+begin_src c +#include +#include +#include + +long str2int(char *str) { + + int num; // Recebe o inteiro convertido. + char *end; // Recebe o endereço onde termina o inteiro na string. + + errno = 0; // Zerar a variável global 'errno'. + + // Converte a parte numérica inicial de 'str' pata long int. + num = strtol(str, &end, 10); + + // Checagem de erros... + if (str == end) { + // A parte inicial da string não era numérica... + fprintf(stderr, "Nenhum dígito encontrado!\n"); + exit(EXIT_FAILURE); + } else if (errno == ERANGE) { + // O número está fora dos limites do tipo 'long int'... + fprintf(stderr, "Número fora dos limites!\n"); + exit(EXIT_FAILURE); + } else if (*end != '\0') { + // Caracteres não convertidos restantes... + fprintf(stderr, "Caracteres inválidos: %s\n", end); + exit(EXIT_FAILURE); + } + + return num; +} + + +int main(int argc, char **argv) { + int soma = 0; + int num; + + for (int i = 1; i < argc; i++) { + num = str2int(argv[i]); + if (i == 1) { + printf("%d ", num); + } else { + printf("+ %d ", num); + } + soma += num; + } + printf("= %d\n", soma); + + return 0; +} +#+end_src + +Aqui, nós usamos a função =strtol=, que converte os dígitos encontrado na parte +inicial de uma string em seu correspondente numérico com o tipo =long int= na +base numérica especificada no terceiro argumento. + +#+begin_src c +long strtol(const char *restrict nptr, char **_Nullable restrict endptr, int base); +#+end_src + +Seu retorno é o valor numérico convertido, a menos que o valor exceda os limites +do tipo =long int=, o que fará com que o retorno seja =LONG_MIN= ou =LONG_MAX=. Se esta +for a situação, a global =errno= receberá o valor da constante simbólica =ERANGE=, +o que nos levou a utilizar o cabeçalho =errno.h= no exemplo. + +#+begin_quote +Como a conversão pode retornar o valor =0=, é preciso inicializar =errno= com =0= antes +de chamar =strtol=. +#+end_quote + +Ao fazer a conversão, o endereço do término da parte numérica é registrado no +parâmetro =endptr=, o que possibilita fazer diversas verificações, como: + +- Se o endereço em =endptr= for igual ao endereço do início da string, a parte + inicial contém dígitos; +- Se o valor em =endptr= for igual a =\0=, a string só contém dígitos. + +Além disso, se houver uma parte final não numérica, ela pode ser recuperada +a partir do endereço em =endptr=. + +*Compilando e executando...* + +#+begin_example +:~$ gcc -Wall -o soma soma.c +:~$ ./soma 1 2 3 4 +1 + 2 + 3 + 4 = 10 +#+end_example diff --git a/aulas/09-args/soma.c b/aulas/09-args/soma.c new file mode 100644 index 0000000..d396615 --- /dev/null +++ b/aulas/09-args/soma.c @@ -0,0 +1,50 @@ +#include +#include +#include + +long str2int(char *str) { + + int num; // Recebe o inteiro convertido. + char *end; // Recebe o endereço onde termina o inteiro na string. + + errno = 0; // Zerar a variável global 'errno'. + + // Converte a parte numérica inicial de 'str' pata long int. + num = strtol(str, &end, 10); + + // Checagem de erros... + if (str == end) { + // A parte inicial da string não era numérica... + fprintf(stderr, "Nenhum dígito encontrado!\n"); + exit(EXIT_FAILURE); + } else if (errno == ERANGE) { + // O número está fora dos limites do tipo 'long int'... + fprintf(stderr, "Número fora dos limites!\n"); + exit(EXIT_FAILURE); + } else if (*end != '\0') { + // Caracteres não convertidos restantes... + fprintf(stderr, "Caracteres inválidos: %s\n", end); + exit(EXIT_FAILURE); + } + + return num; +} + +int main(int argc, char **argv) { + + int soma = 0; + int num; + + for (int i = 1; i < argc; i++) { + num = str2int(argv[i]); + if (i == 1) { + printf("%d ", num); + } else { + printf("+ %d ", num); + } + soma += num; + } + printf("= %d\n", soma); + + return 0; +}