Tenho o seguinte programa:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d",&a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c",&c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
Como li no livro C, o autor diz que scanf()
deixou um caractere de nova linha no buffer, portanto, o programa não para na linha 4 para o usuário inserir os dados, em vez disso, armazena o caractere de nova linha em c2 e vai para linha 5.
Isso está certo?
No entanto, isso só acontece com char
tipos de dados? Porque eu não vi esse problema com int
os tipos de dados nas linhas 1, 2, 3. Está certo?
fflush(stdin)
pode ser usado antes da chamada parascanf()
para um único caractere. Leia Usandofflush(stdin)
para uma discussão sobre os prós, contras e alternativas a esse método (que funciona, mais ou menos, no Windows, e não funciona na maioria dos outros lugares).Respostas:
A
scanf()
função ignora os espaços em branco iniciais automaticamente antes de tentar analisar conversões que não sejam caracteres. Os formatos de caracteres (principalmente%c
; também conjuntos de varredura%[…]
- e%n
) são a exceção; eles não pulam os espaços em branco.Use
" %c"
com um espaço em branco à esquerda para pular o espaço em branco opcional. Não use um espaço em branco à direita em umascanf()
string de formato.Observe que isso ainda não consome nenhum espaço em branco à esquerda no fluxo de entrada, nem mesmo até o final de uma linha, então tome cuidado com isso se também estiver usando
getchar()
oufgets()
no mesmo fluxo de entrada. Estamos apenas fazendo o scanf pular os espaços em branco antes das conversões, como faz para%d
outras conversões sem caracteres.Observe que as "diretivas" sem espaço em branco (para usar a terminologia POSIX scanf ) além de conversões, como o texto literal em
scanf("order = %d", &order);
também não pula os espaços em branco. O literalorder
deve corresponder ao próximo caractere a ser lido.Então você provavelmente vai querer
" order = %d"
lá se quiser pular uma nova linha da linha anterior, mas ainda exigir uma correspondência literal em uma string fixa, como esta questão .fonte
%c
,%n
,%[]
São os 3 expectativas específicas que não consomem os espaços em branco.scanf()
string de formato escanf()
perguntando duas vezes pela entrada, enquanto espero que ele peça apenas uma vez para uma discussão sobre espaços em branco à direita em strings de formato. Eles são uma má ideia - surpreendentemente ruim se você espera interação humana e ruim para a interação do programa.Use
scanf(" %c", &c2);
. Isto irá resolver o seu problema.fonte
Outra opção (que peguei aqui ) é ler e descartar a nova linha usando a opção de supressão de atribuição . Para fazer isso, apenas colocamos um formato para ler um caractere com um asterisco entre
%
ec
:scanf("%d%*c",&a); // line 1 scanf("%c%*c",&c1); // line 3
scanf
irá então ler o próximo caractere (ou seja, a nova linha), mas não o atribuirá a nenhum ponteiro.No final, entretanto, eu concordaria com a última opção do FAQ :
fonte
a
então espaço e nova linha, a conversão de caracteres suprimida lê o espaço e ainda deixa a nova linha. Se o usuário digitarsupercalifragilisticexpialidocious
quando você esperaa
, você terá muitos caracteres extras com os quais lidar. Você nunca pode dizer se uma conversão suprimida à direita foi bem-sucedida - elas não são contadas no retorno descanf()
.Use
getchar()
antes de ligar em segundo lugarscanf()
.scanf("%c", &c1); getchar(); // <== remove newline scanf("%c", &c2);
fonte
int c; while ((c = getchar()) != EOF && c != '\n') ;
(escrito em três linhas quando não está em um comentário). Muitas vezes é suficiente; não é infalível (e você deve se lembrar que os tolos são muito espertos para quebrar coisas).