我有一个ginormous CSV文件,我想剖析它。但我注意到并不是所有的数据都是通过的,我不知道为什么。
当我有两个getfield在fprintf。我得到两个答案,当我有3个,中间的总是空的,当我有4个,中间的都是空的。
为什么我总是得到两个答案,为什么中间的答案总是空的?

#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 ]

最佳答案

代码中存在多个问题:
getfield()修改缓冲区,用空字节覆盖分隔符,因此下次调用时,只能访问第一个字段。
函数参数的求值顺序是未指定的,在参数列表中对getfield()的3个调用中,对fprintf的调用也未指定。
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;
}

关于c - C中的getfield()不一致,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49341270/

10-10 05:56