#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num) {
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("b.csv", "r");
char line[1024];
char *pstr;int num;
const char* value;
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
//printf("Field 3 would be %sn", getfield(tmp, 3));
value=getfield(tmp, 3);
num =strtol(value,&pstr,10);
printf("Field 3 would be %dn", num);
// NOTE strtok clobbers tmp
free(tmp);
}
}
/* b.csv
301,36,15
302,88,75
//我的输出
Field 3 would be 15
Field 3 would be 75
*/
问题是:/* b.csv
301,36,15
302,88,
,,,34
如果表如上面的" strtok"返回null,那么" strtol"给出了" segfault"。如何解决它?
在这里,主要问题是,如果不存在第二个,它将第三次将其视为第二个,并给出segfault!例如,在B.CSV的第三行中,34"是否存在3个值,但其行为类似于" 34"是第一个值,第2个值分别为NULL!
为什么您不能仅检查getfield(tmp, 3);
的value
,如果返回NULL
,并且如果返回NULL
,则不能拨打strtol
?解决的另一种方法是在getfield
中制作static char* not_found = "";
并返回地址而不是NULL
,然后strtol
不会segfault。
update
由于我发现在这种情况下strtok
确实是无助的,所以我尝试编写与strchr
相同的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getfield(char* line, int num) {
char* tok = line;
char* result;
if (line)
{
do
{
if (!--num)
{
tok = strchr(line, ',');
if (tok == NULL)
{
tok = &line[strlen(line)];
}
size_t fieldlen = tok - line;
if (fieldlen)
{
result = (char*)malloc(fieldlen+1);
result[fieldlen] = ' ';
strncpy(result, line, fieldlen);
return result;
}
else
{
break;
}
}
tok = strchr(line, ',');
line = tok + 1;
} while (tok);
}
result = (char*)malloc(2);
strcpy(result, "0");
return result;
}
int main()
{
FILE* stream = fopen("b.csv", "r");
char line[1024];
char *pstr;int num;
char* value;
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
//printf("Field 3 would be %sn", getfield(tmp, 3));
value=getfield(tmp, 3);
num =strtol(value,&pstr,10);
free(value);
printf("Field 3 would be %dn", num);
// NOTE strtok clobbers tmp
free(tmp);
}
}
这在输入文件上工作:
10,,30
10,
代码将返回0
如果什么也没有找到,您可以更改它,结果将动态分配。我希望这会有所帮助,对我的教训是 - 解析字符串时避免C:D
而不是
num =strtol(value,&pstr,10);
printf("Field 3 would be %dn", num);
使用此:
if (value!=NULL) {
num =strtol(value,&pstr,10);
printf("Field 3 would be %dn", num);
}
else {
printf("Field 3 does not existn");
}
您必须在调用strtol()
函数之前检查value!= NULL
是否
编辑修复getfield()
功能的返回
在for循环中尝试更改:(我没有测试它,但可以解决您的问题)
tok = strtok(NULL, ",n")
tok = strtok(tok+strlen(tok)+1, ",n")