我有一个包含多行的以下格式的文件:
2019-12-05 07:14:00 (151.45,-23.917)
我想将每行分成3个变量,以便在示例中第一个变量为“ 2019-12-05”,第二个变量为“ 07:14:00”,最后一个变量为(151.45,-23.917)显示的上述行中的行。
我下面有一段代码,在其中我试图将行分成三个变量,但是遇到了段错误。
int main(int argc, char *argv[])
{
FILE *fp=NULL;
char inpFname[81],buf[8000];
int dates,hour,lon,lat;
int i=0;
int voyageid = atoi(argv[1]);
sprintf(inpFname,"%d_latlon.txt",voyageid);
if ((fp=fopen(inpFname,"rt"))==NULL)
{
printf("\nERROR: Cannot open/read input file [%s]\n\n",inpFname);
exit(1);
}
while(!feof(fp))
{
fgets(buf,8000,fp);
printf("%d) buf is %s",i,buf);
sscanf(buf,"%s %s %s", dates,hour,lon);
printf("date is %s and lat is %s and lon is %s\n",dates,lat,lon);
i=i+1;
}
}
如何调整代码以确保将每一行成功拆分为单独的变量?
正在输入的文件如下所示:
2019-12-03 06:00:00 (152.282,-13.505)
2019-12-03 12:00:00 (152.393,-14.8478)
2019-12-03 18:00:00 (152.505,-16.1906)
2019-12-04 00:00:00 (152.618,-17.5335)
2019-12-04 06:00:00 (152.732,-18.8763)
2019-12-04 12:00:00 (152.846,-20.2191)
2019-12-04 18:00:00 (152.962,-21.5619)
三件事:
dates
,hour
,lon
和lat
声明为字符串,因为这就是%s
中的fscanf
所期望的。这是您的主要问题,但是在解决问题时,您应该修复另外两件事,这会很快导致您遇到其他问题:
您需要检查fscanf
的返回值。
您无需呼叫while(!feof(fp))
。 (请参阅here。)检查fscanf
的返回值后,如果fscanf
返回的项少于您要求的项目数3或4,则应使用它终止循环。
您的下一个问题是,如何将dates
等声明为字符串?如果您执行类似的操作
char *dates;
也将失败,因为dates
尚未指向任何地方。比较容易的是
char dates[100];
或者,如果您要使用指针,则可以保留char *dates
,只要您执行以下操作
dates = malloc(100);
接着进行检查以确保malloc
没有返回NULL。然后,无论哪种情况,为了安全起见,您都应该将格式字符串的相关部分更改为%99s
,以确保fscanf
不会尝试读入超出其范围的字符串(以及您在哪里请使用%99s
,而不要使用%100s
,因为您必须为\0
终止符留出空间)。
然后您的下一个问题是,如果dates
和其余的是字符串,您如何从中取出数字?诸如atoi
,atof
,strtol
和strtod
之类的功能可能会有所帮助,或额外/不同的scanf
格式。
例如,您可以做类似的事情
int y, m, d;
if(sscanf(dates, "%d-%d-%d", &y, &m, &d) == 3) {
/* now have broken-down date in y, m, d *.
}
Of,您可以执行完全不同的顶级解析:
int year, month, day, hour, minute, second;
double lat, lon;
while(fscanf(fp, "%d-%d-%d %d:%d:%d (%lf,%lf)", year, month, day, hour, minute, second, &lat, &lon) == 8) {
...
}