使用fscanf扫描文件后的结果不正确

使用fscanf扫描文件后的结果不正确,c,file,scanf,C,File,Scanf,使用fscanf扫描.txt文件中的某些数据时出现问题 例如: CXKNS87356约翰136年3月-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 h

使用
fscanf
扫描
.txt
文件中的某些数据时出现问题

例如:

CXKNS87356约翰136年3月-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)
#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;
}
因为需要刷新行的其余部分
scanf
在代码中无法管理

请注意,第一个“%”前面的空格用于从上一行绕过换行符,并且我将字符串的大小限制为读取而不是从数组中写入

例如:

  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)
#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;
}
如果要保存所有字段:

#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;
}

请注意第一个“%”之前仍然存在的空格,以绕过换行符从一行到下一行。我还添加了一个以刷新字段“to”开头的空格,但您需要删除字段“from”和“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]
,它排除了空格,但之后您没有添加被排除的空格。添加空格,然后将进行下一次匹配
%[^-]
。然后使用|
-
|(连字符后加空格)

这样做的唯一缺点是John的尾部空间

如何区分“John字段”中的空格是属于该字段还是分隔符?我认为scanf解析器无法处理它。正则表达式可以。或者您可以通过以下方式修复来自的
的结尾,例如:

$ 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| 
通过这样做,您只需删除“johnfield”中的尾随空格

这是我完整的main()方法:

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...
如果您不想解析年份和之后的所有内容,那么只需将其作为字符串解析到缓冲区中,并忽略缓冲区的内容


我假设您的解析丢失了,因为您解析到了一个月,但只打印到了一天。因此,它看起来像是在进行中,问题在于空格。

%[^-]
-这个匹配的字符串有多少?我不明白,它上载了第一个地址的字符串(从),直到-但我仍然需要%d.%d。,问题在于dotsIt只有一行代码需要添加到可接受的答案中,以删除最后不需要的空间。请参见下文。如果我这样做,它为什么会起作用:while(fscanf(fin,%[^\n]%[^-]-%[^;];%d.”,taxi[I]。代码,taxi[I]。from,taxi[I]。to,&taxi[I]。day)==4{如果我在上面编写代码(我写过)没有work@Momo如果您想让行的正确部分读取其中的几个部分,您需要读取行的结尾以刷新它,请查看我的答案中的执行情况,并解释第一个“%”%[^\n][^-]-%[^;];%d.%d.%d.%d:%d%f%[^\n];之前的空格的意义,此完整的fscanf不起作用(我在最后上传浮动价格)不要以“%[^\n]
开头,而是以“%[^]开头,就像我在回答中所做的那样,不要在第一个“…”中使用“
\n
”,而只在最后一个“…”,但当最后一个字段不是字符串时,甚至不要在最后一个bruno jesi ti nasI fscanf John March 136中使用“\n”(直到-)@Momo:你的评论太快了。;-)我甚至在John处键入并最终修复了尾随空格。:-)我的代码仍然无法工作xD,“(空格)%[^][^-]-%[^;];%d.%d.%d.%d:%d%f%f”@Momo我添加了一个注释。我刚刚修复了一行的解析字符串。我假设您将为其余字段添加解析。否则,解析程序将在月点之后停止,在下一个循环中,将从第一次输入开始计算年份!
2014. 05:42 3.80257 71.45\n...