详解C语言读取文件求某一列的平均值
程序员文章站
2021-12-14 10:43:47
目录第一部分:比较读取文件的效率第二部分:比较求取列平均值的效率第一部分:比较读取文件的效率在之前的文章《生信(五)awk求取某一列的平均值》中,笔者曾经给出过c语言求取某列平均值的代码,但是最近回顾...
第一部分:比较读取文件的效率
在之前的文章《生信(五)awk求取某一列的平均值》中,笔者曾经给出过c语言求取某列平均值的代码,但是最近回顾时发现,这段代码至少有几点不足:
1. 利用 fgetc 函数来读取文件,现在看来效率不高。
2. 如果文件最后没有一个空白行的话,会陷入无限循环。也就是对 eof 的处理不完善。
大家都知道,c语言读取文件的常用函数有 fgetc、fgets、fread 以及 fscanf 等。笔者曾经一度以为就读取文件的效率而言,fgetc 不亚于其他函数。但是究竟是不是这样,还是自己验证一下让自己信服。
首先随机生成一个文件,1000万行,4列(该文件下面还会用到)。我们看一下上述函数读取文件的效率:
从上图中可以看出,fread 的效率最高,fgetc 的效率最低。当然这种比较很粗浅,但是能大概看出趋势。
各个函数读取文件的代码如下:其中 main 函数是一样的,只是 readfile 函数的实现不同。
#include <stdio.h> #include <stdlib.h> #include <time.h> #define bufsize 4096 void readfile(file* fp); int main(int argc, char* argv[]) { file *fp; time_t start, end; start = time(null); if (argc < 2) { printf("usage: %s <filename>\n", argv[0]); return 1; } if ((fp = fopen(argv[1], "r")) == null) { printf("error: cannot open file\n"); return 1; } readfile(fp); fclose(fp); end = time(null); printf("time spent: %d seconds\n", end - start); return 0; } // readfile_fgetc: void readfile(file* fp) { char c; while ((c = fgetc(fp)) != eof) ; } // readfile_fgets: void readfile(file* fp) { char buf[bufsize]; while (fgets(buf, maxline, fp) != null) ; } // readfile_fread: void readfile(file* fp) { char buf[bufsize]; while (fread(buf, 1, bufsize, fp) > 0) ; } // readfile_fscanf: void readfile(file* fp) { char buf[bufsize]; while (fscanf(fp, " %[^\n]s", buf) == 1) ; }
第二部分:比较求取列平均值的效率
那么各个函数计算列平均值的效率如何呢?我们依然使用上面那1000万行的文件,用上述各个函数实现计算第2列平均数的功能,它们的效率如下:
代码如下:main 函数大体上是一样的,只是 colaver 函数的实现不一样。
(这些代码完善地处理了eof,无论文件最后是否有空白行都可以正确运行。但是仍然有前提,就是文件中每一行的分隔符(列数)是一样的,否则代码可能会出错。)
这些代码中,fscanf 的最简短,该函数可以大大提高格式化读取数据的编程效率。
#include <stdio.h> #include <stdlib.h> #include <time.h> #define bufsize 4096 void getcolaver(file* fp, const int k); int main(int argc, char* argv[]) { file *fp; time_t start, end; start = time(null); if (argc < 2) { printf("usage: %s <filename>\n", argv[0]); return 1; } if ((fp = fopen(argv[1], "r")) == null) { printf("error: cannot open file\n"); return 1; } getcolaver(fp, 2); fclose(fp); end = time(null); printf("time spent: %d seconds\n", end - start); return 0; } // colaver_fgetc: void getcolaver(file* fp, const int k) { int i = 0; // num of '\t' int j = 0; // num of chars int c; // char char col[50]; float sum = 0; int n = 0; // num of lines. int incol = 0; while ((c = fgetc(fp)) != eof) { if (i == k - 1) { incol = 1; if (c == '\t') i++; else if (c == '\n') i = 0; else col[j++] = c; } else { if (c == '\t') i++; else if (c == '\n') i = 0; if (incol) { col[j] = '\0'; sum += atof(col); n++; } j = 0; incol = 0; } } if (incol) { col[j] = '\0'; sum += atof(col); n++; } if (n == 0) printf("error: no line!\n"); else printf("the average of col %d is %f\n", k, sum / n); } // colaver_fgets: void getcolaver(file* fp, const int k) { int i = 0; // num of '\t' int j = 0; // num of chars char col[50]; char buf[bufsize]; float sum = 0; int n = 0; // num of lines. int incol = 0; char* p; while (fgets(buf, bufsize, fp) != null) { for (p = buf; *p != '\0'; p++) { if (i == k - 1) { incol = 1; if (*p == '\t') i++; else if (*p == '\n') i = 0; else col[j++] = *p; } else { if (*p == '\t') i++; else if (*p == '\n') i = 0; if (incol) { col[j] = '\0'; sum += atof(col); n++; } j = 0; incol = 0; } } } if (incol) { col[j] = '\0'; sum += atof(col); n++; } if (n == 0) printf("error: no line!\n"); else printf("the average of col %d is %f\n", k, sum / n); } // colaver_fread: void getcolaver(file* fp, const int k) { int i = 0; // num of '\t' int j = 0; // num of chars char col[50]; char buf[bufsize]; float sum = 0; int n = 0; // num of lines. int m, l; int sizechr = sizeof(char); int incol = 0; while ((l = fread(buf, sizechr, bufsize, fp)) > 0) { for (m = 0; m < l; m++) { if (i == k - 1) { incol = 1; if (buf[m] == '\t') i++; else if (buf[m] == '\n') i = 0; else col[j++] = buf[m]; } else { if (buf[m] == '\t') i++; else if (buf[m] == '\n') i = 0; if (incol) { col[j] = '\0'; sum += atof(col); n++; } j = 0; incol = 0; } } } if (incol) { col[j] = '\0'; sum += atof(col); n++; } if (n == 0) printf("error: no line!\n"); else printf("the average of col %d is %f\n", k, sum / n); } // colaver_fscanf: void getcolaver(file* fp) { float f; float sum = 0; int n = 0; // num of lines. while (fscanf(fp, "%*s%f%*[^\n]s", &f) == 1) { sum += f; n++; } if (n == 0) printf("error: no line!\n"); else printf("the average of col 2 is %f\n", sum / n); }
以上就是详解c语言读取文件求某一列的平均值的详细内容,更多关于c语言读取文件求某一列的平均值的资料请关注其它相关文章!