我需要验证文本文件是否为 CSV 格式(即每个数字用逗号分隔)。
从网上阅读,似乎人们对此有相互矛盾的看法——但这是Strtok()
最好的方法吗?
任何帮助都会很棒。
您的输入似乎很简单,我可能只会使用循环fgetc(3)
;我将在这里绘制一些伪代码:
fd = fopen("file", "r");
int c;
while((c=fgetc(fd)) != EOF) {
switch(c) {
case '0':
case '1':
/* so on */
case '9':
handle_digit(c);
break;
case ',':
handle_comma();
break;
case '\n':
handle_newline();
break;
default:
fprintf(stderr, "mistaken input %c\n", c);
break;
}
}
fclose(fd);
如果您习惯于使用高级语言(例如 Ruby 或 Python)来获取数字列表,那么您必须以一种可能有点尴尬的方式管理函数中的输入line.split(',')
,但是非常地道 C.
当然,如果这是一个真正的问题,我可能更喜欢flex
and bison
,并编写一个小的词法分析器和语法,主要是因为将来随着需求的变化它会更容易扩展。
更新
通过一些额外的标准来检查,handle_{digit,comma,newline}()
例程更容易绘制。我将使用全局变量进行草图绘制,但您可以轻松地将它们填充到 a 中struct
并将它们从一个函数传递到另一个函数:
enum seen {
NEWLINE,
COMMA,
DIGIT,
};
enum seen last_seen = NEWLINE;
handle_digit(int c) {
if (last_seen == DIGIT) {
/* error if numbers cannot have multiple digits
or construct a larger number if numbers can have
multiple digits */
} else if (last_seen == COMMA || last_seen == NEWLINE) {
/* start a new entry */
}
last_seen = DIGIT;
}
handle_comma() {
if (last_seen == COMMA) {
/* error */
} else if (last_seen == NEWLINE) {
/* error */
} else if (last_seen == DIGIT) {
/* end previous field */
}
last_seen = COMMA;
}
handle_newline() {
if (last_seen == NEWLINE) {
/* error */
} else if (last_seen == COMMA) {
/* error */
} else if (last_seen == DIGIT) {
/* end previous field */
}
last_seen = NEWLINE;
}
根据您拥有的任何规则添加您需要验证内容的任何检查。您可能希望标准化测试的顺序和内容,以确保您永远不会忘记一个,即使这意味着您写一/* nop */
两次评论以提醒自己有些事情是好的。