详解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语言读取文件求某一列的平均值的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言实现从文件读入一个3*3数组,并计算每行的平均值

    题目要求 从文件读入一个3*3数组,并计算每行的平均值. 参考解答 1. 数据文件:array.dat 创建一个.dat文件用于存放数组文件: 1 3 6 2 9 7 3 6 4 文件名随意啦. 2. 代码 如果需要计算行平均值的话改一下avg = (a[i][0] + a[i][1] + a[i][2]) / 3;这行代码就行了. 太简单了懒得写method操作啦: #include<stdio.h> void main(){ FILE *fr; int i, j, a[3][3]; flo

  • C语言中的各种文件读写方法小结

    前言     找工作的时候,曾经用C语言练习过一段时间的算法题目,也在几个还算出名的OJ平台有过还算靠谱的排名.之前以为C语言只限于练习一下算法,但是工作中的一个问题解决让我意识到C语言的用处还是非常广泛的.下面介绍一下,如果用C语言来操作文件保存一个字符串,和读取一个字符串.算法中往往都是printf来打印出结果,但是真实工作中往往通过文件来进行一些持久化的存储工作. C-File I/O     文件的I/O操作是每一门语言的重点,因此这里我先来介绍一下如何用C语言去进行文件的I/O操作.

  • C语言中求和、计算平均值、方差和标准差的实例

    计算C语言中的求和.标准差.方差和标准差等,需要加上头文件:#include <math.h> #include<stdio.h> #include "math.h" double sum = 0;//求和 double array[4] = {1.2,2.1,3.1,4.1}; int length = 0;//数组长度 double average = 0;//求平均数 double var = 0; //求方差 double standard = 0; /

  • C语言读取文件流的相关函数用法简介

    C语言fread()函数:读文件函数(从文件流读取数据) 头文件: #include <stdio.h> 定义函数: size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream); 函数说明:fread()用来从文件流中读取数据. 参数stream 为已打开的文件指针, 参数ptr 指向欲存放读取进来的数据空间, 读取的字符数以参数size*nmemb 来决定. Fread()会返回实际读取到的nmemb 数目, 如果此值

  • c语言文件读写示例(c语言文件操作)

    方法: 复制代码 代码如下: long filesize(char* filename);char* file_get_contents(char* filename);void file_put_contents(char* filename, char* data); 示例: 复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <string.h>long filesize(char* filename)

  • 详解C语言读取文件求某一列的平均值

    目录 第一部分:比较读取文件的效率 第二部分:比较求取列平均值的效率 第一部分:比较读取文件的效率 在之前的文章<生信(五)awk求取某一列的平均值>中,笔者曾经给出过C语言求取某列平均值的代码,但是最近回顾时发现,这段代码至少有几点不足: 1. 利用 fgetc 函数来读取文件,现在看来效率不高. 2. 如果文件最后没有一个空白行的话,会陷入无限循环.也就是对 EOF 的处理不完善. 大家都知道,C语言读取文件的常用函数有 fgetc.fgets.fread 以及 fscanf 等.笔者曾经

  • 一文详解C语言中文件相关函数的使用

    目录 一.文件和流 1.程序文件 2.数据文件 3.流 二.文件组成 三.文件的打开和关闭 1.文件的打开fopen 2.文件关闭fclose 四.文件的顺序读写 1.使用fputc和fgetc写入/读取单个字符 2.使用fputs和fgets写入/读取一串字符 3.使用fprintf和fscanf按照指定的格式写入/读取 4.使用fwrite和fread按照二进制的方式写入/读取 5.使用sprintf和sscanf将格式化数据和字符串互相转换(文件无关) 五.文件的随机读写 1.fseek(

  • 详解C语言之文件操作下)

    目录 文件的随机读写 fseek函数 ftell函数 rewind函数 文件结束判定 feof函数和ferror函数 总结 文件的随机读写 之前的函数只能实现顺序读写,而实现随机读写需用fseek函数来定位--根据文件指针的位置和偏移量来定位文件指针 fseek函数 int fseek(FILE* stream, long int offset, int origin); 返回值:若成功返回0,则返回非0值. 参数:stream为文件指针,offset为偏移量.origin为起始位置,有三种 S

  • 详解C语言之文件操作(上)

    目录 什么是文件 程序文件 数据文件 文件名 文件类型 文件缓冲区 文件指针 文件的打开和关闭 输入和输出 总结 什么是文件 磁盘上的文件就是文件. 在程序设计中,我们一般谈的文件有两种:程序文件和数据文件 程序文件 包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe). 数据文件 文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行时需要从中读取数据的文件,或者输出内容的文件. 文件名 文件名包含三部分:文件路径.

  • 详解C语言fscanf函数读取文件教程及源码

    目录 第一部分:问题和结论 fscanf 函数的原型是: 第二部分:实验代码 实验代码: fscanf 函数用于格式化读入文件中数据,可以大大提高读取文件的效率.这次笔者将最近使用该函数的一些经验记录下来. 第一部分:问题和结论 fscanf 函数的原型是: int fscanf(FILE* stream, const char* format, [argument...]); fscanf 函数与 scanf 函数用法类似,只不过前者用于读取文件流的数据而已.至于 fscanf 的基础用法我就

  • 详解Go语言如何使用xorm实现读取mysql

    目录 一.介绍 二.安装使用xorm,注意连接的关闭! 关于连接数的坑以及engine.Close() 常用方法介绍 三.mysql生产struct 四.xorm常用操作示例--insert数据 4.1 insert 增加1条数据 4.2 insert 增加多条数据 4.3 insert 增加不同表数据 五.xorm常用操作示例--删除某行 5.1 通过id删除 5.2 通过where条件删除 5.3 软删除,通过某个字段实现软删除,比如status=0 六.xorm常用操作示例--update

  • 详解C 语言项目中.h文件和.c文件的关系

    详解C 语言项目中.h文件和.c文件的关系 在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件.但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件. 于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句.这样即

  • 详解PHP如何读取大文件

    衡量成功 唯一能确认我们对代码所做改进是否有效的方式是:衡量一个糟糕的情况,然后对比我们已经应用改进后的衡量情况.换言之,除非我们知道 "解决方案" 能帮我们到什么程度 (如果有的话),否则我们并不知道它是否是一个解决方案. 我们可以关注两个指标.首先是 CPU 使用率.我们要处理的过程运行得有多快或多慢?其次是内存使用率.脚本执行要占用多少内存?这些通常是成反比的 - 这意味着我们能够以 CPU 使用率为代价减少内存的使用率,反之亦可. 在一个异步处理模型 (例如多进程或多线程 PH

  • 详解C语言gets()函数与它的替代者fgets()函数

    在c语言中读取字符串有多种方法,比如scanf() 配合%s使用,但是这种方法只能获取一个单词,即遇到空格等空字符就会返回.如果要读取一行字符串,比如: I love BIT 这种情况,scanf()就无能为力了.这时我们最先想到的是用gets()读取. gets()函数从标准输入(键盘)读入一行数据,所谓读取一行,就是遇到换行符就返回.gets()函数并不读取换行符'\n',它会吧换行符替换成空字符'\0',作为c语言字符串结束的标志. gets()函数经常和puts()函数配对使用,puts

  • 用十张图详解TensorFlow数据读取机制(附代码)

    在学习TensorFlow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下TensorFlow的数据读取机制,文章的最后还会给出实战代码以供参考. TensorFlow读取机制图解 首先需要思考的一个问题是,什么是数据读取?以图像数据为例,读取数据的过程可以用下图来表示: 假设我们的硬盘中有一个图片数据集0001.jpg,0002.jpg,0003.jpg--我们只需要把

随机推荐