fscanf настройки парсинга в файле

Добрый день всем у меня вопрос..

Как заставить fscanf прочитать весь файл целиком?

Допустим у меня есть файлы settings.txt

setting1 = 1
setting2 = 2
setting3 = 3

Как мне разобрать их в переменные программирования C?

int setting1, setting2,setting3;

Я попытался просто сделать это:

fscanf(fp, "setting2 = %d\n", &setting2);

но он не может получить значение из файла, пока это работает:

fscanf(fp, "setting1 = %d\n", &setting1);

Есть ли правильный способ чтения всего файла?


person Jomar Sevillejo    schedule 19.08.2013    source источник


Ответы (4)


Во-первых, в fscanf() нет ничего плохого. Первое, что вы должны знать, это то, что fscanf обрабатывает символы новой строки как пробелы. Таким образом, даже если вы смотрите на файл как на отдельные строки, fscanf видит его как:

  setting1 = 1  setting2 = 2  setting3 = 3

Это НЕ проблема, но это влияет на то, как вы могли бы написать код fscanf для чтения этой текстовой строки. Этот следующий простой подход слишком прост?!

  fscanf(fp, " setting1 = %d", &setting1);
  fscanf(fp, " setting2 = %d", &setting2);
  fscanf(fp, " setting3 = %d", &setting3);

Примечание. В форматах для fscanf есть начальный пробел. Это делается для того, чтобы сканер не мог найти ни одного, одного или нескольких пробельных символов. Если в строках текстового файла есть начальные пробелы, совпадение НЕ будет найдено, если только этот начальный пробел не указан в формате. Это имеет смысл, потому что в начале строки может быть несколько пробелов.

Открытие файла с чтением и добавлением также работает, если fscanf закодирован правильно.

Заставьте это работать. Теперь, есть ли в файле больше, чем три настройки? Если это так, то ваш код fscanf должен быть более сложным, а может и нет. Помните, что идея состоит в том, чтобы читать данные, если ваш код читает данные, то все готово.

Ради интереса я попробовал следующие fscanfs:

fscanf(fp, " setting1 = %i ", &setting1);
fscanf(fp, "setting2 = %i ", &setting2);
fscanf(fp, "setting3 = %i", &setting3); 

Обратите внимание, что «странно расположенные пробелы в определении формата позволяют использовать один или несколько пробелов между каждым из ключевых слов.

И последний комментарий. Ваш код должен учитывать, что ключевое слово может быть написано пользователем с ошибкой, и в этом случае fscanf не работает. Таким образом, всегда сохраняйте или проверяйте возвращаемое значение из fscanf:

   int x;

   x = fscanf(fp, " setting1 = %d", &setting1);

   if (x == 0) { // keyword setting1 was misspelled...

И по мелочам дня:

  x = fscanf(fp, " s e t t i n g 1 = %d", &setting1);  // also works
person Community    schedule 19.08.2013
comment
Я думал, что это решит эту проблему, но все же он читает только первую строку. Я даже попробовал тест siplier, отсканировал Jake123 с Джейком% d и смог получить 123. Затем я добавил asd к предыдущей строке, в которой был Джейк. (Это делает Джейка второй строкой). когда я побежал, он больше не смог его найти. :\ - person Jomar Sevillejo; 20.08.2013
comment
Я сделал еще один тест со строкой. У меня есть JakeSold в settings.txt (первая строка и только одна строка), затем я отсканировал его с помощью Jake%s, он может быть продан, но когда я добавил пробел между Jake и Sold, это делает его Jake Sold. Больше не написано "Продано". Как сделать так, чтобы он включал пробелы? поскольку fscanf останавливается на пробелах, я не понимаю, почему.. - person Jomar Sevillejo; 20.08.2013
comment
В настоящее время я открываю файл с флагом a+ fopen. в режиме чтения и добавления.. Имеет ли это значение? - person Jomar Sevillejo; 20.08.2013
comment
@user2128576 user2128576, в принципе, я думаю, что да. Режим добавления помещает файл ptr в конец файла. Попробуйте, как только что прочитали и дайте мне знать. - person JackCColeman; 20.08.2013

Как насчет чтения каждой строки с помощью fgets() и анализа их содержимого с помощью sscanf(), как в этом примере: https://stackoverflow.com/a/861822/1150918 ? :)

Кроме того, лично для таких конфигураций я бы предпочел Lua или что-то маленькое и простое в этом роде. Встроенная проверка синтаксиса, C API и небольшой размер интерпретатора.

person Kamiccolo    schedule 19.08.2013
comment
Спасибо, но проблема с fgets в том, что вам нужно указать размер переменной, которая ее содержит, и я не знаю, насколько она будет велика... настройки могут быть очень длинными числами. - person Jomar Sevillejo; 20.08.2013

Вы хотите что-то вроде этого:

int setting[3], i;
for(i = 0; i < 3; ++i)
    fscanf(fp, "setting%*d = %d\n", &setting[i]);
person Paul Evans    schedule 19.08.2013

лучший подход — отделить файловый ввод-вывод от синтаксического анализа и обрабатывать их отдельные потенциальные ошибки. IOWs: избегать fscanf().

void Parse(FILE *fp, int NN) {
  char buf[100];
  int setting[NN];
  int i;
  for (i = 0; i < NN; i++) {
    if (fgets(buf, sizeof(buf), fp) == NULL ) {
      ;  // Handle unexpected I/O error
    }
    int n, count;
    unsigned u;
    count = sscanf(buf, "setting%u = %d", &u, &n);
    // Qualify the parse
    if ((count != 2) && (u <= 0) && (u > NN)) {
      ;  // Handle parse I/O error
    }
    setting[u - 1] = n;
  }
}
person chux - Reinstate Monica    schedule 19.08.2013