scanf(" %[^\n]",line);
Один мой друг предположил, что использование fgets()
для чтения строки в качестве входного сигнала было бы гораздо лучшей идеей, чем использование scanf()
, как в приведенном выше утверждении. Он оправдан?
scanf(" %[^\n]",line);
Один мой друг предположил, что использование fgets()
для чтения строки в качестве входного сигнала было бы гораздо лучшей идеей, чем использование scanf()
, как в приведенном выше утверждении. Он оправдан?
char * fgets ( char * str, int num, FILE * stream );
безопасен в использовании, поскольку он избегает проблемы с переполнением буфера , он сканирует только num-1
число char.
Считывает символы из потока и сохраняет их как строку C в str до тех пор, пока не будут прочитаны (num-1) символы или не будет достигнута новая строка или конечный файл, в зависимости от того, что произойдет раньше.
здесь второй аргумент num
- максимальное количество символов, подлежащих копированию на str (включая завершающий нуль-символ).
Например, предположим, что в вашем коде размер массива строк равен 5
символам, как показано ниже.
char str[5];
fgets (str, 5, fp); //5 =you have provision to avoid buffer overrun
Используя вышеприведенный код, если ввод из fp
длиннее, чем 4
символов, fgets()
будет читать только первые 4
символы, а затем добавляет \0
(и отбрасывает другие дополнительные входные символы, просто сохраняет пять char в str[]
).
В то время как scanf(" %[^\n]",str);
будет читать до тех пор, пока \n
не будет найден, и если длина ввода будет длиннее, то 4
chars scanf()
вызовет переполнение буфера (as scanf
попытается получить доступ к памяти за пределами максимального индекса 4
в str[]
).
C FAQ содержит подробное объяснение проблемы scanf
:
В более общем плане
scanf
предназначен для относительно структурированного отформатированного ввода (его имя фактически получено из "отформатированного сканирования" ). Если вы обратите внимание, он скажет вам, удалось ли это или не удалось, но он может сказать вам только примерно, где это не удалось, и совсем не так, как и почему. У вас очень мало возможностей для восстановления любой ошибки.
см. здесь для подробностей.
fgets
будет лучше, чем этот scanf
.
Возможны следующие проблемы с scanf
, как указано в OP
1) переполнение буфера, предложенное @Grijesh
2) возможно следующий scanf
после этого не будет работать, потому что новая строка оставлена во входном потоке (если вы пропустили пробел)
Да fgets - лучший и безопасный способ чтения строки со стандартного ввода.
Кроме того, в коде будет больше читаемости. Посмотрите на инструкцию scanf, предоставленную вами.
Любой второй человек, который его видит, будет полностью запутан. Но в то время как для fgets будет больше readeablity, и это легко понять.
Проще говоря: да, fgets
- лучший выбор.
Я посмотрел на ваш спецификатор формата scanf
, и я был озадачен. Понимая, что именно он делает, требуется некоторое время, просматривая страницы man
.
Кроме того, ваш код scanf
восприимчив к переполнениям буфера.
Держите его простым, и вы уменьшите затраты на обслуживание и избегаете поиска ошибок!
не используйте fgets (...) вместо этого следующий фрагмент:
char _x[7000];
char* y;
while ( ! feof (_f) )
{
fscanf(_f,"%[^\n]\n",_x);
y=x;
}