C中的getfield(),不一致

时间:2018-03-17 19:52:43

标签: c csv

我有这个巨大的CSV文件,我想解剖。但我注意到并非所有数据都通过,我无法弄清楚原因。

当我在fprintf中有2个getfield时。我得到了两个答案,当我有3个时,中间总是NULL,当我有4个时,两个中间都是NULL。 那么为什么我总是得到2个答案,为什么中间的答案总是空的呢?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num){
    const char* tok;
    for (tok = strtok(line, ","); tok && *tok ; tok = strtok(NULL, ",\n")){
        if (!--num){
            return tok;
        }
    }
    return NULL;
}
int main(){
    FILE* stream = fopen("perf log (paralel encoding disabled).CSV", "r");
    FILE *f = fopen("file2.html", "w+");
    if (f == NULL){
        printf("Error opening file!\n");
        exit(1);
    }
    char* html1 = "<!DOCTYPE html> \n<html> \n<head> \n <title></title> \n</head> \n<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'> </script>\n <body> \n";
    fprintf(f, "%s", html1 );
    int i = 0;
    char line1[102400];
    while (fgets(line1, 102400, stream)){
        char* tmp1 = strdup(line1);
        if(i > -1 && i<60000){
            fprintf(f,"[%i , %s  , %s , %s ] <br>",i, getfield(tmp1, 1),  getfield(tmp1, 2), getfield(tmp1, 3), );
        }
        free(tmp1);
        i++;
    }
    char* html4 = "   \n </body> \n </html> \n";
    fprintf(f, "%s", html4);
    fclose(f);
}

一些输出

[0 , Date , (null) , "Virtual Memory Commited [MB]" ] 
[1 , 13.3.2018 , (null) , 7226 ] 
[2 , 13.3.2018 , (null) , 7237 ] 
[3 , 13.3.2018 , (null) , 7226 ] 
[4 , 13.3.2018 , (null) , 7298 ] 
[5 , 13.3.2018 , (null) , 8011 ] 

1 个答案:

答案 0 :(得分:1)

您的代码中存在多个问题:

  • getfield()修改缓冲区,用空字节覆盖分隔符,因此下次调用它时,只能访问第一个字段。
  • 未指定评估函数参数的顺序,因此对getfield()的参数列表中的3个调用中fprintf的调用成功。{/ li>
  • strtok()很少是正确的解析工具:它会将任何分隔符序列视为单个分隔符,这对CSV文件无效,因为空字段会导致错误的解析。

您应该更改getfield()以分配字符串或将其复制到目标缓冲区。

以下是分配返回值的修改版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *getfield(const char* line, int num) {
    const char *p = line;
    size_t len;
    char *res;
    for (;;) {
        len = strcspn(p, ";\n");
        if (--num <= 0)
            break;
        p += len;
        if (*p == ';')
            p++;
    }
    res = malloc(len + 1);
    if (res) {
        memcpy(res, p, len);
        res[len] = '\0';
    }
    return res;
}

int main() {
    FILE *stream = fopen("perf log (paralel encoding disabled).CSV", "r");
    if (stream == NULL) {
        fprintf(stderr, "Error opening input file!\n");
        exit(1);
    }
    FILE *f = fopen("file2.html", "w+");
    if (f == NULL) {
        fprintf(stderr, "Error opening output file!\n");
        exit(1);
    }
    const char *html1 = "<!DOCTYPE html> \n<html> \n<head> \n <title></title> \n</head>\n"
                        "<script type='text/javascript' "
                        "src='https://www.gstatic.com/charts/loader.js'> </script>\n <body> \n";
    fprintf(f, "%s", html1);
    int i = 0;
    char line1[102400];
    while (fgets(line1, 102400, stream)) {
        char *tmp1 = getfield(line1, 1);
        char *tmp2 = getfield(line1, 2);
        char *tmp3 = getfield(line1, 3);
        if (i > -1 && i < 60000) {
            fprintf(f,"[%i , %s  , %s , %s ] <br>", i, tmp1, tmp2, tmp3);
        }
        free(tmp1);
        free(tmp2);
        free(tmp3);
        i++;
    }
    const char *html4 = "   \n </body> \n </html> \n";
    fprintf(f, "%s", html4);
    fclose(stream);
    fclose(f);
    return 0;
}