我有一个制表符分隔文件,我试图将其转换为制表符分隔文件。我正在使用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);
}
}
答案 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也存在一些问题。 (格式化字符串的数量不正确。)我会把它留给你。