paulo1205
(usa Ubuntu)
Enviado em 29/11/2016 - 14:02h
Vamos fazer o “chinês” do seguinte bloco de código (supondo que o usuário não digite nada deliberadamente mal-intencionado para o programa).
l01: printf ("Digite a quantidade que deseja adicionar ao estoque: \n");
l02: scanf ("%i", &produtos[ i ].quantidade);
l03: printf ("Digite a categoria do produto: \n");
l04: scanf ("%[^\n]s", produtos[ i ].categoria);
l05: printf ("Digite o codigo do produto: \n");
l06: scanf ("%i", &produtos[ i ].codigo);
l07: printf ("Digite o preço do produto: \n");
l08: scanf ("%f", &produtos[ i ].preco);
l09: printf ("Digite a descrição do produto: \n");
l10: scanf ("%[^\n]s", produtos[ i ].descricao);
l11: printf ("Digite o fornecedor do produto: \n");
l12: scanf ("%[^\n]s", produtos[ i ].categoria);
l13: printf ("Digite a validade do produto: \n");
l14: scanf ("%[^\n]s", produtos[ i ].validade);
l15: printf ("Deseja adicionar um novo produto? Digite [s] ou [n]: \n");
l16: scanf ("%c", &add_produto);
Na linha
l02 , lê o valor de um dado do tipo inteiro. Supondo que o usuário digite um número (por exemplo: 50) e tecle
Enter , o conteúdo buffer de entrada nessa hora será
"50\n" . A conversão
"%i" de
scanf () consumirá os bytes
'5' e
'0' e os converterá num valor inteiro que é gravado em
produtos[i ].quantidade , e deixará o
'\n' no buffer de entrada.
O programa então imprime a mensagem da linha
l03 . A string de formatação da linha
l04 pede para ler uma quantidade qualquer (zero ou mais) de caracteres diferentes de
'\n' , e depois pede para localizar o caráter 's'. Como o buffer de entrada não está vazio e como a conversão
"%[" não habilita o descarte de espaços em branco, o processamento do buffer de entrada começa imediatamente, mesmo que o usuário ainda não tenha digitado nada. Como o caráter que está presente no buffer não atende o critério, a conversão
"%[\n]" é
bem-sucedida , lendo uma string de tamanho zero e deixando o
'\n' no buffer de entrada. A seguir, o processamento da string de formatação continua, e o primeiro caráter do buffer é comparado com
's' . Como
'\n'!='s' , a função mantém o '\n' no buffer de entrada, e
interrompe o processamento prematuramente ao notar que parte da string de formatação não corresponde ao conteúdo do buffer.
Ainda com o
'\n' da leitura em
l02 no buffer de entrada, você passa pela linha
l05 , imprimindo uma mensagem (que provavelmente o usuário vai ver aparecendo logo após a mensagem da linha
l03 ), e chega à linha
l06 , que tenta ler um inteiro. A conversão
"%i" realiza a supressão de espaços em branco, então o
'\n' que sobrara finalmente será consumido. Se o usuário se sentir tentado a digitar o texto da categoria, cuja leitura passou direto por causa do erro na string de formatação de
l03 , então esse texto será submetido à tentativa de ler um valor inteiro, e provavelmente a leitura vai falhar (a não ser que a categoria seja composta apenas de algarismos), deixando o texto inteiro (incluindo o
'\n' correspondente a se se apertado
Enter ) no buffer. Por outro lado, se o usuário entender que a chance de ler a categoria já passou, e digitar apenas um número inteiro, esse número será lido e convertido, mas o
'\n' que vem depois dele vai permanecer no buffer de entrada.
Ao tentar ler o dado de ponto flutuante em
l08 , se o buffer contiver apenas o
'\n' , esse
'\n' será descartado pelo descarte automático de espaços em branco realizado pela conversão
"%f" , e o programa vai tentar consumir caracteres que formem num número de ponto flutuante válido e, ao final dessa leitura, o
'\n' que segue o número vai ficar no buffer de entrada. Entretanto, se ainda houver texto referente à possível entrada equivocada da leitura em
l06 , esse texto vai causar também a falha de leitura em
l08 .
As leituras em
l10 ,
l12 e
l14 são todas de strings, mas todas têm o mesmo erro na string de formatação que a da leitura em
l02 (e uma delas inclusive repete a leitura da categoria). Se se tiver erroneamente digitado o texto da categoria na hora de ler a quantidade, esse texto será finalmente consumido por
l10 , mas o
'\n' que vinha após o texto permanecerá no buffer, deixando de ser consumido também pelas leituras em
l12 e
l14 . Se houver apenas o
'\n' após uma leitura bem sucedida em
l08 , todas as operações em
l10 ,
l12 e
l14 não conseguirão consumi-lo. Em qualquer dos casos, as três leituras falharão em encontrar o caráter
's' com um retorno de
scanf () que ocorrerá antes de chegar ao fim da strong de formatação.
Ao chegar a
l16 , haverá um
'\n' no buffer. Como a conversão
"%c" não provoca descarte de espaços em branco, é esse
'\n' que será colocado na variável
add_produto .