C использует fread для чтения неизвестного количества данных

У меня есть текстовый файл с именем test.txt

Внутри него будет номер, он может быть таким:

1
2391
32131231
3123121412

То есть это может быть любой размер числа, от 1 цифры до x цифр.

В файле будет только 1 вещь - этот номер. Я хочу немного кода, использующего fread, который будет считывать это количество байтов из файла и помещать его в переменную соответствующего размера.

Может ли кто-нибудь предложить лучший способ решить эту проблему?


person RenegadeAndy    schedule 11.12.2011    source источник
comment
это одно число или список чисел переменного размера?   -  person havexz    schedule 11.12.2011
comment
Если вы действительно должны использовать fread, объясните, почему.   -  person Zan Lynx    schedule 29.02.2012


Ответы (4)


Вы можете просто использовать:

char buffer[4096];
size_t nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp);

if (nbytes == 0)
    ...EOF or other error...
else
    ...process nbytes of data...

Или, другими словами, предоставьте себе пространство данных, достаточно большое для любых допустимых данных, а затем запишите, сколько данных было фактически прочитано в строку. Обратите внимание, что строка не будет заканчиваться нулем, если только buffer не содержит все нули перед fread() или файл не содержит нулевой байт. Вы не можете полагаться на то, что локальная переменная будет обнулена перед использованием.

Непонятно, как вы хотите создать «переменную подходящего размера». Вы можете в конечном итоге использовать динамическое выделение памяти (malloc()), чтобы предоставить правильный объем пространства, а затем вернуть этот выделенный указатель из функции. Не забудьте проверить возврат null (недостаточно памяти) перед его использованием.

person Jonathan Leffler    schedule 11.12.2011
comment
Будет ли это резервировать 4096 байтов пространства, даже если я использую, скажем, только 4 байта... или этого не произойдет?! - person RenegadeAndy; 11.12.2011
comment
Да - это резервирует 4096 байт. Если вам нужно узнать размер файла перед его чтением, вы можете использовать fstat(fileno(fp)) или поиграть с fseek() и ftell(), чтобы узнать, насколько велик файл. Но помните, что длина файла может измениться между временем тестирования и временем чтения. - person Jonathan Leffler; 11.12.2011
comment
Что ж, если память плотная, то резервирование действительно тяжелое, на самом деле почти наверняка я не смогу эффективно сделать это с помощью этого метода. - person RenegadeAndy; 11.12.2011
comment
Итак, используйте 16 вместо 4096; или 32, или любой другой размер, который больше, чем наибольшее количество цифр, с которым вы собираетесь иметь дело. - person Jonathan Leffler; 11.12.2011
comment
(Примечание: функция fstat() принимает два аргумента: она должна быть больше похожа на: struct stat sb; fstat(fileno(fp), &sb));, но вы также должны проверить результат fstat(). Она не должна давать сбоев, но известны и более забавные вещи. - person Jonathan Leffler; 11.12.2011

Один из способов добиться этого — использовать fseek, чтобы переместить местоположение файлового потока в конец файла:

fseek(file, SEEK_END, SEEK_SET);

а затем с помощью ftell получить позицию курсора в файле — это возвращает позицию в байтах, поэтому вы можете использовать это значение для выделения подходящего большого буфера, а затем прочитать файл в этот буфер.

Я видел предупреждения о том, что это не всегда может быть точным на 100%, но я использовал его в нескольких случаях без проблем — я думаю, что проблемы могут зависеть от конкретных реализаций функций на определенных платформах.

person Matt Lacey    schedule 11.12.2011
comment
Я попробую это завтра и посмотрю, сработает ли это, это C на встроенном устройстве, так что кто знает! - person RenegadeAndy; 11.12.2011
comment
Почти уверен, что некоторое время назад я использовал эту технику на Nintendo DS, и там она работала — очевидно, не совсем то же самое, но это может быть то, что вам нужно. - person Matt Lacey; 11.12.2011

Если вы хотите избежать избыточного чтения, fread не подходит. Вы, вероятно, хотите fscanf со спецификатором преобразования в строках %100[0123456789]...

person R.. GitHub STOP HELPING ICE    schedule 11.12.2011

В зависимости от того, насколько умным вам нужно быть с преобразованием чисел... Если вам не нужно быть особенно умным и быстрым, вы можете прочитать его символ в типе с getc. Итак, начнем с переменной, инициализированной 0. Прочитайте символ, умножьте переменную на 10 и добавьте новую цифру. Затем повторяйте до тех пор, пока не закончите. Получите переменную большего размера по мере необходимости или начните с переменной самого большого размера, а затем скопируйте ее в наименьший размер, который подходит после того, как вы закончите.

person Zan Lynx    schedule 29.02.2012