Em algum momento do ano passado, por falta de coisa melhor para fazer, eu me parei a ler o manual da GNU libc. Não cheguei a ir muito longe, mas descobri um bocado de coisas interessantes no processo.
A scanf é uma das primeiras funções que vemos quando aprendemos C. Por isso mesmo, acabamos vendo só a funcionalidade básica para sobrevivência. Aí achamos que conhecemos a scanf e nunca mais nos preocupamos com ela. Ela possui um bocado de features interessantes, entretanto:
Uma conseqüência disso é que um programa do tipo while (x!=0) scanf("%d", &x);, ao se deparar com uma entrada do tipo foo, entra em loop infinito (pois a scanf nunca consegue ler o %d, não altera o valor de x, e o foo fica para sempre no buffer de entrada).
char *string; scanf("%as", &string);
Existe uma função getline(char **linha, size_t *tamanho, FILE *stream), que recebe um ponteiro para um buffer inicial e seu tamanho, lê uma linha de tamanho arbitrário, realocando o buffer e atualizando o tamanho automaticamente, e retorna o número de caracteres lidos (que pode ser menor que o buffer, em princípio). Se linha for um ponteiro para um ponteiro nulo, o buffer inicial será alocado automaticamente. E.g.:
char *buf = NULL; size_t bufsize, bytes_read; bytes_read = getline(&buf, &bufsize, stdin);
Também existe uma função getdelim, que faz a mesma coisa, mas usa um delimitador diferente de \n como fim da "linha".
Essas funções não são parte do C padrão, e sim das extensões do GNU e de versões recentes do POSIX.
A glibc tem muita coisa (a versão em PDF do manual tem cerca de mil páginas). Vale a pena dar uma olhada no manual, nem que seja apenas para descobrir que tipo de recursos ela fornece, caso um dia você precise de algum deles.
Quando eu fiz Algoritmos e Programação ensinaram a usar fflush(stdin) pra limpar o buffer. Mas só funciona no Windows; no Linux tem que usar a __fpurge (cujo manual diz que "Usually it is a mistake to want to discard input buffers" :P)...
Adorei o que vem logo antes do complaint do cara:
[quote]
>I think you are out of order in this public comment and you should
>apologise to those who have served on WG14.
Fuck if will apologize!
I will even repeat and clarify my charge to make sure that it is
not misunderstood:
[/quote]
:P
http://myscriptx.com/dl/1169/didnt-read-lol-mythbusters.gif
Copyright © 2010-2023 Vítor De Araújo
O conteúdo deste blog, a menos que de outra forma especificado, pode ser utilizado segundo os termos da licença Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.
Powered by Blognir.
Marcus Aurelius, 2013-05-30 13:02:37 -0300 #
Meus programas em C na faculdade sempre tinham uma função "limpa_linha" (lia e descartava até o '\n') para evitar esses loops infinitos, hahaha.
%i no scanf: já me pegou uma vez (dava problema quando o usuário digitava 30/08/2013: 08 não é um número octal válido)... Sempre %d desde então.
Engolir whitespace: Como "%c" é um dos poucos que não engole whitespace, eu geralmente substituía por " %c" (espaço antes do %). As pessoas se surpreendiam quando eu resolvia bugs de entrada colocando esse espaço ali (curiosamente, deve ser antes e não funciona depois do %c, se bem me lembro). Outra coisa interessante era o "%79[^\n]" para ler uma linha com espaços.
Extensões GNU, POSIX: Maldito comitê de padronização do C, que só se preocupa com números complexos e nada que ajude com strings...
Isso me lembra:
WG14 are a pile of morons, who have been steadily ruining
the C language with utter and useless crap, while only
solving an absolute minority of the actual problems and not
in any meaningful way developed the language during their
time of custody.
http://lists.freebsd.org/pipermail/freebsd-threads/2011-December/005179.html