我需要验证文本文件是否为CSV格式(即每个数字都用逗号分隔)。
通过在线阅读,似乎人们对此有不一致的看法 - 但Strtok()
是最好的方法吗?
任何帮助都会很棒。
答案 0 :(得分:2)
您的输入似乎如此很容易,我可能只会使用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
和bison
,写一个小词法和语法,主要是因为它会是随着需求的变化, lot 将来更容易扩展。
<强>更新强>
通过一些额外的标准来检查,handle_{digit,comma,newline}()
例程更容易绘制。我将使用全局变量进行草图绘制,但您可以轻松地将它们填充到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 */
注释以提醒自己某些事情没问题。