使用 fscanf 扫描文件后结果不正确
Incorrect results after scanning a file using fscanf
我在使用 fscanf
.
扫描 .txt
文件中的一些数据时遇到问题
示例:
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
typedef struct
{
char code[12];
char from[45];
char to[45];
int day;
int month;
int year;
int hour;
int min;
float km;
float price;
}Taxi;
while(fscanf(fin, "%[^ \n]%[^-]-%[^;]; %d.%d.", taxi[i].code, taxi[i].from, taxi[i].to, &taxi[i].day, &taxi[i].month)==5)
{
printf("|%s| |%s| |%s| |%d| ", taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day);
i++;
}
使用此代码,我可以 fscanf
直到我输入 &taxi[i].month
,从那里代码不起作用。我需要正确上传示例
你想要例如:
char restofline[64];
...
while(fscanf(fin, " %11[^ ]%44[^-]-%[^;]; %d.%d.%63[^\n]", taxi[i].code, taxi[i].from, taxi[i].to,
&taxi[i].day, &taxi[i].month, restofline)==6)
因为您需要刷新行的其余部分 scanf
未在您的代码中管理
注意第一个 '%' 之前的 space 绕过上一行的换行符,事实上我限制了要读取的字符串的大小而不是写出数组
例如:
#include <stdio.h>
typedef struct{
char code[12];
char from[45];
char to[45];
int day;
int month;
int year;
int hour;
int min;
float km;
float price;
}Taxi;
int main()
{
int i = 0;
Taxi taxi[10];
char restofline[64];
while(fscanf(stdin, " %11[^ ]%44[^-]-%[^;]; %d.%d.%63[^\n]", taxi[i].code, taxi[i].from, taxi[i].to,
&taxi[i].day, &taxi[i].month, restofline)==6)
{
printf("|%s| |%s| |%s| |%d| \n", taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day);
if (++i == 10)
break;
}
return 0;
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| | John March 136 | | Mary Perpetum 419| |8|
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| | John March 136 | | Mary Perpetum 419| |8|
^C
pi@raspberrypi:/tmp $
如果您想保存所有字段:
#include <stdio.h>
typedef struct{
char code[12];
char from[45];
char to[45];
int day;
int month;
int year;
int hour;
int min;
float km;
float price;
}Taxi;
int main()
{
int i = 0;
Taxi taxi[10];
while(fscanf(stdin, " %11[^ ] %44[^-]- %[^;]; %d.%d.%d.%d:%d%f%f",
taxi[i].code, taxi[i].from, taxi[i].to,
&taxi[i].day, &taxi[i].month, &taxi[i].year,
&taxi[i].hour, &taxi[i].min,
&taxi[i].km, &taxi[i].price)==10)
{
printf("|%s| |%s| |%s| |%d| %d:%d %f %f\n",
taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day,
taxi[i].hour, taxi[i].min, taxi[i].km, taxi[i].price);
if (++i == 10)
break;
}
return 0;
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| |John March 136 | |Mary Perpetum 419| |8| 5:42 3.802570 71.449997
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| |John March 136 | |Mary Perpetum 419| |8| 5:42 3.802570 71.449997
^C
pi@raspberrypi:/tmp $
请注意 space 仍然存在于第一个 '%' 之前以绕过从一行到下一行的换行符。我还加了一个flush space(s)在字段'to'的开头,但是你需要去掉字段末尾可能的space(s)[=33] =] 和 'to'
你漏掉了不想读的字符:
$ grep scanf test2.c
fscanf(stdin, "%[^ \n] %[^-] - %[^;]; %d.%d.", taxi[i].code, taxi[i].from, taxi[i].to, &taxi[i].day, &taxi[i].month);
$ echo 'CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45'|./test2
|CXKNS87356| |John March 136 | |Mary Perpetum 419| |8|
|
|和 |
|在 |-
| 之后失踪了。
示例:您的第一个匹配项是 %[^ \n]
,它排除了 space,但您没有在之后添加被排除的 space。添加 space 然后你的下一场比赛 %[^-]
就会发生。之后使用 |-
| (连字符后有 space)。
这样做的唯一缺点是约翰尾随 space。
如何区分“约翰字段”中的space是属于该字段还是分隔符?我不认为scanf解析器可以处理它。正则表达式可以。或者你修复 from
的结尾,例如:
$ grep strlen test2.c
if (taxi[i].from[strlen(taxi[i].from)-1] == ' ') taxi[i].from[strlen(taxi[i].from)-1] = 0;
$ echo 'CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45'|./test2
|CXKNS87356| |John March 136| |Mary Perpetum 419| |8|
通过这样做,您只需删除“John field”中的尾随 space。
这是我完整的 main() 方法:
int main() {
Taxi taxi[1];
int i=0;
// 'CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45'
fscanf(stdin, "%[^ \n] %[^-] - %[^;]; %d.%d.", taxi[i].code, taxi[i].from, taxi[i].to, &taxi[i].day, &taxi[i].month);
if (taxi[i].from[strlen(taxi[i].from)-1] == ' ') taxi[i].from[strlen(taxi[i].from)-1] = 0;
printf("|%s| |%s| |%s| |%d| \n", taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day);
return 0;
}
字符串
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
我只是从上面复制过来的
注意:我像您一样忽略了年份、小时等。我假设您将添加对它们的解析。
这意味着您的第一个 scanf 将解析到
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.
你的下一个循环将在
上继续解析
2014. 05:42 3.80257 71.45\n...
如果您不想解析年份和之后的所有内容,那么只需将其作为字符串解析到缓冲区中并忽略缓冲区的内容。
我假设你的解析丢失了,因为你最多解析了一个月,但只打印了一天。因此,看起来工作正在进行中,问题出在 spaces.
我在使用 fscanf
.
.txt
文件中的一些数据时遇到问题
示例:
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
typedef struct
{
char code[12];
char from[45];
char to[45];
int day;
int month;
int year;
int hour;
int min;
float km;
float price;
}Taxi;
while(fscanf(fin, "%[^ \n]%[^-]-%[^;]; %d.%d.", taxi[i].code, taxi[i].from, taxi[i].to, &taxi[i].day, &taxi[i].month)==5)
{
printf("|%s| |%s| |%s| |%d| ", taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day);
i++;
}
使用此代码,我可以 fscanf
直到我输入 &taxi[i].month
,从那里代码不起作用。我需要正确上传示例
你想要例如:
char restofline[64];
...
while(fscanf(fin, " %11[^ ]%44[^-]-%[^;]; %d.%d.%63[^\n]", taxi[i].code, taxi[i].from, taxi[i].to,
&taxi[i].day, &taxi[i].month, restofline)==6)
因为您需要刷新行的其余部分 scanf
未在您的代码中管理
注意第一个 '%' 之前的 space 绕过上一行的换行符,事实上我限制了要读取的字符串的大小而不是写出数组
例如:
#include <stdio.h>
typedef struct{
char code[12];
char from[45];
char to[45];
int day;
int month;
int year;
int hour;
int min;
float km;
float price;
}Taxi;
int main()
{
int i = 0;
Taxi taxi[10];
char restofline[64];
while(fscanf(stdin, " %11[^ ]%44[^-]-%[^;]; %d.%d.%63[^\n]", taxi[i].code, taxi[i].from, taxi[i].to,
&taxi[i].day, &taxi[i].month, restofline)==6)
{
printf("|%s| |%s| |%s| |%d| \n", taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day);
if (++i == 10)
break;
}
return 0;
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| | John March 136 | | Mary Perpetum 419| |8|
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| | John March 136 | | Mary Perpetum 419| |8|
^C
pi@raspberrypi:/tmp $
如果您想保存所有字段:
#include <stdio.h>
typedef struct{
char code[12];
char from[45];
char to[45];
int day;
int month;
int year;
int hour;
int min;
float km;
float price;
}Taxi;
int main()
{
int i = 0;
Taxi taxi[10];
while(fscanf(stdin, " %11[^ ] %44[^-]- %[^;]; %d.%d.%d.%d:%d%f%f",
taxi[i].code, taxi[i].from, taxi[i].to,
&taxi[i].day, &taxi[i].month, &taxi[i].year,
&taxi[i].hour, &taxi[i].min,
&taxi[i].km, &taxi[i].price)==10)
{
printf("|%s| |%s| |%s| |%d| %d:%d %f %f\n",
taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day,
taxi[i].hour, taxi[i].min, taxi[i].km, taxi[i].price);
if (++i == 10)
break;
}
return 0;
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| |John March 136 | |Mary Perpetum 419| |8| 5:42 3.802570 71.449997
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
|CXKNS87356| |John March 136 | |Mary Perpetum 419| |8| 5:42 3.802570 71.449997
^C
pi@raspberrypi:/tmp $
请注意 space 仍然存在于第一个 '%' 之前以绕过从一行到下一行的换行符。我还加了一个flush space(s)在字段'to'的开头,但是你需要去掉字段末尾可能的space(s)[=33] =] 和 'to'
你漏掉了不想读的字符:
$ grep scanf test2.c
fscanf(stdin, "%[^ \n] %[^-] - %[^;]; %d.%d.", taxi[i].code, taxi[i].from, taxi[i].to, &taxi[i].day, &taxi[i].month);
$ echo 'CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45'|./test2
|CXKNS87356| |John March 136 | |Mary Perpetum 419| |8|
|
|和 |
|在 |-
| 之后失踪了。
示例:您的第一个匹配项是 %[^ \n]
,它排除了 space,但您没有在之后添加被排除的 space。添加 space 然后你的下一场比赛 %[^-]
就会发生。之后使用 |-
| (连字符后有 space)。
这样做的唯一缺点是约翰尾随 space。
如何区分“约翰字段”中的space是属于该字段还是分隔符?我不认为scanf解析器可以处理它。正则表达式可以。或者你修复 from
的结尾,例如:
$ grep strlen test2.c
if (taxi[i].from[strlen(taxi[i].from)-1] == ' ') taxi[i].from[strlen(taxi[i].from)-1] = 0;
$ echo 'CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45'|./test2
|CXKNS87356| |John March 136| |Mary Perpetum 419| |8|
通过这样做,您只需删除“John field”中的尾随 space。
这是我完整的 main() 方法:
int main() {
Taxi taxi[1];
int i=0;
// 'CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45'
fscanf(stdin, "%[^ \n] %[^-] - %[^;]; %d.%d.", taxi[i].code, taxi[i].from, taxi[i].to, &taxi[i].day, &taxi[i].month);
if (taxi[i].from[strlen(taxi[i].from)-1] == ' ') taxi[i].from[strlen(taxi[i].from)-1] = 0;
printf("|%s| |%s| |%s| |%d| \n", taxi[i].code, taxi[i].from, taxi[i].to, taxi[i].day);
return 0;
}
字符串
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.2014. 05:42 3.80257 71.45
我只是从上面复制过来的
注意:我像您一样忽略了年份、小时等。我假设您将添加对它们的解析。
这意味着您的第一个 scanf 将解析到
CXKNS87356 John March 136 - Mary Perpetum 419; 8.2.
你的下一个循环将在
上继续解析2014. 05:42 3.80257 71.45\n...
如果您不想解析年份和之后的所有内容,那么只需将其作为字符串解析到缓冲区中并忽略缓冲区的内容。
我假设你的解析丢失了,因为你最多解析了一个月,但只打印了一天。因此,看起来工作正在进行中,问题出在 spaces.