Ответ 1
Хотя это выглядит как естественное решение, я обычно советю использовать fscanf()
для потенциально искаженного ввода.
В функции есть несколько проблем, среди которых:
- Невозможность восстановления из-за ошибки из-за ошибки (меньше
ftell()
/fseek()
), потому что вы не знаете, где именно он остановил синтаксический анализ. - Легкость, с которой она приводит к использованию неинициализированных значений (если формат не соответствует вводу, и вы не правильно проверяли код возврата).
- Некоторые угловые случаи, когда
fscanf()
дросселируют на входе, гдеatoi()
/strtol()
не ( "0xz" ...).
Все это отбрасывает fscanf()
для чтения только форматированного ввода, т.е. того, что ваша собственная программа написала ранее в известном формате.
Для любого типа ввода, который может отсутствовать в ожидаемом формате, Я рекомендую читать строку за раз (fgets()
) и анализировать ее в памяти, например, с помощью strtol()
:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define LINE_BUFFER_SIZE 256;
// ...
char line[ LINE_BUFFER_SIZE ];
fgets( line, LINE_BUFFER_SIZE, fp );
char * scanptr;
errno = 0;
long number = strtol( line, &scanptr, 0 );
if ( scanptr == line )
{
// not a number...
}
-
scanptr
теперь указывает на то, где закончилось парсинг чисел. -
number
содержит число проанализированных, 0, если строка не начиналась с числа, аLONG_MAX
соответственно.LONG_MIN
, если найденное число вне диапазонаlong
(и в этом случаеerrno == ERANGE
).
Я не знаю ваших точных требований, поэтому я не могу дать хороший пример, что делать, если вы не найдете номер или что делать с текстом. Но так как вы получили строку (или, первые LINE_BUFFER_SIZE
символы более длинной строки...) в памяти, у вас есть весь диапазон строки функции в вашем распоряжении. strpbrk( line, "0123456789" )
можно использовать для сканирования следующей цифры или strpbrk( line, "+-0123456789" )
, если у вас может быть +-
на вашем входе...