我有一个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/