我有一个CSV文件,格式为:
name,num-one,num-two,num-three
我有一个我使用的解析脚本(如下),但我想编辑脚本以检查整个文件,然后继续。
脚本的伪代码:
Read through the whole file/
Find a line where token 1 matches a set value AND
Token two matches another set value THEN
Set the value two tokens as new variables
Otherwise move onto the next line.
如果令牌1(name
)和令牌2(num-one
)等于我的程序当前正在处理的值,则将令牌3和4设置为value1
和{{ 1}}。
value2
答案 0 :(得分:6)
你真的不应该使用strtok()
来做这样的事情。
相反,做得更简单:
fgets()
读取一行。你已经这样做了。sscanf()
解析该行。使用sscanf()
,解析出四个字段是单个函数调用:
char name[16];
int num1, num2, num3;
if(sscanf(line, "%15s,%d,%d,%d", name, &num1, &num2, &num3) == 4)
{
printf("got '%s' with values %d, %d and %d\n", name, num1, num2, num3);
}
我并非100%确定您期望的字段是正确的,我发现您的描述(和代码)很难理解。我假设一个字符串后跟四个整数。
请注意,上面将字符串部分视为一个简单的字符串;它不能嵌入空格。要改为依赖逗号分隔字段,请使用:
if(sscanf(line, "%15[^,],%d,%d,%d", name, &num1, &num2, &num3) == 4)
^
|
changed this
这会将第一部分视为一串非逗号字符,允许嵌入空格。
答案 1 :(得分:1)
为什么不考虑在awk中编写检查器(如果我理解你的帖子的目的)? awk将遍历你的.csv,如果你使用gawk -vFS =','将用逗号分隔字段,你可以很容易地在字段之间添加任何类型的测试或重新排列它们。那么无论你的目标是什么,你都可以假设一旦awk程序运行,文件就会满足你所有的前提条件。
#!/usr/bin/gawk -f
BEGIN { OFS=FS=',';}
{
print $1+$3, $2, $3, $4;
}
此代码将复制输入文件,同时将第一个数字替换为第一个和第三个的总和。 awk程序写得比C快得多,更容易维护和修改,我敢打赌它会比你的未经修改的C版本运行得更快。
答案 2 :(得分:1)
您的问题已经得到解答。尽管如此,我想展示如何将strtok
用于您的目的。您的count
方法不起作用。相反,您可以一次分析一个字段,如果不满足条件,则可以continue
循环。
(你似乎错过了你的例子中的外部循环。我不知道这是否是“检查整个文件”的意思。这个循环逐行读取文件; continue
表示阅读下一行,break
表示停止阅读。)
for (;;) {
char line[32];
char *pch;
int x;
if (fgets(line, 32, read_file) == NULL) break;
pch = strtok(line, ",");
if ((strcmp(pch, name) != 0)) continue;
pch = strtok(NULL, ",");
if (sscanf(pch, "%d", &x) < 1 || x != num) continue;
pch = strtok(NULL, ",");
if (sscanf(pch, "%d", &value1) < 1) continue;
pch = strtok(NULL, ",");
if (sscanf(pch, "%d", &value2) < 1) continue;
}
但我必须承认,sscanf
方法更简单,可能足以满足您的目的。如果您有更复杂的输入,例如,如果字段的含义和数据类型取决于第一个字段,strtok
方法可能更灵活。