0

我需要验证文本文件是否为 CSV 格式(即每个数字用逗号分隔)。

从网上阅读,似乎人们对此有相互矛盾的看法——但这是Strtok()最好的方法吗?

任何帮助都会很棒。

4

1 回答 1

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.

当然,如果这是一个真正的问题,我可能更喜欢flexand 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 */两次评论以提醒自己有些事情是好的。

于 2012-04-23T05:28:31.703 回答