使用Strtok()验证CSV文件

时间:2012-04-23 04:53:59

标签: c strtok

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

通过在线阅读,似乎人们对此有不一致的看法 - 但Strtok()是最好的方法吗?

任何帮助都会很棒。

1 个答案:

答案 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.

当然,如果这是一个真正的问题,我可能更喜欢flexbison,写一个小词法和语法,主要是因为它会是随着需求的变化, 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 */注释以提醒自己某些事情没问题。