Я читаю из текстового файла, который содержит 3 столбца (идентификатор координаты, шнур x и шнур y). Все значения разделены табуляцией (\ t). Когда я пытаюсь использовать fscanf () для создания списка, он не печатает мою 1-ю строку и распечатывает последнюю строку 2 раза.
while ((fgets(buffer, BUFFER_SIZE, fptr)) != NULL)
{
fscanf(fptr,"%d%f%f", &id, &xc, &yc);
tempValue.xyID = id;
tempValue.x = xc;
tempValue.y = yc;
addToList(nodeID++, tempValue);
}
printList();
Приведенный выше код не работает со scanf, но когда я это сделаю:
while ((fgets(buffer, BUFFER_SIZE, fptr)) != NULL)
{
tempValue.xyID = atoi(strtok(buffer,"\t"));
tempValue.x = atoi(strtok(NULL, "\t"));
tempValue.y = atoi(strtok(NULL, "\t"));
addToList(nodeID++, tempValue);
}
printList();
Приведенный выше код работает отлично, и я хочу знать, что я делаю не так с fscanf. Спасибо!
fscanf (fptr, "% d \ t% f \ t% f", & id, & xc, & yc); , попробовал это то же самое: /
Пожалуйста, предоставьте правильный минимальный воспроизводимый пример, включая а) введенные вами данные, б) полученные вами выходные данные и определение id
, xc
, yc
а такжеtempValue
.
Если вы используете fgets()
для чтения строки из файла в память, вам нужно использовать sscanf(buffer, ...)
для сканирования этой строки. Если вы вызываете fscanf(fptr, ...)
, вы в основном отбрасываете только что прочитанную строку и читаете следующий бит данных из файла.
Причина, по которой вы видите последнюю строку дважды, скорее всего, вызвана тем, что fscanf()
был вызван, когда вы уже достигли конца файла. Если он не может прочитать какие-либо данные, переменные, которые вы передаете в fscanf()
, не будут перезаписаны. Вы не проверяете возвращаемое значение fscanf()
, чтобы убедиться, что вы действительно читаете новые данные, вместо этого вы всегда вызываете addToList()
, который затем добавит элемент в список, используя значения, сохраненные предыдущим вызовом fscanf()
.
Вторая попытка работает, потому что теперь вы фактически анализируете данные, которые считываете в буфер. Обратите внимание, что вы снова не проверяете все возвращаемые значения функций, которые вы вызываете, на наличие ошибок. Если вы попытаетесь прочитать файл, содержащий строку с менее чем тремя элементами, тогда ваша вторая версия выйдет из строя, потому что strtok()
вернет NULL
, и тогда вы фактически вызовете atoi(NULL)
. Кроме того, atoi()
молча игнорирует любые ошибки, например, когда строка, которую он пытается проанализировать, не содержит допустимого числа, и вместо этого возвращает 0. Лучше использовать strtol()
, если вы хотите быть уверены, что вы правильно проанализировали значение. .
Спасибо за хороший ответ. Но почему он по-прежнему печатает последнюю строку 2 раза?
Если fscanf()
вызывается, но не может прочитать данные, он вернет значение ошибки, но не изменит переменные, которые вы пытаетесь прочитать. Вы проигнорировали возвращаемое значение и просто печатаете значения из предыдущего вызова fscanf()
.
Я заменил fscanf на sscanf, как вы сказали. Я больше не использую fscanf в программе
Большой. Убедитесь, что вы также проверили возвращаемое значение sscanf()
!
Вы забыли разделитель
\t
в вызове fscanf ...