fscanf () забирает только первую строку файла - PullRequest
2 голосов
/ 01 июня 2011

У меня есть файл с разделителями табуляции, который я пытаюсь преобразовать в файл с разделителями табуляции.Я использую C. Я пытаюсь прочитать вторую строку файла.Теперь у меня просто десятки тысяч строк, повторяющих первую строку.

#include <stdio.h>
#include <string.h>
#define SELLERCODE  A2LQ9QFN82X636

int main ()
{
     typedef char* string;
     FILE* stream;
     FILE* output;
     string asin[200];
     string sku[15];
     string fnsku[15];
     int quality = 0;

     stream = fopen("c:\\out\\a.txt", "r");
     output = fopen("c:\\out\\output.txt", "w");

     if (stream == NULL)
     { 
         perror("open");
         return 0;
      }

     for(;;)
     {
       fscanf(stream, "%[^\t]\t%[^\t]", sku, fnsku);
       printf("%s\t%s\n",  sku, fnsku);
       fprintf(output, "%s\t%s\t%\t%s\t%s\t%i\n", sku, fnsku, asin, quality);
     }

}

Ответы [ 3 ]

3 голосов
/ 01 июня 2011

Предпочитают fgets() читать входные данные и анализировать строки в вашей программе, используя, например, sscanf() или strtok().

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

Do , однако проверьте возвращаемое значение .Это очень помогает.

chk = fscanf(stream, "%[^\t]\t%[^\t]", sku, fnsku);
/* 2 conversions: sku and fnsku */
if (chk != 2) {
    /* something went wrong */
}
1 голос
/ 01 июня 2011

Вы читаете с

   fscanf(stream, "%[^\t]\t%[^\t]", sku, fnsku);

После прочтения первой строки, которая должна заканчиваться символом табуляции (как в "%[^\t]\t%[^\t]").Входной буфер имеет последний символ табуляции '\ t', который не читается приведенным выше вызовом функции.Таким образом, в следующей итерации он будет прочитан в начале с вашей строкой формата.Но fcanf в следующей итерации сразу же возвращается, так как он встретил символ табуляции '\ t' в самом начале ("%[^\t]"), поэтому буферы все еще имеют значение последнего считанного значения.Отныне каждая итерация пытается прочитать файл с fscanf, но терпит неудачу каждый раз, когда сталкивается с '\t' в самом начале.Таким образом, вы не продолжаете чтение файла, и первые значения чтения из ваших программных буферов показываются и включаются.

Вам необходимо прочитать последний символ, который завершил сопоставление набора сканирования.Вы можете либо использовать fgetc (stream) после вызова fscanf (), либо использовать следующую строку формата: "%[^\t]\t%[^\t]%*c".%*c - это синтаксис подавления присваивания.Это сделает один символ прочитанным из входного файла, но затем отбросит его.

Также вы должны проверить, что возвращает fscanf ().Если он не возвращает 2 (количество элементов для чтения), то есть проблема, которую вы должны решить.Таким образом, вы можете убедиться, что правильное количество элементов было прочитано за один вызов.

Так что вы можете сделать:

 while (!feof (stream))
 {
   fscanf(stream, "%[^\t]\t%[^\t]", sku, fnsku);
   fgetc (stream);
   printf("%s\t%s\n",  sku, fnsku);
   fprintf(output, "%s\t%s\t%\t%s\t%s\t%i\n", sku, fnsku, asin, quality);
 }

Или вы можете сделать:

 while (!feof (stream))
 {
   fscanf(stream, "%[^\t]\t%[^\t]%*c", sku, fnsku);
   printf("%s\t%s\n",  sku, fnsku);
   fprintf(output, "%s\t%s\t%\t%s\t%s\t%i\n", sku, fnsku, asin, quality);
 }

Но я рекомендую прочитать его с помощью fgets (), а затем проанализировать его внутри вашей программы с помощью strtok () или другими способами и способами.

EDIT1:

Примечаниечто если исходный файл заканчивается на '\n', то после прочтения строк, как указано выше, в ваши буферы будет добавлен дополнительный символ новой строки.Если вы по-прежнему рассматриваете возможность непосредственного чтения полей с fscanf (), где каждая строка имеет несколько полей, разделенных с '\t', а запись заканчивается '\n', тогда вам следует использовать следующую строку формата: "%[^\t]\t%[^\t]\n".

Трудно ответить, пока мы не получаем точный формат файла.Содержит ли файл только одну строку с полями, разделенными вкладками?Или есть несколько строк, каждая строка имеет разделенные табуляцией поля.Если последнее верно, лучше всего отсканировать всю строку сразу, а затем выполнить внутренний анализ.

0 голосов
/ 01 июня 2011

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

if( fscanf(stream, "%[^\t]\t%[^\t]\n", sku, fnsku) < 2 ) break;

Ключ - это новая строка в конце, которая будет использовать новую строку во вводе.

Есть некоторые проблемы с вашим printfтакже.(Неверное количество строк форматирования.) Я оставлю это вам.

...