Linux C 文件操作函数(~上善止水~)
翻翻笔记,整理一下 C 语言中的文件操作函数 ~~~~~~,多注意细节,maybe 细节决定成败~
1. fopen
/* fopen(打开文件) * * 相关函数 open,fclose * * 表头文件 #include<stdio.h> * * 函数原型 FILE * fopen(const char * path,const char * mode); * * 函数说明: * path 字符串包含欲打开的文件路径及文件名 * mode 字符串则代表着流形态 * * mode 有下列几种形态字符串: * * r 打开只读文件,该文件必须存在。 * * r+ 打开可读写的文件,该文件必须存在。 * * w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失, * 若文件不存在则建立该文件。 * * w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失, * 若文件不存在则建立该文件。 * * a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件 * 存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。 * * a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文 * 件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 */
上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库打开的文件为二进制文件,
而非纯文字文件。不过在POSIX系统,包含Linux都会忽略该字符。由fopen()所建立的新文件会具
有 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask值。
返回值
文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并把错误代码存在errno 中。
附加说明
一般而言,打开文件后会作一些文件读取或写入的动作,若开文件失败,接下来的读写动作也无法顺利进行,
所以在fopen()后请作错误判断及处理。
实例:
1 #include<stdio.h> 2 3 int main(int argc, char *argv[]) 4 { 5 FILE * fp; 6 7 fp=fopen("noexist","a+"); 8 if(NULL == fp) return; 9 10 fclose(fp); 11 }
2. fprintf
这里先对经常用的几个printf系列函数做个了解,
printf: 就是标准输出,在屏幕上打印出一段字符串来
sprintf:把格式化的数据写入到某个子符串中,返回值字符串的长度
fprintf: 用于文件操作
/* 功能:传送格式化输出到一个文件中/或标准输出 * * 表头文件:#include<stdio.h> * * 函数原型:int fprintf(FILE *stream, char *format[, argument,...]); * * 参数: * FILE* 一个FILE型的指针 * char* 格式化输入函数,和printf里的格式一样 * * 返回值: * 成功时返回转换的字节数,失败时返回一个负数 */
实例一:文件操作
#include <stdio.h> #include <stdlib.h> #include <error.h> int main(int argc, char *argv[]) { FILE *fp = NULL; char str[] = "hello world"; fp = fopen("tt.txt","a+"); // 若文件存现追加在尾部,不存在就会创建tt.txt if(NULL == fp) { perror("fopen error!"); exit(-1); } fprintf(fp,"%s\n",str); // 格式化写入 fclose(fp); return 0; }
实例二:输出到终端上,这是fprintf 常见的一种操作
static void usage(void) { fprintf(stderr, "webbench [option]... URL\n" " -f|--force Don't wait for reply from server.\n" " -r|--reload Send reload request - Pragma: no-cache.\n" " -t|--time <sec> Run benchmark for <sec> seconds. Default 30.\n" " -p|--proxy <server:port> Use proxy server for request.\n" " -c|--clients <n> Run <n> HTTP clients at once. Default one.\n" " -9|--http09 Use HTTP/0.9 style requests.\n" " -1|--http10 Use HTTP/1.0 protocol.\n" " -2|--http11 Use HTTP/1.1 protocol.\n" " --get Use GET request method.\n" " --head Use HEAD request method.\n" " --options Use OPTIONS request method.\n" " --trace Use TRACE request method.\n" " -?|-h|--help This information.\n" " -V|--version Display program version.\n" ); }
插曲:stderr 和 stdout 有别
#include <stdio.h> extern FILE *stdin; // 标准输入 extern FILE *stdout; // 标准输出 extern FILE *stderr; // 标准错误
我们知道,标准输出和标准错误默认都是将信息输出到终端,那说他们有别,区别在哪里?我们看个题目
问题:下面程序的输出是什么?
1 #include <stdio.h> 2 3 4 int main() 5 { 6 fprintf(stdout, "Hello "); 7 fprintf(stderr, "World!"); 8 9 return 0; 10 }
答:输出结果是 World!Hello,为什么不是Hello World! 呢???
解释:在默认情况下,stdout 是行缓冲的,它的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。而 stderr 是无缓冲的,
会直接输出,举例来说就是 printf(stdout,"xxx");和 printf(stderr, "xxx\n");前者会憋住,直到遇到新行才一起输出,而后者不管有么"\n"都输出。
再看一题:
这 3 句效果不是一样嘛,有什么区别?
#include <stdio.h> int main() { fprintf(stderr, "stderr->Hello world!\n"); fprintf(stdout, "stdout->Hello world!\n"); printf("printf->Hello world!\n"); return 0; }
有区别:
stdout -- 标准输出设备(printf("..."))同stdout
stderr -- 标准错误输出设备
两者默认向屏幕输出,但如果定向输出到磁盘文件的时候,就可看出两者的区别,stdout 输出到磁盘文件,stderr 在屏幕。
直接运行:
定向到磁盘文件:
3. fscanf
/* * 功能:从一个流中执行格式化输入 * * 表头文件:#include<stdio.h> * * 函数原型:int fscanf(FILE *stream, char *format[,argument...]); * * 参数解释: * FILE* 一个FILE型的指针 * char* 格式化输出函数,和scanf里的格式一样 * 返回值: * 成功时返回转换的字节数,失败时返回一个负数 */
fp = fopen("/local/test.c","a+"); if(NULL == fp) { // fopen 后要做错误判断 perror("fopen error!"); exit(-1); } fscanf(fp,"%s",str);
4. clearerr
/* * 功能:清除文件流的错误旗标 * * 相关函数 feof * * 表头文件 #include<stdio.h> * 函数原型:void clearerr(FILE * stream); * * 函数说明 clearerr()清除参数stream指定的文件流所使用的错误旗标。 */
5. fclose
/* * 功能:关闭文件 * * 相关函数 close,fflush,fopen,setbuf * * 表头文件 #include<stdio.h> * * 定义函数 int fclose(FILE * stream); * * 函数说明 * fclose()用来关闭先前fopen()打开的文件。此动作会让缓冲区内的数据写入文件中, * 并释放系统* 所提供的文件资源。 * * 返回值 * 若关文件动作成功则返回0,有错误发生时则返回EOF并把错误代码存到errno。 * * 错误代码 * EBADF表示参数stream非已打开的文件。 * 范例 请参考fopen() */
6. fdopen
/* 功能:将文件描述词转为文件指针 相关函数 fopen,open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fdopen(int fildes,const char * mode); 函数说明 fdopen()会将参数fildes 的文件描述词,转换为对应的文件指针后返回。参数mode 字符串则代表着文件指针的流形态,此形态必须和原先文件描述词读写模式相同。 关于mode 字符串格式请参考fopen()。 返回值 转换成功时返回指向该流的文件指针。失败则返回NULL,并把错误代码存在errno中。 */ #include<stdio.h> int main() { FILE * fp =fdopen(0,"w+"); fprintf(fp,"%s/n","hello!"); fclose(fp); }
7. feof
/* 功能:检查文件流是否读到了文件尾 相关函数 fopen,fgetc,fgets,fread 表头文件 #include<stdio.h> 定义函数 int feof(FILE * stream); 函数说明 feof()用来侦测是否读取到了文件尾,尾数stream为fopen()所返回之文件指针。 如果已到文件尾则返回非零值,其他情况返回0。 返回值 返回非零值代表已到达文件尾。 */
8. fflush
/* 功能:更新缓冲区 相关函数 write,fopen,fclose,setbuf 表头文件 #include<stdio.h> 定义函数 int fflush(FILE* stream); 函数说明 fflush()会强迫将缓冲区内的数据写回参数stream指定的文件中。如果参数stream为NULL, fflush()会将所有打开的文件数据更新。 返回值 成功返回0,失败返回EOF,错误代码存于errno中。 错误代码 EBADF 参数stream 指定的文件未被打开,或打开状态为只读。其它错误代码参考write()。 */
9. fgetc
/* 功能:由文件中读取一个字符 相关函数 open,fread,fscanf,getc 表头文件 include<stdio.h> 定义函数 int fgetc(FILE * stream); 函数说明 fgetc()从参数stream所指的文件中读取一个字符。若读到文件尾而无数据时便返回EOF。 返回值 getc()会返回读取到的字符,若返回EOF则表示到了文件尾。 范例 复制代码 代码如下: */ #include<stdio.h> #include <errno.h> #include <stdlib.h> int main() { FILE *fp = NULL; int c; fp=fopen("exist","r"); if(NULL == fp) { perror("fopen error!"); exit(-1); } while((c=fgetc(fp))!=EOF) printf("%c",c); fclose(fp); return 0; }
10. fgets
/* 功能:由文件中读取一字符串 相关函数 open,fread,fscanf,getc 表头文件 include<stdio.h> 定义函数 char *fgets(char * s,int size,FILE * stream); 函数说明 fgets()用来从参数stream所指的文件内读入字符并存到参数s所指的内存空间, 直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束。 返回值 gets()若成功则返回s指针,返回NULL则表示有错误发生。 */ #include<stdio.h> #include <errno.h> #include <stdlib.h> int main() { char s[80]; puts(fgets(s,80,stdin),stdout); return 0; } /*执行结果*/ //this is a test /*输入*/ //this is a test /*输出*/
11. fileno
/* 功能:返回文件流所使用的文件描述词 相关函数 open,fopen 表头文件 #include<stdio.h> 定义函数 int fileno(FILE * stream); 函数说明 fileno()用来取得参数stream指定的文件流所使用的文件描述词。 返回值 返回文件描述词。 */ #include<stdio.h> #include <errno.h> #include <stdlib.h> int main() { FILE * fp = NULL; int fd; fp=fopen("/etc/passwd","r"); if(NULL == fp) { perror("fopen error!"); exit(-1); } fd=fileno(fp); printf("fd=%d/n",fd); // fd = 3 fclose(fp); return 0; }
12. fputc
/* 功能:将一指定字符写入文件流中 相关函数 fopen,fwrite,fscanf,putc 表头文件 #include<stdio.h> 定义函数 int fputc(int c,FILE * stream); 函数说明 fputc 会将参数c 转为unsigned char 后写入参数stream 指定的文件中。 返回值 fputc()会返回写入成功的字符,即参数c。若返回EOF则代表写入失败。 */ #include<stdio.h> #include <errno.h> #include <stdlib.h> int main() { FILE * fp = NULL; char a[26]="abcdefghijklmnopqrstuvwxyz"; int i; fp= fopen("tmp.txt","w"); if(NULL == fp) { perror("fopen error!"); exit(-1); } for(i = 0; i < 26; i++) fputc(a[i],fp); fclose(fp); return 0; }
13. fputs
/* 功能:将一指定的字符串写入文件内 相关函数 fopen,fwrite,fscanf,fputc,putc 表头文件 #include<stdio.h> 定义函数 int fputs(const char * s,FILE * stream); 函数说明 fputs()用来将参数s所指的字符串写入到参数stream所指的文件内。 返回值 若成功则返回写出的字符个数,返回EOF则表示有错误发生。 范例 请参考fgets()。 */
14. fread
/* 功能:从文件流读取数据 相关函数 fopen,fwrite,fseek,fscanf 表头文件 #include<stdio.h> 定义函数 size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream); 函数说明 fread()用来从文件流中读取数据。参数stream为已打开的文件指针,参数ptr 指向欲存放读取进来的数据空间,读取的字符数以参数size*nmemb来决定。 fread()会返回实际读取到的nmemb数目,如果此值比参数nmemb来得小,则代表可能 读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。 返回值 返回实际读取到的nmemb数目。 */ #include<stdio.h> #include <errno.h> #include <stdlib.h> int main() { FILE * stream = NULL;char str[10]; stream = fopen("tmp.txt","r"); if(NULL == stream) { perror("fopen error!"); exit(-1); } fread(str,sizeof(str),1,stream); // 读 10个字节 printf("str = [%s]\n", str); fclose(stream); return 0; }
15. freopen
/* 功能:打开文件 相关函数 fopen,fclose 表头文件 #include<stdio.h> 定义函数 FILE * freopen(const char * path, const char * mode, FILE * stream); 函数说明 path 字符串包含欲打开的文件路径及文件名,参数mode请参考fopen()说明。 stream 为已打开的文件指针。freopen()会将原stream所打开的文件流关闭,然后打开参数path的文件。 返回值 文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno 中。 */ #include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { FILE * fp = NULL; fp=fopen("/etc/passwd","r"); if(NULL == fp) { perror("fopen error!"); exit(-1); } fp=freopen("/etc/group","r",fp); fclose(fp); return 0; }
16. fseek
/* 功能:移动文件流的读写位置 相关函数 rewind,ftell,fgetpos,fsetpos,lseek 表头文件 #include<stdio.h> 定义函数 int fseek(FILE * stream, long offset, int whence); 函数说明 fseek()用来移动文件流的读写位置。 参数:stream为已打开的文件指针, 参数:offset为根据参数whence来移动读写位置的位移数。 参数:whence为下列其中一种: SEEK_SET 从距文件开头offset位移量为新的读写位置。 SEEK_CUR 以目前的读写位置往后增加offset个位移量。 SEEK_END 将读写位置指向文件尾后再增加offset个位移量。 当whence值为SEEK_CUR 或SEEK_END时,参数offset允许负值的出现。 下列是较特别的使用方式: 1) 欲将读写位置移动到文件开头时: fseek(FILE *stream,0,SEEK_SET); 2) 欲将读写位置移动到文件尾时: fseek(FILE *stream,0,0SEEK_END); 返回值 当调用成功时则返回0,若有错误则返回-1,errno会存放错误代码。 附加说明 fseek()不像lseek()会返回读写位置,因此必须使用ftell()来取得目前读写的位置。 */ #include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { FILE * stream; long offset; fpos_t pos; // pos 是一个fpos_t类型的结构体 stream=fopen("/etc/passwd","r"); if(NULL == stream) { perror("fopen error!"); exit(-1); } fseek(stream,5,SEEK_SET); printf("offset=%d\n",ftell(stream)); rewind(stream); // rewind 函数->使文件位置标记指向文件开头 fgetpos(stream,&pos); printf("offset=%d\n",pos);
// pos = 10; // 编译器提示:error:incompatible type when assigning to type 'fpos_t'
// from type 'int'
pos.__pos = 10; // 正确 给fpos_t 类型的变量赋值 fsetpos(stream,&pos); printf("offset = %d\n",ftell(stream)); fclose(stream); return 0; } /*打印输出*/ // offset=5 // offset=0 // offset = 10
补充:如何给 fpos_t 类型的变量赋值
我们在上面fseek的实例中用到另外两个函数 fgetpos 和 fsetpos, 我们看一下两个函数的原型
/* * 头文件:#include <stdio.h> * * 函数fgetpos * 是获取strerm 当前的指针所指的位置并把该指针所指的位置数 * 存放到pos所值得对象中。pos值以内部格式存储。 * * 函数fsetpos * 是设置stream文件的读写指针到pos * * 参数: * stream: 指向文件的文件指针 * pos: fpos_t 类型的结构体 * */ // 函数原型 int fgetpos(FILE *stream, fpos_t *pos); int fsetpos(FILE *stream, fpos_t *pos); // fpos_t 结构体 typedef struct { __off_t __pos; __mbstate_t __state; }_G_fpos_t;
所以我们在上面 fseek 实例总,定义了 fpos_t pos; 在给pos赋值的时候,不能直接 pos = 10;(但是网上很多例子都是直接这样赋值),
正确的赋值应该是:pos.__pos = 10;
17. ftell
/* 功能:取得文件流的读取位置 相关函数 fseek,rewind,fgetpos,fsetpos 表头文件 #include <stdio.h> 定义函数 long ftell(FILE * stream); 函数说明 ftell()用来取得文件流目前的读写位置。参数stream为已打开的文件指针。 返回值 当调用成功时则返回目前的读写位置,若有错误则返回-1,errno会存放错误代码。 错误代码 EBADF 参数stream无效或可移动读写位置的文件流。 范例 参考fseek()。 */
18. fwrite
/* 功能:将数据写至文件流 相关函数 fopen,fread,fseek,fscanf 表头文件 #include <stdio.h> 定义函数 size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream); 函数说明 fwrite()用来将数据写入文件流中。 参数说明 stream 为已打开的文件指针, ptr 指向欲写入的数据地址, size 总共写入的字符数以参数size*nmemb来决定。fwrite()会返回实际写入的nmemb数目。 返回值 返回实际写入的nmemb数目。 */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #define nmemb 3 typedef struct test { char name[20]; int size; }TEST; #define set_s(x,y) \ strcpy(s[x].name,y); \ s[x].size = strlen(y); int main() { FILE * stream = NULL; TEST s[3]; // 结构体数组 set_s(0, "Linux!"); set_s(1, "unix!"); set_s(2, "Window!"); stream = fopen("tmp.txt","w"); if(NULL == stream) { perror("fopen error!"); exit(-1); } fwrite(s,sizeof(struct test),nmemb,stream); fclose(stream); return 0; }
19. getc
/* 功能:由文件中读取一个字符 相关函数 read,fopen,fread,fgetc 表头文件 #include <stdio.h> 定义函数 int getc(FILE * stream); 函数说明 getc()用来从参数stream所指的文件中读取一个字符。若读到文件尾而无数据时便返回EOF。 虽然getc()与fgetc()作用相同,但getc()为宏定义,非真正的函数调用。 返回值 getc()会返回读取到的字符,若返回EOF则表示到了文件尾。 范例 参考fgetc()。 */
20. getchar
/* 功能:由标准输入设备内读进一字符 相关函数 fopen,fread,fscanf,getc 表头文件 #include <stdio.h> 定义函数 int getchar(void); 函数说明 getchar()用来从标准输入设备中读取一个字符。然后将该字符从unsigned char转换成int后返回。 返回值 getchar()会返回读取到的字符,若返回EOF则表示有错误发生。 附加说明 getchar()非真正函数,而是getc(stdin)宏定义。 */
21. mktemp /mkstemp
/* 功能:产生唯一的临时文件名 相关函数 tmpfile 表头文件 #include <stdlib.h> 定义函数 char * mktemp(char * template); 函数说明 mktemp()用来产生唯一的临时文件名。 参数说明 template所指的文件名称字符串中最后六个字符必须是XXXXXX。产生后的文件名会借字符串指针返回。 返回值 文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL, 并把错误代码存在errno中。 附加说明 参数template所指的文件名称字符串必须声明为数组,如: char template[ ]="template-XXXXXX"; 不可用char * template="template-XXXXXX"; */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> int main() { char template[ ]="template-XXXXXX"; mkstemp(template); //使用mktemp时编译器会提示这个是危险的,用mkstemp printf("template=%s\n",template); return 0; }
运行结果
22. putc
/* putc(将一指定字符写入文件中) 相关函数 fopen,fwrite,fscanf,fputc 表头文件 #include <stdio.h> 定义函数 int putc(int c,FILE * stream); 函数说明 putc()会将参数c转为unsigned char后写入参数stream指定的文件中。虽然putc()与fputc()作用相同, 但putc()为宏定义,非真正的函数调用。 返回值 putc()会返回写入成功的字符,即参数c。若返回EOF则代表写入失败。 范例 参考fputc()。 */
23. putchar
/* putchar(将指定的字符写到标准输出设备) 相关函数 fopen,fwrite,fscanf,fputc 表头文件 #include <stdio.h> 定义函数 int putchar (int c); 函数说明 putchar()用来将参数c字符写到标准输出设备。 返回值 putchar()会返回输出成功的字符,即参数c。若返回EOF则代表输出失败。 附加说明 putchar()非真正函数,而是putc(c,stdout)宏定义。 范例 参考getchar()。 */
24. rewind
/* 24.rewind(重设文件流的读写位置为文件开头) 相关函数 fseek,ftell,fgetpos,fsetpos 表头文件 #include <stdio.h> 定义函数 void rewind(FILE * stream); 函数说明 rewind()用来把文件流的读写位置移至文件开头。参数stream为已打开的文件指针。此函数 相当于调用fseek(stream,0,SEEK_SET)。 范例 参考fseek() */
25. setbuf
/* 25.setbuf(设置文件流的缓冲区) 相关函数 setbuffer,setlinebuf,setvbuf 表头文件 #include <stdio.h> 定义函数 void setbuf(FILE * stream,char * buf); 函数说明 在打开文件流后,读取内容之前,调用setbuf()可以用来设置文件流的缓冲区。 参数说明 stream 为指定的文件流, buf 指向自定的缓冲区起始地址。 如果参数buf为NULL指针,则为无缓冲IO。Setbuf()相当于调用:setvbuf(stream,buf,buf?_IOFBF:_IONBF,BUFSIZ) */
26. setbuffer
/* 26.setbuffer(设置文件流的缓冲区) 相关函数 setlinebuf,setbuf,setvbuf 表头文件 #include <stdio.h> 定义函数 void setbuffer(FILE * stream, char * buf,size_t size); 函数说明 在打开文件流后,读取内容之前,调用setbuffer()可用来设置文件流的缓冲区。 参数说明 tream 为指定的文件流, buf 指向自定的缓冲区起始地址, size 为缓冲区大小。 stream为指定的文件流,参数buf指向自定的缓冲区起始地址,参数size为缓冲区大小。 */
27. setlinebuf
/* 27.setlinebuf(设置文件流为线性缓冲区) 相关函数 setbuffer,setbuf,setvbuf 表头文件 #include <stdio.h> 定义函数 void setlinebuf(FILE * stream); 函数说明 setlinebuf()用来设置文件流以换行为依据的无缓冲IO。 相当于调用:setvbuf(stream,(char * )NULL,_IOLBF,0);请参考setvbuf()。 */
28. setvbuf
/* 28.setvbuf(设置文件流的缓冲区) 相关函数 setbuffer,setlinebuf,setbuf 表头文件 #include <stdio.h> 定义函数 int setvbuf(FILE * stream,char * buf,int mode,size_t size); 函数说明 在打开文件流后,读取内容之前,调用setvbuf()可以用来设置文件流的缓冲区。 参数说明 stream 为指定的文件流, buf 指向自定的缓冲区起始地址, size 为缓冲区大小, mode 有下列几种stream为指定的文件流, buf 指向自定的缓冲区起始地址, mode有下列几种 _IONBF 无缓冲IO _IOLBF 以换行为依据的无缓冲IO _IOFBF 完全无缓冲IO。如果参数buf为NULL指针,则为无缓冲IO。 */
29. ungetc
/* ungetc(将指定字符写回文件流中) 相关函数 fputc,getchar,getc 表头文件 #include <stdio.h> 定义函数 int ungetc(int c,FILE * stream); 函数说明 ungetc()将参数c字符写回参数stream所指定的文件流。 这个写回的字符会由下一个读取文件流的函数取得。 返回值 成功则返回c 字符,若有错误则返回EOF。 */
30. getline
/* getline 函数原型:man 手册 ,Linux C 中使用条件 #define _GNU_SOURCE #include <stdio.h> ssize_t getline(char **lineptr, size_t *n, FILE *stream); 函数说明: getline 不是C库函数,而是C++库函数,它会生成一个包含一串从输入 流读入的字符的字符串,直到一下情况发生会导致生成的字符串结束。 1) 到文件结束 2) 遇到函数的定界符 3) 输入达到最大限度 参数: lineptr 指向存放该行字符串的指针,如果是NULL,则有系统帮助malloc 请在使用完后free释放。 n 如果是由系统malloc的指针,请填0 stream 文件指针 返回值: 成功:返回读取的字符数 失败:返回 -1 */ /* size_t 与 ssize_t * * size_t * 感谢: * https://blog.csdn.net/lplp90908/article/details/50405899 * https://blog.csdn.net/21aspnet/article/details/1540025 * * 为了增强程序的可移植性,便有了size_t,他是为了方便系统之间的移植而定义的 * 不同系统上定义的 size_t 可能不一样。 * * 32 位系统上,size_t 为 unsigned int ,32位无符号整型 * typedef unsigned int size_t; * * 64 位系统上,size_t 为 unsigned long , 64位无符号整型 * typedef unsigned long size_t; * * ssize_t * * 而ssize_t 这个数据类型用来表示可以执行读写操作的数据块的大小,它和 * size_t 类似,但必须是signed.它表示的是 signed size_t类型的。 * * */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> int main() { FILE *fp = NULL; char *line = NULL; size_t len = 0; ssize_t read; // getline 返回类型 fp = fopen("tmp.txt", "r"); if(NULL == fp){ perror("fopen error!"); exit(-1); } while(-1 != (read = getline(&line, &len, fp))) {//读取行信息,'\n'为换行标志 // %zu 输出ssize_t 类型变量 printf("Read line of length %zu :\n", read); printf("%s", line); } //空间的释放 if(line){ free(line); } fclose(fp); return 0; }
后记:青春&热血,Thank you Ronaldo.
我不是个地道的足球迷,相反我是一个篮球fans,但是我也喜欢C罗,
一起感受一下C罗温情致敬马德里的告白~
'Real Madrid have conquered my heart' - Ronaldo's letter to fans
These years in Real Madrid, and in this city of Madrid, have been possibly
the happiest of my life.
I only have feelings of enormous gratitude for this club, for its fans and
for this city. I can only thank all of them for the love and affection I have received.
However, I believe that the time has come to open a new stage in my life and that
is why I have asked the club to accept transferring me. I feel that way and I ask
everyone, and especially our fans, to please understand me.
They have been absolutely wonderful for nine years. They have been nine unique years.
It has been an emotional time for me, full of consideration but also hard because
Real Madrid is of the highest demands, but I know very well that I will never forget
that I have enjoyed football here in a unique way.
I have had fabulous team-mates on the field and in the dressing room, I have felt
the warmth of an incredible crowd and together we have won three Championships in
a row and four Championships in five years. And with them also, on an individual
level, I have the satisfaction of having won four Gold Balls and three Gold Boots.
All during my time in this immense and extraordinary club.
Real Madrid has conquered my heart, and that of my family, and that is why more than
ever I want to say thank you: thanks to the club, the President, the directors,
my colleagues, all the technical staff, doctors, physios and incredible workers
that make everything work, that tirelessly pursue every minute detail.
Thank you infinitely once more to our fans and thanks also to Spanish Football.
During these nine exciting years I have played against great players.
My respect and my recognition for all of them.
I have reflected a lot and I know that the time has come for a new cycle. I'm leaving
but this shirt, this badge and the Santiago Bernabeu but they will continue to always
feel part of me wherever I am.
Thanks to all and, of course, as I said that first time in our stadium nine years ago: Go Madrid!