精华内容
下载资源
问答
  • 我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open()、close()、write()、read()等,而标准C语言库函数中也有一套对文件的操作函数fopen()、fclose()、fwrite()、fread()等....

    我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open()、close()、write()、read()等,而标准C语言的库函数中也有一套对文件的操作函数fopen()、fclose()、fwrite()、fread()等.。那么同样是对文件的操作函数,标C与UC有什么区别呢?是标C效率高还是UC效率高呢?今天就让我们来一探究竟。

    程序作用:将0~999999这1000000个整型数据写入文件。

    1、标准C实现大量数据写入文件:

    /*文件名test1.c*/
    #include<stdio.h>
    #include<stdlib.h>
    
    #define MAX 1000000
    
    int main (void)
    {
        FILE * fp = fopen("test1.txt","w");
        if(fp == NULL){
            perror("fopen test1.txt");
            exit(EXIT_FAILURE);
        }
    
        int i;
        for(i = 0; i < MAX; i++){
            fwrite(&i, sizeof(int), 1, fp);/*我们采用fwrite一个一个写入文件*/
        }
    
        fclose(fp);
        return 0;
    }
    /*gcc -o test1 test1.c编译*/

    写入文件的效率测试结果:
    这里写图片描述

    2、Linux系统函数实现大量数据写入文件:

    /*文件名test2.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<fcntl.h>
    
    #define MAX 1000000
    
    int main (void)
    {
        int fd = open("test2.txt",O_RDWR|O_TRUNC|O_CREAT,0666);
        /*O_RDWR可读可写,O_CREAT没有则新建,O_TRUNC覆盖写入(原有内容小清空),O_APPEND追加写入(原有内容不清空)*/
        if(fd == -1){
            perror("open test2.txt");
            exit(EXIT_FAILURE);
        }
    
        int i;
        for(i = 0; i < MAX; i++){
            write(fd, &i, sizeof(int));
        }
    
        close(fd);
        return 0;
    }
    /*gcc -o test2 test2.c编译*/

    写入效率测试结果:
    这里写图片描述
    我们发现系统函数的使用并没有使程序运行速率(写入速率)变快而是变慢了几十倍,而且在测试中,我们可以看见增加的时间基本都是在sys(系统层面)中增加的。这是因为,系统函数在用户层没有缓冲区,在内核层有缓冲区,但是缓冲区很小,所以大量数据在写入文件时,频繁刷新缓冲区降低了写入速率。所以系统函数(如write)需要加自定义缓冲区以提高速率,而标准C函数(如fwrite)不用自己设置缓冲区,如果系统函数用自定义缓冲区其效率比标C要好,不定义缓冲区则效率很低,但是缓冲区大小要合适,否则物极必反(即使有缓冲区,从缓冲区向文件中写也是一个一个写入的)。

    3、Linux系统函数实现大量数据写入文件修改:

    /*文件名test3.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<fcntl.h>
    
    #define MAX 1000000
    #define BUF_SIZE 500
    /*缓冲区大小,合适为宜,多少为合适需要自己测试,但是不同大小的缓冲区影响肯定是不同的*/
    int main (void)
    {
        int fd = open("test3.txt",O_RDWR|O_TRUNC|O_CREAT,0666);
        if(fd == -1){
            perror("open test3.txt");
            exit(EXIT_FAILURE);
        }
    
        int i;
        int buffer[BUF_SIZE] = {0};
        for(i = 0; i < MAX; i++){
            buffer[i%BUF_SIZE] = i;
            if(i%BUF_SIZE == BUF_SIZE-1)
                write(fd, buffer, sizeof(buffer));/*当缓冲区写满时向文件中写一次(刷新一次缓冲区)*/
        }
    
        close(fd);
        return 0;
    }
    /*gcc -o test3 test3.c编译*/

    写入效率测试结果:
    这里写图片描述
    加入自定义缓冲区后的测试发现,其效率比不加自定缓冲区要快100多倍,比标C写入速率也要快好几倍。如果缓冲区大小合适,其效率会提升更大。那么当我们将BUF_SZIE改为更大的值(BUF_SZIE=50000),重新编译之后,测试结果如下:
    这里写图片描述
    虽然该效率高于不自定义缓冲区的效率,但是其效率比起标C就要差一点了,所以选择一个合适的缓冲区尤为重要。

    展开全文
  • 【精讲】C语言库函数

    2019-02-25 18:29:24
    一、系统调用和库函数 1.系统调用 操作系统向用户提供的函数接口,通过这些函数接口进入内核空间,使用内核提供的功能 2.库函数 别人实现好的函数接口,使用者不需要自己实现,直接调用...fopen/fgetc/fgets/fread/...

    一、系统调用和库函数

    1.系统调用

    操作系统向用户提供的函数接口,通过这些函数接口进入内核空间,使用内核提供的功能

    2.库函数

    别人实现好的函数接口,使用者不需要自己实现,直接调用就可以

    • GNU C库(glibc)提供的函数接口

      open/read/write/lseek/close 这些函数接口直接和系统调用关联

    • 标准C库提供的函数接口:

      fopen/fgetc/fgets/fread/fputc/fputs/fwrite/fseek/ftell/rewind/fclose

    问题:库和实现的函数的代码有什么区别?

    实现的代码是一个文本文件,可见,可以被别人使用,安全性不好
    库是别人代码编译之后的二进制文件,不可见,可以被别人使用,安全性好
    

    二、Linux 下的库

    gcc编译流程:预处理、编译、汇编、链接(链接库和xxx.o文件生成一个可执行文件)

    1.动态库

       windows  : name.dll
    
       Linux : libname.so
    

    当编译器链接动态库的时候,会在可执行文件的头信息中记录库的名字,便于在操作系统执行这个可执行文件的时候,让操作系统去加载对应的动态库。

    注意:

    • 当操作执行可执行文件时候,会先读取可执行文件的头信息,然后加载头信息中记录的动态库到内存中运行
    • 在可执行文件中会调用一些函数接口,而这些函数接口并不是自己实现的,而是在动态库中实现的,所以这个程序在执行的时候,需要动态库

    2.静态库

      windows :  name.lib
    
      Linux   :  libname.a
    

    当编译器链接静态库的时候,如果在可执行文件中有调用静态库的函数接口,则会将静态库中实现好的函数接口代码拷贝到可执行文件中

    注意:

    • 由于链接的时候,需要将库函数接口实现代码拷贝到可执行文件中,所以生成可执行文件积较大
    • 由于可执行文件中有静态库中函数接口的实现代码,运行的时候不需要静态库

    3.链接静态库和动态库的优缺点

    • 动态库优点:
      多个程序链接同一个动态库的时候,在执行的时候只需要加载一次动态库,占用内存体积小

    • 动态库缺点:
      可执行程序在运行时候,没有动态库无法运行,必须让操作系统加载动态库

    • 静态库优点:
      可执行在执行的时候,不需要加载动态库,可以直接运行

    • 静态库优点:
      多个程序链接静态库的时候,需要拷贝多份静态库的代码,占用的内存较多

    4.制作动态库

    <1>.将file.c编译程file.o

    gcc -c file.c -o file.o 
    

    <2>.将file.o生成动态库

    gcc -shared file.o -o libfile.so 
    

    <3>.相关命令

    • A.查看文件中的符号信息
    nm  file.o   或 num libfile.so 
    
    • B.删除文件中的符号信息
    strip file.o  或 strip libfile.so 
    

    5.编译器链接库

    <1>告诉编译器头文件的路径

    -I 头文件路径
    

    注意:

    gcc编译器默认在/usr/include目录下寻找头文件
    

    <2>告诉编译器需要链接的库

    -L 库的路径  -l库名
    

    注意:

    • A. gcc编译器默认在/usr/lib和/lib目录下寻找需要链接库文件
    • B. gcc编译器默认只认识它自带的库,别人的库它不认识

    6.编译器错误解析

    linux@ubuntu:~/lib/dll-lib$ gcc main.c 
    main.c:2:18: fatal error: head.h: No such file or directory
    #include <head.h>
    	    ^
    compilation terminated.
    

    这个错误是因为编译器没有找到head.h头文件,我们可以将head.h拷贝到/usr/include目录(不推荐)

    通过 -I 指定头文件的路径

      linux@ubuntu:~/lib/dll-lib$ gcc main.c -I ./include/
    	/tmp/ccDMXNiG.o: In function `main':
    	main.c:(.text+0x19): undefined reference to `add'
    	main.c:(.text+0x3d): undefined reference to `sub'
    	collect2: error: ld returned 1 exit status
    

    这个错误是因为编译器没有找到add和sub函数所在的库文件

    解决方法是通过-L 指定库路径 -l指定库的名字

      linux@ubuntu:~/lib/dll-lib$ gcc main.c -I ./include/ -las
    	/usr/bin/ld: cannot find -las
    	collect2: error: ld returned 1 exit status
    

    这个错误是编译器没有找到libas.so库,我们

    可以通过-L 指定库路径让编译器找到它

    7.一些疑问

    问题1:

    编译器已经链接动态库成功,为什么操作系统运行程序的时候,还需要加载动态库?

    由于链接的是动态库,编译器并没有将需要的动态库中实现的函数接口代码拷贝到可执行程序中
    只是在可执行程序的头头信息中记录了动态库的名字,
    所以可执行程序执行的时候需要动态库此时操作系统会加载动态库
    

    问题2:

    编译器在链接动态库的时候,已经在可执行程序的头信息中记录了动态库的名字,如何查看?

    Linux 可执行程序可以看成如下结构
    	  |头信息(elf格式) |  
    	  |机器码          |
    	  
    查看的命令:
    	  readelf -a a.out | grep "Shared"
    

    问题3:

    操作系统为什么可以加载C库成功,而无法正确加载自己的动态库?

    因为操作加载动态库默认路径如下:
    - /lib 和 /usr/lib目录下去寻找
    - 在LD_LIBRARY_PATH环境变量记录的路径下寻找
    
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:自己库所在的路径
    

    8.制作静态库

    <1>.将file.c编译程file.o

    gcc -c file.c -o file.o 
    

    <2>.将file.o生成动态库

    ar  libfile.a  file.o 
    

    问题:

    如果动态和静态库同时存在,编译器在链接的时候,默认链接谁?

    默认链接动态库,如果想链接静态库则需要在编译的时候加上-static参数
    
    展开全文
  • 标准库函数 <stdio.h> fopen() 打开文件 fclose() 关闭文件 fprintf() 输出数据到文本文件中 sprintf() 输出数据到字符数组中 fscanf() 从文本文件中输入数据 feof() 检测是否达到文件末尾 fwrite() ...

    标准库函数
    <stdio.h>
    fopen() 打开文件
    fclose() 关闭文件
    fprintf() 输出数据到文本文件中
    sprintf() 输出数据到字符数组中
    fscanf() 从文本文件中输入数据
    feof() 检测是否达到文件末尾
    fwrite() 输出数据到二进制文件中
    fread() 从二进制文件中输入数据
    fseek() 移动文件读写“光标”

    <string.h>
    strcmp() 比较两个字符串是否相等
    strcpy() 复制字符串
    <math.h>
    abs() 求绝对值
    sqrt() 求算数平方根

    <stdlib.h>
    rand() 产生随机数
    srand() 设置随机数种子
    malloc() 分配内存空间
    free() 释放内存空间
    exit() 结束整个程序

    <time.h>
    time() 获取计算机当前的时间

    展开全文
  • 我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open()、close()、write()、read()等,而标准C语言库函数中也有一套对文件的操作函数fopen()、fclose()、fwrite()、fread()等....

    我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open()、close()、write()、read()等,而标准C语言的库函数中也有一套对文件的操作函数fopen()、fclose()、fwrite()、fread()等.。那么同样是对文件的操作函数,标C与UC有什么区别呢?是标C效率高还是UC效率高呢?今天就让我们来一探究竟。

    程序作用:将0~999999这1000000个整型数据写入文件。

    1、标准C实现大量数据写入文件:

    /*文件名test1.c*/
    #include<stdio.h>
    #include<stdlib.h>
    
    #define MAX 1000000
    
    int main (void)
    {
        FILE * fp = fopen("test1.txt","w");
        if(fp == NULL){
            perror("fopen test1.txt");
            exit(EXIT_FAILURE);
        }
    
        int i;
        for(i = 0; i < MAX; i++){
            fwrite(&i, sizeof(int), 1, fp);/*我们采用fwrite一个一个写入文件*/
        }
    
        fclose(fp);
        return 0;
    }
    /*gcc -o test1 test1.c编译*/

    写入文件的效率测试结果: 

    2、Linux系统函数实现大量数据写入文件:

    /*文件名test2.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<fcntl.h>
    
    #define MAX 1000000
    
    int main (void)
    {
        int fd = open("test2.txt",O_RDWR|O_TRUNC|O_CREAT,0666);
        /*O_RDWR可读可写,O_CREAT没有则新建,O_TRUNC覆盖写入(原有内容小清空),O_APPEND追加写入(原有内容不清空)*/
        if(fd == -1){
            perror("open test2.txt");
            exit(EXIT_FAILURE);
        }
    
        int i;
        for(i = 0; i < MAX; i++){
            write(fd, &i, sizeof(int));
        }
        close(fd);
        return 0;
    }
    /*gcc -o test2 test2.c编译*/

    写入效率测试结果: 

     

    我们发现系统函数的使用并没有使程序运行速率(写入速率)变快而是变慢了几十倍,而且在测试中,我们可以看见增加的时间基本都是在sys(系统层面)中增加的。这是因为,系统函数在用户层没有缓冲区,在内核层有缓冲区,但是缓冲区很小,所以大量数据在写入文件时,频繁刷新缓冲区降低了写入速率。所以系统函数(如write)需要加自定义缓冲区以提高速率,而标准C函数(如fwrite)不用自己设置缓冲区,如果系统函数用自定义缓冲区其效率比标C要好,不定义缓冲区则效率很低,但是缓冲区大小要合适,否则物极必反(即使有缓冲区,从缓冲区向文件中写也是一个一个写入的)。

    3、Linux系统函数实现大量数据写入文件修改:

    /*文件名test3.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<fcntl.h>
    
    #define MAX 1000000
    #define BUF_SIZE 500
    /*缓冲区大小,合适为宜,多少为合适需要自己测试,但是不同大小的缓冲区影响肯定是不同的*/
    int main (void)
    {
        int fd = open("test3.txt",O_RDWR|O_TRUNC|O_CREAT,0666);
        if(fd == -1){
            perror("open test3.txt");
            exit(EXIT_FAILURE);
        }
    
        int i;
        int buffer[BUF_SIZE] = {0};
        for(i = 0; i < MAX; i++){
            buffer[i%BUF_SIZE] = i;
            if(i%BUF_SIZE == BUF_SIZE-1)
                write(fd, buffer, sizeof(buffer));/*当缓冲区写满时向文件中写一次(刷新一次缓冲区)*/
        }
    
        close(fd);
        return 0;
    }
    /*gcc -o test3 test3.c编译*/

    写入效率测试结果: 

    加入自定义缓冲区后的测试发现,其效率比不加自定缓冲区要快100多倍,比标C写入速率也要快好几倍。如果缓冲区大小合适,其效率会提升更大。那么当我们将BUF_SZIE改为更大的值(BUF_SZIE=50000),重新编译之后,测试结果如下: 

    该效率又提高了,所以选择一个合适的缓冲区尤为重要。

    转自:https://www.cnblogs.com/zhangkele/p/9311427.html

    展开全文
  • C语言_标准I/O库

    2017-07-17 18:40:31
    文件操作标准I/O库函数: fopen、fread、fwrite、fclose、fflush、fseek、fgetc、getc、getchar、fputc、 putc、putchar、fgets、gets、printf、fprintf、sprintf、scanf、fscanf、sscanf、 fgetops、fsetops、ftell...
  • (1)open/read/write是系统调用,而fopen/fread/fwrite是C语言标准库函数,后者是对前者的封装,后者的可移植性比较好。(2)open/read/write是通过文件描述符对文件进行管理的,只能读取二进制文件或文本文件,而...
  •  在C语言中,文件操作都是由库函数来完成的。 在本章内将介绍主要的文件操作函数。 文件打开函数fopen  fopen函数用来打开一个文件,其调用的一般形式为: 文件指针名=fopen(文件名,使用文件方式) 其中,...
  • c语言文件练习

    2018-12-24 00:08:28
    c语言文件处理:C语言中没有输入输出语句,所有的输入输出功能都用 ANSI C提供的一组标准库函数来实现。文件操作标准库函数有: 文件的打开操作 fopen 打开一个文件 文件的关闭操作 fclose 关闭一个文件 文件的读写...
  • 一文件相关的系统调用 C语言标准库函数中有对文件的操作 fopen(),fwrite(),fread(),fclose();等   FILE *fd=fopen("./test.txt","w"); ...
  • fopen是ANSI C标准中的C语言库函数,在不同的操作系统中应该调用不同的内核API,UNIX环境下,fopen是对open的封装。 文件描述符是UNIX/Linux下的一个概念,Linux环境下,一切设备皆是文件,一切设备皆是以文件的...
  • 我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open()、close()、write()、read()等,而标准C语言库函数中也有一套对文件的操作函数fopen()、fclose()、fwrite()、fread()等....
  • 36_标准IO库介绍

    2018-03-18 21:09:23
    文件IO是Linux系统API标准IO是C语言库函数区别:c语言库函数是API封装而来,库函数多了一层封装,所以c库函数更好用一些。API在不同系统是不通用的,C库函数在所有系统是几乎一样的所以C库函数具有可移植性,而API不...
  • fwrite/fread 导致system 内存不断减少

    千次阅读 2014-01-06 16:23:04
    fopen是ANSI C标准中的C语言库函数,在不同的操作系统中应该调用不同的内核API,UNIX环境下,fopen是对open的封装。 文件描述符是UNIX/Linux下的一个概念,Linux环境下,一切设备皆是文件,一切设备皆是以文件的...
  • open/read/write和fopen/fread/fwrite的区别   open:系统调用,返回...fopen是ANSI C标准中的C语言库函数,在不同的操作系统中应该调用不同的内核API,UNIX环境下,fopen是对open的封装。 文件描述符是UNIX/Linux
  • fopen是ANSI C标准中的C语言库函数,在不同的操作系统中应该调用不同的内核API,UNIX环境下,fopen是对open的封装。 文件描述符是UNIX/Linux下的一个概念,linux环境下,一切设备皆是文件,一切设备皆是以文件的...
  • 1.c语言标准库函数进行文件操作  打开文件:fopen 关闭文件:fclose 读取文件:fgetc、fread、fscan 写入文件:fputc、fwrite、fprintf 文件定位:rewind、fseek 2.windowsAPI操作文件  创建文件:...
  • open:系统调用,返回的是文件描述符,即文件句柄,是文件在文件描述副表里的索引。...fopen是ANSI C标准中的C语言库函数,在不同的操作系统中应该调用不同的内核API,UNIX环境下,fopen是对o
  • 回顾C语言库函数 fopen,fread,fwrite,fseek,fclose这几个函数。关键在于参数的使用。 例如fopen,FILE *fopen(const char *path, const char *mode),在不同的模式下打开文件所能作的操作也不同。 文件使用...
  • C语言进阶要点笔记5

    2020-01-28 22:29:53
    目录 八、文件 1、行缓冲 2、全缓冲 3、无缓冲 4、文件指针 5、打开文件 6、关闭文件 ...标准io库函数往屏幕输出东西的时候是有行缓冲的,只有遇到换行符的时候才刷新缓冲区;以下情况刷新缓冲区:...

空空如也

空空如也

1 2 3 4
收藏数 65
精华内容 26
关键字:

c语言标准库函数fread

c语言 订阅