主页 > 创业  > 

Linux——库函数

Linux——库函数
一、基本概念

文件:     一组相关数据的集合  文件名:     01.sh //文件名 

流:

         流是指数据在程序或系统中的流动方式。在Linux中,数据流通常通过文件描述符(File Descriptors)进行管理。文件描述符是一个非负整数,用于标识打开的文件或输入/输出资源。

二、linux下的文件类型 

  b block         块设备文件   eg: 硬盘    c character     字符设备文件 eg: 鼠标,键盘   d directory     目录文件     eg: 文件夹    - regular       常规文件     eg: 1.txt 01.sh xx.bmp    l symblink      软链接       eg: 快捷方式   s socket        套接字       eg: 网络通信用   p pipe          管道         eg: 进程间通信   

三、思想

  linux中一个核心设计思想    everything is file!     //一切皆文件 

四、 linux操作文件的函数

   两套函数 (两套操作路径

       (一)库函数  

               --- 第三方提供的函数   

 集成了很多功能函数      //标准输入输出      //数学函数 

   (二)系统调用

               --- 内核提供的函数  

(三)标准io的概念 

1975 Dennis r IO库,     从C语言的标准,ANSI c      IO  input  output     I: 键盘是标准输入设备 ====》默认输入就是指键盘  /dev/input     O: 显示器是标准输出设备 ==》默认输出就是指显示器          Linux操作系统当中IO都是对文件的操作     C一部分,任何支持标准C的系统都可使用标准IO实现文件存储     标准IO在UNIX上是对文件IO的封装         一般都是对普通文件操作是一种有缓存的IO 在文件IO和用户程序之间,     加入缓冲区,可以有效减少系统调用的次数,节省系统IO调度资源          说明:     标准IO库,不单单是linux上有,在windows,Mac os上都有。     很多操作系统都实现了标准IO库。     都是依据IOS C标准实现的。     所以基本保证了可移植性。     但是因为标准和具体实现之间的差异,     未必敢保证所有的函数在都可以相互通用。          标准IO都干了些啥?     标准IO处理了很多细节:     (1).处理缓冲区分配   (缓存--提高效率 --- 慢速 快速)     (2).读写IO的块长度的优化     (3).对系统调用进行了封装,内部对应的"文件描述符"           好处:         用户使用方便,不必再担心如何选择正确的块长度。     //地位:         标准I/O库是由 Dennis Ritchie在1975年左右编写的。         它是Mike Lesk编写的可移植I/O库的主要修改版本。         令人惊讶的是,50年来,几乎没有对标准I/O库进行修改。

五、函数接口

(一)fopen

FILE * fopen(const char *pathname,const char *mode);   功能:          流打开函数   参数:      @pathname --- 要打开的文件名 //字符串形式的名字       @mode     --- 打开的模式         r   --- 只读          r+  --- 读写                 说明: 带r的 要求,文件必须存在 ,如果不存在,就会报错        w   --- 只写         w+  --- 读写                 说明:                      文件存在 ,截断成 0长度                     不存在,则创建        a  --- 追加(写)        a+ --- 读写                说明:                  读 从头读                   写 从末尾开始写                   文件存在 则打开做写操作即可                   文件不存在 创建文件    返回值:      成功 FILE*指针  //文件指针 流指针 --- 从程序上讲,FILE *指针就代表打开的这个文件      失败 NULL 同时 errno会被设置   

#include<stdio.h> #include<errno.h> int main(int argc, const char *argv[]) { if (argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } FILE *fp = fopen(argv[1],"w+"); // FILE *fp = fopen(argv[1],"r+"); if(fp == NULL) { printf("fopen fail\n"); return -1; } // printf ("fopen success!\n"); return 0; } (二)perror

void perror(const char *s);

#include<stdio.h> #include<errno.h> int main(int argc, const char *argv[]) { if (argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } FILE *fp = fopen(argv[1],"r"); if(fp == NULL) { perror("fopen fail"); return -1; } printf ("fopen success!\n"); return 0; }

(三)fgetc  、fputc

1、 int fgetc(FILE * stream);

 功能:      从文件中读取字符   参数:      @stream 表示要读取的文件对应的流指针   返回值:      成功 对应字符的ASCII码值       失败 EOF 到达文件结尾            出错 

 2、int fputc(int c,FILE *stream);

  功能:       将一个字符输出到指定的流(文件)   参数:     @c          //要输出的字符 ---ascii码值     @stream     //指定的文件    返回值:       成功 被写入的字符的ASCII码值     失败 EOF   

 问题:    EOF      文件中有没有 EOF?  //只是到达结尾时的一个标志

#include<stdio.h> #include<errno.h> //类似cat功能 int main(int argc, const char *argv[]) { //处理命令行参数 if (argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } //1.打开文件 FILE *fp = fopen(argv[1],"r+"); if(fp == NULL) { perror("fopen fail"); return -1; } //2.读写数据 int ret; while((ret = fgetc(fp)) != EOF) { fputc(ret,stdout); //printf("%c",ret); } //3.关闭 fclose(fp); return 0; }

     系统默认打开的流指针: stdin  //标准输入  stdout //标准输出  stderr //标准出错 --- 屏幕  --- 可以专门把错误信息输出到 stderr 

#include<stdio.h> int main(int argc, const char *argv[]) { int ret; while ( (ret = fgetc(stdin)) != EOF) fputc(ret,stdout); return 0; } (四)fclose

int fclose(FILE *stream);   功能:      关闭文件        刷新流       关闭了底层文件描述符  返回值:    成功 0    失败 EOF    注意,不要多次重复关闭

(五)fgets、fputs 1、char * fgets(char*s,int size,FILE*stream)

功能:    从stream中读取size-1个字符,到s指向的空间  参数:   @s        //存放读取到的数据 对应的内存空间    @size     //指定一次最多读取多少个字符    @stream   //表示要读取的文件  返回值:    成功 返回s    失败 NULL          读到文件结尾 也 返回NULL 

注意:    fgets读取结束:    1. EOF    2. '\n'    3. size-1

 练习:      统计文件行数 

#include<stdio.h> #include<errno.h> #include<string.h> int main(int argc, const char *argv[]) { if(argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } FILE *fp = fopen(argv[1],"r+"); if(fp == NULL) { perror("fopen fail"); return -1; } char buf[1024]; int n = 0; while (fgets(buf,sizeof(buf),fp)) { if(buf[strlen(buf) - 1] == '\n') { n++; } } printf("%d\n",n); fclose(fp); return 0; }

2、int fputs(const char *s, FILE *stream);

 功能:       输出s到stream中    参数:     @s 代表要输出的字符串      @stream 代表 输出到的文件     返回值:     成功 非负数      失败 EOF

 注意:      不会将 '\0' 输出 

练习:       cat //fgets实现cat 

#include<stdio.h> #include<errno.h> //类似cat功能 int main(int argc, const char *argv[]) { //处理命令行参数 if (argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } //1.打开文件 FILE *fp = fopen(argv[1],"r+"); if(fp == NULL) { perror("fopen fail"); return -1; } //2.读写数据 int ret; while((ret = fgetc(fp)) != EOF) { fputc(ret,stdout); //printf("%c",ret); } //3.关闭 fclose(fp); return 0; }

cp_fputsfgets.c 

#include<stdio.h> #include<errno.h> int main(int argc, const char *argv[]) { if (argc != 3) { printf("Usage: %s <filename>\n",argv[0]); return -1; } FILE *fp = fopen(argv[1],"r"); FILE *srt = fopen(argv[2],"w"); if(fp == NULL || srt == NULL) { printf("fopen fail\n"); return -1; } char buf[1024]; while(fgets(buf,1024,fp) != NULL) { fputs(buf,srt); } fclose(fp); fclose(srt); return 0; }

"123" --- 文本文件 --- '1''2''3'  //每个数据是按照固定的编码格式存放的 -ASCII  123   --- 二进制   --- 01111011   //    linux下操作时 ,没有区别   windows下区别     说明:     1.fgets 和 fputs 在拷贝 二进制文件时 可能出问题 

(六)fread / fwrite

fread/fwrite //二进制读写函数 按对象读写

1、size_t  fread(      void *ptr, size_t size, size_t nmemb, FILE *stream); 2、size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:      二进制流的读/写 参数:    @ptr   表示存放数据的空间的地址     @size  要操作的单个元素(对象)的大小    @nmemb 要操作的元素(对象)的个数     @stream 要操作的文件  返回值:    成功 返回的是 成功操作到的对象的个数     失败 0      到达文件结尾 返回 0       应用:    主要 应用在 文件中 有固定格式的  场景   

#include<stdio.h> int main(int argc, const char *argv[]) { char buf[10]; int ret = fread(buf,sizeof(char),10,stdin); printf("ret = %d\n",ret); fwrite(buf,sizeof(char),ret,stdout); putchar('\n'); return 0; }

练习:    将3个学生的信息,写到文件中     之后,    从文件中读出学生信息,打印

#include<stdio.h> typedef struct stu { char name[20]; int sno; float score; }stu_t; int main(int argc, const char *argv[]) { stu_t s[3] = {{"tom",110,99}, {"liam",111,98}, {"beta",112,99}}; FILE *fp = fopen("stu.txt","w+"); if(fp == NULL) { perror("fopen fail"); return -1; } fwrite(s,sizeof(stu_t),3,fp); rewind(fp); stu_t s1[3]; fread(s1,sizeof(stu_t),3,fp); int i = 0; for(i = 0;i < 3;i++) { printf("name = %s\n",s1[i].name); printf("sno = %d\n",s1[i].sno); printf("score = %.2f\n",s1[i].score); } fclose(fp); return 0; }

cat_fread_fwrite.c

#include<stdio.h> int main(int argc, const char *argv[]) { if(argc != 2) { printf("Usag: %s <filename>\n",argv[0]); } FILE *fp = fopen(argv[1],"r"); if(fp == NULL) { perror("fopen fail"); return -1; } char buf[1024]; int ret = 0; while(ret =fread(buf,sizeof(char),1024,fp)) fwrite(buf,sizeof(char),ret,stdout); fclose(fp); putchar('\n'); return 0; } (七)文件偏移量  rewind

int  fseek(FILE* stream,long offset,int whence);    功能:        定位文件     参数:       @stream  表示要操作文件        @offset  表示文件偏移量        @whence  定位的参考点                 SEEK_SET //相对于文件开头的                    offset >=0                 SEEK_CUR //相对于当前位置                   offset>=0                   offset<0   //不能超过这个文件开头                SEEK_END //相对于文件末尾                    offset < 0  //不能超过这个文件开头                   offset >= 0 //可以  --- 创建 空洞 文件    返回值:       成功 0       失败 -1  

fseek(fp,100,SEEK_SET);// fseek(fp,0,SEEK_SET);//定位到开头 fseek(fp,0,SEEK_END);//定位到末尾

应用:

 创建空洞文件:       1.做偏移       2.写操作

#include<stdio.h> int main(int argc, const char *argv[]) { if(argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } FILE *fp = fopen(argv[1],"r"); if(fp == NULL) { perror("file fail"); return -1; } if(fseek(fp,100,SEEK_END) != 0) { perror("fseek fail"); return -1; } fputc('A',fp); fclose(fp); return 0; } (八)   long ftell(FILE*stream);

功能:        获得当前文件的偏移量     void rewind(FILE*stream);    功能:        将文件偏移量设置到文件开头 

         获得某个文件的大小:   1. fseek(fp,0,SEEK_END);//定位到末尾   2. long len =ftell(fp); 

              实现 cp功能

#include<stdio.h> int main(int argc, const char *argv[]) { if(argc != 3) { printf("Usage: %s <src> <dest>\n",argv[0]); return -1; } FILE *fp1 = fopen(argv[1],"r"); if(fp1 == NULL) { perror("file fail"); return -1; } fseek(fp1,0,SEEK_END); long len = ftell(fp1); FILE *fp2 = fopen(argv[2],"w"); if(fp2 ==NULL) { perror("file fail"); return -1; } fseek(fp2,len-1,SEEK_SET); fputc('\0',fp2); rewind(fp1); rewind(fp2); char buf[len]; fread(buf,sizeof(buf),1,fp1); fwrite(buf,sizeof(buf),1,fp2); fclose(fp1); fclose(fp2); return 0; }

六、缓存

缓存 设计的目的提高效率   本质上来说 ---缓存其实就是一块内存空间

行缓冲,1k, terminal,主要用于人机交互stdout          缓存区满或者遇到\n刷新    1024                 行缓存多是关于终端的一些操作                 1.遇到\n刷新                 2.缓存区满刷新                 3.程序结束刷新                 4.fflush刷新  fflush(stdout);                  全缓冲,4k,主要用于文件的读写     缓存区满刷新缓存区 4096             对普通文件进行标准IO操作,建立             的缓存一般为全缓存             刷新条件:                 1.缓存区满刷新                 2.程序结束刷新                 3.fflush来刷新  fflush(fp); 无缓冲,0k  主要用于出错处理信息的输出 stderr      不对数据缓存直接刷新     printf();==>>stdout      fprintf(strerr,"fopen error %s",filename);                 界面交互    出错处理

./a.out < main.c   //< 表示输入重定向  ./a.out > main.c   //> 表示输出重定向 

七、作业

1、统计一个文件中出现英文字母出现的次数

#include<stdio.h> #include<fcntl.h> #include<unistd.h> int main(int argc, const char *argv[]) { if(argc != 2) { printf("Usage: %s <filename>\n",argv[0]); return -1; } int fd = open(argv[1],O_RDONLY); if(fd < 0) { perror("file fail"); return -1; } unsigned char ch; int n[26] = {0}; while(read(fd,&ch,1) != 0) { if(ch >= 'a' && ch <= 'z') { n[ch - 'a']++; } else if(ch >= 'A' && ch <= 'Z') { n[ch - 'A']++; } } int i = 0; for(i = 0;i < 26;i++) { printf("%c:%d\n",i+'a',n[i]); } close(fd); return 0; }

二、完成两个图片的拼接

把第一个有色点写入第二个文件,使第二个文件和第三个文件的图片一样

#include<stdio.h> #include<stdlib.h> #pragma pack(1) //保证结构体的紧凑,编译器指令,控制成员的对齐方式为按1字节对齐 typedef struct { unsigned char b; unsigned char g; unsigned char r; } pixel; int pixel_white(pixel p) { return (p.r == 255 && p.g == 255 && p.b == 255); } int main(int argc, const char *argv[]) { //参数检查 if(argc != 3) { printf("Usage: %s <file1.bmp> <file2.bmp>\n",argv[0]); return -1; } //打开文件(进入二进制读写模式) FILE *fp1 = fopen(argv[1],"rb+"); FILE *fp2 = fopen(argv[2],"rb+"); if(fp1 == NULL || fp2 == NULL) { perror("file fail"); return -1; } //跳过54字节头文件 if(fseek(fp1,54,SEEK_SET ) || fseek(fp2,54,SEEK_SET)) { perror("fseek fail"); return -1; } //读取并比较像素 pixel p1,p2; long pos = 54; //记录当前文件位置 while(1) { size_t read1 = fread(&p1,sizeof(pixel),1,fp1); size_t read2 = fread(&p2,sizeof(pixel),1,fp2); if(read1 != 1 || read2 != 1) break; if(pixel_white(p2)) { fseek(fp2,pos,SEEK_SET); //回退文件指针 fwrite(&p1,sizeof(pixel),1,fp2); fflush(fp2); } pos += sizeof(pixel); //更新位置 } fclose(fp1); fclose(fp2); return 0; }

把两个图片拼接成第三个

#include <stdio.h> // ./a.out 1.bmp 2.bmp 3.bmp int main(int argc, const char *argv[]) { if (argc != 4) { printf("usage: %s <src1.bmp> <src2.bmp> <dest.bmp>\n", argv[0]); return -1; } FILE *fp1 = fopen(argv[1], "r"); FILE *fp2 = fopen(argv[2], "r"); FILE *fp3 = fopen(argv[3], "w"); if (fp1 == NULL || fp2 == NULL || fp3 == NULL) { perror("open fail"); return -1; } unsigned char head1[54]; unsigned char head2[54]; unsigned char body1[600*800*3]; unsigned char body2[600*800*3]; fread(head1, sizeof(unsigned char), 54, fp1); fread(body1, sizeof(unsigned char), 600*800*3, fp1); fread(head2, sizeof(unsigned char), 54, fp2); fread(body2, sizeof(unsigned char), 600*800*3, fp2); int i = 0; for (i = 0; i < 600 * 800 * 3; ++i) { if (!((body1[i] == 255 && body1[i+1] == 255 && body1[i+2] == 255)) { body2[i] = body1[i]; body2[i+1] = body1[i+1]; body2[i+2] = body1[i+2]; } } fwrite(head2, sizeof(char), 54, fp3); fwrite(body2, sizeof(char), 600*800*3, fp3); fclose(fp1); fclose(fp2); fclose(fp3); return 0; }

标签:

Linux——库函数由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Linux——库函数