我正在尝试使用以下格式从csv文件中读取数据:
a_x,a_y,v_x,o_rear,o_front,theta,type
-0.040,10.206,-0.000,0.000,-0.000,-0.002,plane
1.269,9.813,0.011,0.043,0.091,-0.002,plane
1.266,9.985,0.021,0.086,0.177,-0.002,plane
1.257,10.002,0.032,0.130,0.265,-0.002,plane
1.256,10.004,0.043,0.173,0.353,-0.002,plane
1.257,10.003,0.053,0.216,0.440,-0.002,plane
1.258,10.002,0.064,0.259,0.527,-0.002,plane
1.258,10.002,0.074,0.302,0.615,-0.002,plane
我写了以下代码: -
FILE *in_file = fopen(argv[1], "r");
int i=0, s=0;
char *temp;
fscanf(in_file,"%s",temp);
printf("%s\n",temp);
while(i<100){
float a_x,a_y,v_x,o_rear,o_front,theta;
char *type;
if((s = fscanf(in_file,"%f,%f,%f,%f,%f,%f,%[^,]",&a_x,&a_y,&v_x,&o_rear,&o_front,&theta,type))!=7)
printf("%7d,%d,%f,%f,%f,%f,%f,%f,%s\n",++i,s,a_x,a_y,v_x,o_rear,o_front,theta,type);
else{
printf("ALL GOOD: %7d\n",++i);
}
}
我遇到了分段错误。在运行gdb时,我发现它出现在fscanf(in_file,"%s",temp);
行,并出现以下错误: -
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff71c6f64 in _IO_vfscanf_internal (s=<optimized out>, format=<optimized out>, argptr=argptr@entry=0x7fffffffda48, errp=errp@entry=0x0)
at vfscanf.c:1107
1107 vfscanf.c: No such file or directory.
堆栈跟踪: -
#0 0x00007ffff71c6f64 in _IO_vfscanf_internal (s=<optimized out>, format=<optimized out>, argptr=argptr@entry=0x7fffffffda48,
errp=errp@entry=0x0) at vfscanf.c:1107
#1 0x00007ffff71cce47 in ___vfscanf (s=<optimized out>, format=<optimized out>, argptr=argptr@entry=0x7fffffffda48) at vfscanf.c:3066
#2 0x00007ffff71d47b7 in __fscanf (stream=<optimized out>, format=<optimized out>) at fscanf.c:31
#3 0x0000555555555186 in main (argc=2, argv=0x7fffffffdc58) at data_handler.cpp:23
令人惊讶的是,当我使用type
变量转储第一行时,我没有遇到任何seg错误。相反,fscanf
第一次返回7,然后返回0。因此,我可以正确读取第二行,但不能读取其他行。我究竟做错了什么?我想了解为什么会发生这种行为。
答案 0 :(得分:4)
从C ++中读取文件的惯用方法是istream::operator>>
,您可以找到here的详细文档。
它工作得更好,并且更难以获得分段错误和未定义的行为。
如果你打算解决这个问题 C way ,你应该使用C编译器(而不是C ++编译器),这段代码应该使用.c
扩展名这个问题应该使用[c]
标记。
尽管如此,无论您是C ++程序员还是C程序员,您都预期 阅读手册。例如,an fscanf
manual会告诉您如何正确使用fscanf
,从而回答这个问题。它说:
s匹配不是空格字符的字节序列。应用程序应确保相应的参数是指向
char
,signed char
或unsigned char
数组的初始字节的指针,该数组足以接受序列和一个终止的空字符代码,应自动添加。
虽然手册页提供了重点,但我强调了您需要了解的最重要的部分:temp
需要指向某些内容!
目前情况下,您的变量temp
可能指向任何或没有。例如,它可能包含空指针值,意味着它指向 nothing ;你还没有告诉它不这样做,对吗?
更改temp
的声明,如下所示:
char temp[512]; // ... or
char *temp = new char[512]; // ... etc
其中任何一项都会确保temp
中的fscanf(in_file, "%s", temp);
表达位于数组。
答案 1 :(得分:3)
您在temp
的调用中使用fscanf
,但未确定它指向可以读取数据的某个有效内存。这会导致未定义的行为。
您可以使用:
// Use any number that is big enough for your needs
char temp[200];
// Make sure you provide the maximum number of characters to
// read to temp, always leaving space for the null terminator.
fscanf(in_file, "%199s", temp);
答案 2 :(得分:1)
正如@PaulMcKenzie指出的那样,我没有初始化我的指针。所以我在所有地方使用了char x[100]
而不是char *x
。另一个问题是错误的格式字符串:它应该是"%f,%f,%f,%f,%f,%f,%s"
而不是"%f,%f,%f,%f,%f,%f,%[^,]"