scanf: “% ” pula a segunda input, mas “% ” não. porque?

Considere o seguinte código:

#include  int main (void) { char str1[128], str2[128], str3[128]; printf ("\nEnter str1: "); scanf ("%[^\n]", str1); printf ("\nstr1 = %s", str1); printf ("\nEnter str2: "); scanf ("%[^\n]", str2); printf ("\nstr2 = %s", str2); printf ("\nEnter str3: "); scanf ("%[^\n]", str3); printf ("\nstr3 = %s", str3); printf ("\n"); return 0; } 

Quando executado, somente o primeiro scanf pára para o prompt. O programa não pára para os próximos scanf s. Mas se a string de formato for alterada de "%[^\n]" para " %[^\n]" (observe o espaço em branco antes de % ), então tudo funciona bem. Algum caractere de nova linha existente do buffer de input anterior é automaticamente aceito? Mas flushing stdin não resolve isso.

Qual é a causa disso?

Você só precisa ‘consumir’ o caractere '\n' depois de ler o que deseja. Use a seguinte diretiva de formato:

 "%[^\n]%*c" 

Que vai ler tudo até a nova linha na string que você passar, então consumirá um único caractere (a nova linha) sem atribuí-lo a nada (que '*' é ‘supressão de atribuição’).

Caso contrário, a nova linha é deixada no stream de input aguardando para finalizar imediatamente as diretivas de formato "%[^\n]" subsequentes.

O problema com a adição de um caractere de espaço à diretiva de formato ( " %[^\n]" ) é que o espaço corresponderá a qualquer espaço em branco. Então, ele vai comer a nova linha a partir do final da input anterior, mas também irá comer qualquer outro espaço em branco (incluindo múltiplas novas linhas).

Atualize para o seu exemplo:

  char* fmt = "%[^\n]%*c"; printf ("\nEnter str1: "); scanf (fmt, str1); printf ("\nstr1 = %s", str1); printf ("\nEnter str2: "); scanf (fmt, str2); printf ("\nstr2 = %s", str2); printf ("\nEnter str3: "); scanf (fmt, str3); printf ("\nstr2 = %s", str3); printf ("\n"); 

Quando você usa scanf() para ler as strings, sua string de formato ( %[^\n] ) diz à function para ler todos os caracteres que não são '\n' . Isso deixa o caractere '\n' no buffer de input. Então quando você tenta ler str2 e str3 , scanf() descobre que a primeira coisa no buffer é '\n' toda vez e, por causa da string de formatação, não a remove do buffer de input. O que você precisa é de um getchar() entre as horas que você lê a partir do buffer de input (geralmente colocado imediatamente após scanf() ). Como já existe um '\n' no buffer, seu programa não parecerá travar porque não terá que esperar pela input de getchar() para receber. Tente. 🙂

Para aqueles que não têm idéia do que esse modificador scanf() faz, aqui está um trecho relevante de http://linux.die.net/man/3/scanf

[

Corresponde a uma seqüência não vazia de caracteres do conjunto especificado de caracteres aceitos; o próximo ponteiro deve ser um ponteiro para char e deve haver espaço suficiente para todos os caracteres na cadeia, além de um byte nulo de terminação. O salto normal do principal espaço branco é suprimido. A string deve ser composta de caracteres (ou não) em um conjunto específico; o conjunto é definido pelos caracteres entre o caractere de colchete de abertura [caractere e colchete de fechamento]. O conjunto exclui esses caracteres se o primeiro caractere após o colchete for um circunflexo (^). Para include um colchete de fechamento no conjunto, torne-o o primeiro caractere após o colchete aberto ou circunflexo; qualquer outra posição terminará o conjunto. O hífen – também é especial; quando colocado entre dois outros personagens, adiciona todos os caracteres intervenientes ao conjunto. Para include um hífen, torne-o o último caractere antes do colchete final. Por exemplo, [^] 0-9-] significa que o conjunto “tudo, exceto colchete, zero a nove e hífen”. A sequência termina com a aparência de um caractere que não está no conjunto (ou, com um circunflexo, em) ou quando a largura do campo se esgota.

TAMBÉM: Para ler uma string:

 scanf("%[^\n]\n", a); 

// significa ler até encontrar ‘\ n’ e, em seguida, eliminar o lixo ‘\ n’

🙂

Apenas use um getchar () após a function scanf ().

Apenas adicionando um pouco mais acima para responder- Se queremos remover algum padrão específico, suponha números 0-9, a partir do stream de input, então teremos que usar getchar () para o buffer de liberação.

 scanf("%[^0-9\n]", str1); while(getchar() != '\n'); // this approach is much better bcz it will // remove any number of left characters in buffer. scanf("%c", &ch); 

Então, aqui, se você passar ashish019, então apenas ashish será copiado para str e 019 será deixado no buffer, para que você precise de getchar () várias vezes.

use fflush(stdin) para limpar o buffer de input depois de ler cada input.