чтение файлов: как указатель файла перемещается с помощью fscanf и как scanf / fscanf работает с отсутствующим типом%

0

Я действительно новичок в обработке файлов на C, и я хотел бы задать несколько вопросов!

  1. Я использую fscanf/fget для преобразования файлов в разные форматы. Однако я не очень понимаю разницу между fscanf и fgets.

В частности, я не уверен, будут ли fscanf() и fgets() автоматически увеличивать указатель файла по строкам. Из того, что я понимаю при тестировании и документации, fscanf() только перемещает указатель файла на 1 символ/тип за раз; но fgets(), кажется, читает файл строки за строкой (поскольку он завершается, когда встречается с символом новой строки). И из документации fscanf() будет игнорировать любые пробельные символы. Это значит, что даже если у меня есть файл с линейным вводом, fscanf не сможет прочитать его по строкам? Даже если я укажу точное форматирование, символ новой строки не сохранится?

  1. Со всеми fscanf/scanf()/sscanf() я не уверен, как строки разбираются.

В частности, если одна строка содержит 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() не автоматически переводит строку, не так ли?

  1. Этот вопрос относится к линии шаблонов: [облигации] 387

Все спецификаторы формата в функциях scanf будут игнорировать символы пробелов. Однако, если я хочу пропустить первую часть ([bond]) и прочитать последнее целое число, есть ли способ сделать что-то вроде% * some_format% d (игнорируя, пока не найдет целое число)? Будет ли работать% [^ format]? Я пробовал% [^% d] или% [^ d], либо просто остановится на символе "d" и даст "[bon". Я знаю, что вы можете указать количество символов, которое должно быть исключено с помощью% [^], однако, если число меняется в файле, этот метод не может быть использован.

  1. Будет ли scanf иметь возможность различать разные форматы, если все части соединены вместе без пробелов. пример: 9opls_182DNPCT91.40STUI8. Может ли шаблон% d% s% d% s% f% s% d зачитывать: 9, opls_, 182, DNPCT, 91.40, STUI, 8?

Я обнаружил, что функция чтения/записи в C очень мощная, но также сложно сделать все правильно. Спасибо вам, ребята!

  • 2
    обратите внимание, что этот вопрос не имеет ничего общего с C ++.
  • 0
    Использование fscanf для чего-либо серьезного, вероятно, не очень хорошая идея. Например, использование %d или %f приводит к неопределенному поведению для определенных входных файлов, и вы не хотите ситуации, когда ваша программа может быть повреждена из-за тщательно созданного ввода.
Теги:
string
pointers

1 ответ

0
Лучший ответ
  1. Правило очень просто: fgets() читает целую строку, если длина строки не превышает предоставленный буфер, и в этом случае она читает столько, сколько может. fscanf(), с другой стороны, читает то, что вы ему рассказываете, пропуская предыдущие пробелы. Например, если строка "1 2 3" (без кавычек), fgets() будет читать всю строку, а fscanf(fp, "%d %d", &i1, &i2) будет читать два целых числа и хранить их в предоставленные адреса, и оставить " 3" (примечание включено пробелы) непрочитанным.

  2. Во втором вызове sscanf() последний %*s анализирует только второй-последний столбец. Используйте что-то вроде %*[^\n] если вы хотите пропустить все до конца строки. Вы правы, что если вы использовали fscanf, только первая версия будет делать то, что вы хотите, поскольку fscanf() рассматривает новую fscanf() как просто еще одно пробельное fscanf(). Тем не менее, вы можете исправить fscanf() используя спецификатор формата %*[^\n].

  3. Нет никакого способа для scanf "искать" для ввода, он должен всегда анализировать его в соответствии с указанным форматом. Нет формата, эквивалентного регулярному выражению. .*.

  4. Ваш вызов scanf не будет делать то, что вы хотите, потому что первый экземпляр %s будет использовать оставшуюся строку, поэтому будут обрабатываться только два символа формата. Однако, если вы замените %s %[^0-9], он будет делать именно то, что вы хотите (для этого ввода).

  • 0
    Поведение любого [ ] содержимого, связанного с, - определяется реализацией.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню