fscanf()只拾取第一行文件

时间:2011-06-01 14:51:48

标签: c text-files scanf

我有一个制表符分隔文件,我试图将其转换为制表符分隔文件。我正在使用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 个答案:

答案 0 :(得分:3)

首选fgets()阅读输入并解析程序中的行,例如sscanf()strtok()

众所周知,

fscanf很难使用 您的fscanf在第一行之后没有执行任何转换 它读取的字符最多为 TAB ,然后忽略 TAB ,并读取更多字符直到下一个 TAB 。在循环的第二次,sku没有数据:第一个字符是 TAB

尽管检查返回值。它有很大的帮助。

chk = fscanf(stream, "%[^\t]\t%[^\t]", sku, fnsku);
/* 2 conversions: sku and fnsku */
if (chk != 2) {
    /* something went wrong */
}

答案 1 :(得分:1)

您正在阅读

   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'终止,则应使用以下格式字符串:{ {1}}。

虽然我们没有得到文件的确切格式,但很难回答。该文件是否只包含一行,其中的字段与选项卡分开?或者有多行,每行包含制表符分隔的字段。如果后者为真,那么最好立即扫描整行,然后在内部进行解析。

答案 2 :(得分:0)

好的,这是实际发生的事情。您正在阅读第一行,从那时起,您不会阅读任何内容,只是重复使用这些值。您应检查fscanf的返回值,如果小于2,则退出循环(在第一次迭代后将循环)。您的fscanf行应如下所示:

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

关键是最后的换行符,它将在输入中使用换行符。

您的printf也存在一些问题。 (格式化字符串的数量不正确。)我会把它留给你。