Ler uma linha usando scanf () não é bom?

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

Um amigo meu sugeriu que usar fgets() para ler uma linha como input seria uma idéia muito melhor do que usar scanf() como na instrução acima. Ele é justificado?

char * fgets ( char * str, int num, FILE * stream ); é seguro usar porque evita o problema de estouro de buffer , ele varre apenas num-1 número de char.

Lê caracteres do stream e os armazena como uma string C em str até que os caracteres (num-1) sejam lidos ou seja uma nova linha ou o fim do arquivo, o que ocorrer primeiro.

aqui o segundo argumento num é o número máximo de caracteres a serem copiados em str (incluindo o caractere nulo de terminação).

Por exemplo, suponha que em seu código uma capacidade de array de string tenha apenas 5 caracteres como abaixo.

  char str[5]; fgets (str, 5, fp); //5 =you have provision to avoid buffer overrun 

Usando o código acima, se a input de fp for maior que 4 chars, fgets() lerá apenas os primeiros 4 caracteres e depois adicionará \0 ( , e descarta outros caracteres de input extras, apenas armazena cinco caracteres em str[] ).

Considerando scanf(" %[^\n]",str); irá ler até que \n não seja encontrado e se a string de input for maior que 4 chars scanf() causará estouro de buffer (como scanf tentará acessar a memory além do índice max 4 em str[] ).

C FAQ tem algumas explicações detalhadas sobre o problema do scanf :

Mais geralmente, o scanf é projetado para input formatada e relativamente estruturada (seu nome é, na verdade, derivado de “formatado por varredura”). Se você prestar atenção, ele lhe dirá se foi bem-sucedido ou falhou, mas pode dizer apenas onde ele falhou, e não como ou por quê. Você tem muito pouca oportunidade de fazer qualquer recuperação de erro.

veja aqui para detalhes.

fgets será melhor que este scanf . Pode haver problemas a seguir com o scanf conforme fornecido no OP

1) estouro de buffer como sugerido por @Grijesh

2) possivelmente o próximo scanf depois disso não funcionará porque a nova linha é deixada no stream de input (se você perder um espaço em branco)

Simplificando: sim, o fgets é uma escolha melhor.

Eu olhei para o seu especificador de formato scanf e fiquei perplexa. Compreender exatamente o que faz requer algum tempo lendo as man pages.

Além disso, seu código scanf é suscetível a saturações de buffer.

Mantenha-o simples e você reduzirá os custos de manutenção e evitará erros difíceis de encontrar!

Sim fgets é a maneira melhor e segura de ler uma linha a partir da input padrão.

Além disso, haverá mais legibilidade no código. Olhe para a declaração scanf dada por você.

Qualquer segunda pessoa que a vir será totalmente confusa. Mas enquanto haverá mais facilidade de leitura para os fgets e é fácil de entender.

não use fgets (…) use o seguinte trecho:

 char _x[7000]; char* y; while ( ! feof (_f) ) { fscanf(_f,"%[^\n]\n",_x); y=x; }