Я действительно новичок в обработке файлов на C, и я хотел бы задать несколько вопросов!
В частности, я не уверен, будут ли fscanf() и fgets() автоматически увеличивать указатель файла по строкам. Из того, что я понимаю при тестировании и документации, fscanf() только перемещает указатель файла на 1 символ/тип за раз; но fgets(), кажется, читает файл строки за строкой (поскольку он завершается, когда встречается с символом новой строки). И из документации fscanf() будет игнорировать любые пробельные символы. Это значит, что даже если у меня есть файл с линейным вводом, fscanf не сможет прочитать его по строкам? Даже если я укажу точное форматирование, символ новой строки не сохранится?
В частности, если одна строка содержит 10 не-пробельных частей (слово, целое число, двойное и т.д.), Но я указываю только 3 из них для чтения в переменных (используя% * или просто ничего не ставьте), что эти читать функции?
Например, мой входной файл выглядит так:
9 opls_182 9 DNP CT 9 0.140 12.0110
10 opls_182 10 DNP CT 10 0.140 12.0110
11 opls_145 11 DNP CA 11 -0.115 12.0110
12 opls_145 12 DNP CA 12 -0.115 12.0110
Я просто хочу прочитать opls_182 и CT и 9 часть (2-й, 5-й и 6-й столбцы). С fgets() и sscanf() я бы написал так:
fgets(fp,500,buffer);
sscanf(buffer, "%*s %s %*d %*s %s %d %*f %*f", variables);
or this:
sscanf(buffer, "%*s %s %*d %*s %s %d %*s", variables);
or this:
sscanf(buffer, "%*s %s %*d %*s %s %d", variables);
Будут ли эти три функции работать одинаково? Итак, во второй версии, последний% * s проанализирует все последние два столбца или просто второй последний? (% s, кажется, начинается от небелого символа пробела до небелого символа пробела).
Что делать, если у меня больше спецификатора, чем в каждой части? Будет ли ошибка, или дополнительная переменная останется 0/пустой?
И если я использовал fscanf(), только первая версия будет работать правильно, а 2-я и 3-я версии испортят чтение, так как fscanf() не автоматически переводит строку, не так ли?
Все спецификаторы формата в функциях scanf будут игнорировать символы пробелов. Однако, если я хочу пропустить первую часть ([bond]) и прочитать последнее целое число, есть ли способ сделать что-то вроде% * some_format% d (игнорируя, пока не найдет целое число)? Будет ли работать% [^ format]? Я пробовал% [^% d] или% [^ d], либо просто остановится на символе "d" и даст "[bon". Я знаю, что вы можете указать количество символов, которое должно быть исключено с помощью% [^], однако, если число меняется в файле, этот метод не может быть использован.
Я обнаружил, что функция чтения/записи в C очень мощная, но также сложно сделать все правильно. Спасибо вам, ребята!
Правило очень просто: fgets()
читает целую строку, если длина строки не превышает предоставленный буфер, и в этом случае она читает столько, сколько может. fscanf()
, с другой стороны, читает то, что вы ему рассказываете, пропуская предыдущие пробелы. Например, если строка "1 2 3"
(без кавычек), fgets()
будет читать всю строку, а fscanf(fp, "%d %d", &i1, &i2)
будет читать два целых числа и хранить их в предоставленные адреса, и оставить " 3"
(примечание включено пробелы) непрочитанным.
Во втором вызове sscanf()
последний %*s
анализирует только второй-последний столбец. Используйте что-то вроде %*[^\n]
если вы хотите пропустить все до конца строки. Вы правы, что если вы использовали fscanf
, только первая версия будет делать то, что вы хотите, поскольку fscanf()
рассматривает новую fscanf()
как просто еще одно пробельное fscanf()
. Тем не менее, вы можете исправить fscanf()
используя спецификатор формата %*[^\n]
.
Нет никакого способа для scanf
"искать" для ввода, он должен всегда анализировать его в соответствии с указанным форматом. Нет формата, эквивалентного регулярному выражению. .*
.
Ваш вызов scanf
не будет делать то, что вы хотите, потому что первый экземпляр %s
будет использовать оставшуюся строку, поэтому будут обрабатываться только два символа формата. Однако, если вы замените %s
%[^0-9]
, он будет делать именно то, что вы хотите (для этого ввода).
[ ]
содержимого, связанного с, -
определяется реализацией.
fscanf
для чего-либо серьезного, вероятно, не очень хорошая идея. Например, использование%d
или%f
приводит к неопределенному поведению для определенных входных файлов, и вы не хотите ситуации, когда ваша программа может быть повреждена из-за тщательно созданного ввода.