printfscanf)、putsgets)和putchargetchar)是分别向标准流输出(由标准流读入)字符串、一行字符和单个字符的函数。除了这些函数,C语言也提供了面向任何流的输入和输出函数。

fprintf函数

fprintf函数的原型为:

int fprintf(FILE *stream, const char *format, ...);

该函数向stream流输出字符串。与printf函数唯一的不同只是增加了一个参数:访问输出流的文件指针,支持向任何流输出字符串。

可变长度实参

<stdarg.h>中提供了三个宏va_start, va_argva_end以及一个类型va_list。利用这些元素可以编写具有变长参数列表的函数。

具有变长参数列表的函数必须至少具有一个正常的形式参数,在最后一个正常形式参数的后边添加,...。变长参数列表的声明形式为:

返回值类型 函数名(正常形式参数1,正常形式参数2,...);

在函数的定义中,首先使用va_list声明变量,以支持访问在最后一个正常实际参数后面的实际参数:

va_list ap;

然后调用va_start声明可变长度部分开始的位置:

va_start(ap, 最后一个正常形式参数名);

之后依次通过va_arg获取可变参数:

可变参数的值 = va_arg(ap, 可变参数的类型);

在访问完成后,使用va_end结束:

va_end(ap);


在调用时,会进行默认的参数类型提升,例如由字符型自动提升到整型,由float型到double型等。

vfprintf函数

vfprintf原型为:

int vfprintf(FILE *stream, const char *format, va_list arg);

可以在带有变长参数列表的函数内调用,支持对输出信息的包装。

/***************************************** stream_fprintf.c                     **                                      ** C语言中文件流的输出和变长参数列表函数*****************************************/#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>void Print(FILE* fp, char *msgtype, char* format, ...)
{va_list vp;va_start(vp, format);fprintf(fp, "%s: ", msgtype);vfprintf(fp, format, vp);va_end(vp);fprintf(fp,"\n");
}int Sum(size_t n, ...)
{va_list vp;va_start(vp, n);size_t i = 0;int sum = 0;while (i < n){int num = va_arg(vp, int);sum += num;i++;}va_end(vp);return sum;
}int main()
{FILE *fp = NULL;fp = fopen("test.txt", "w");int n;Print(fp, "询问","输入整数的个数: ");scanf("%d", &n);Print(fp, "询问", "输入%d个整数: ", n);int *nums = malloc(n * sizeof(int));int i = 0;for (; i < n; i++){scanf("%d", nums + i);}Print(fp, "结果", "输入的整数为:");for (i = 0; i < n; i++){fprintf(fp, "%d ", nums[i]);}fprintf(fp, "\n");int sum1 = Sum(3, 4, 5, 6);Print(fp, "结果","4,5,6的和为%d", sum1);int sum2 = Sum(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Print(fp, "结果","1到10的和为%d", sum2);fclose(fp);return 0;
}

fscanf函数

fscanf函数的原型为:

int fscanf(FILE *stream, const char *format, ...);

该函数从stream流读入数据。与scanf函数唯一的不同只是增加了一个参数:访问输入流的文件指针,支持由任何流读入数据。

文件结尾或错误指示函数

每个流都有两个指示器:错误指示器和文件末尾指示器。当遇到文件结尾时设置文件末尾指示器,若遇到错误(不是匹配错误引起的)则设置错误指示器。重新打开同一个流时会清除原来的指示器。也可以使用clearerr函数主动清除文件末尾指示器和错误指示器,其使用原型为:

void clearerr(FILE *fp);

可以利用feof函数检查指定的流是否设置了文件末尾指示器,如果设置了则返回非零值,否则返回0。feof函数的原型为:

int feof(FILE *fp);

可以利用ferror函数检查指定的流是否设置了错误指示器,设置了则返回非零值,否则返回0。

/*************************************** string_scanf.c                     **                                    ** C语言中文件流的输入和错误检测      ***************************************/#include <stdio.h>int main()
{FILE *fp = NULL;fp = fopen("test.txt", "r");int x ,y;int num = fscanf(fp, "%d%d", &x, &y);if (num < 2){printf("是否已达到文件末尾:%d\n", feof(fp));printf("是否出现错误: %d\n", ferror(fp));}clearerr(fp);fclose(fp);return 0;
}

字符输出函数fputcputc

putchar函数向标准输出流输出一个字符。fputcputcputchar的更通用版本,向任何流输出字符,两个函数的原型为:

int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);

其中putcfputc的功能相同,只是putc是利用宏实现的。

正常的情况下三个函数都会返回输出的字符,而在出现错误时都会设置错误指示器,并返回EOF

字符输入函数fgetcgetcungetc

getchar从标准流中读入一个字符,fgetcgetcgetchar的更通用版本,从任何流读入一个字符,两个函数原型为:

int fgetc(FILE *stream);
int getc(FILE *stream);

其中getcfgetc的功能相同,但getc是利用宏实现的。

fgetcgetcgetchar三个函数在与遇到文件结尾的问题,都会设置文件末尾指示器,并返回EOF。如果产生了错误,就会设置错误指示器。

ungetc函数将从流中读入的字符回退,并清除掉流的文件末尾指示器,原型为:

int ungetc(int c, FILE *stream);

通过多次调用ungetc函数可以回退多个的字符,可以回退的数量依赖于实现和流的类型。调用文件定位函数会丢失回退的字符。ungetc正常情况下会返回字符,若试图返回过多的字符则返回EOF

/*************************************** stream_char.c                      **                                    ** C语言文件流输入和输出字符          ***************************************/#include <stdio.h>int main()
{FILE *fp = NULL;fp = fopen("test.txt", "w+");int c = 'A';fputc(c, fp);c = 'B';fputc(c, fp);c = 'C';fputc(c, fp);/*将文件位置返回到开头*/rewind(fp);c = fgetc(fp);printf("读出字符:%c\n", c);c = fgetc(fp);printf("读出字符:%c\n", c);ungetc(c,fp);printf("放回字符:%c\n", c);c = fgetc(fp);printf("再次读出字符:%c\n", c);fclose(fp);return 0;
}

行输出函数fputs

puts函数向标准输出流stdout输出一串字符,并且在输出字符后自动添加一个换行符。fputsputs的更通用版本,可以向任意的输出流写入字符串,不同的是它不会自动添加换行符。fputs的函数原型为:

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

当出现错误时,两个函数都返回EOF。否则,返回一个非负数。

行输入函数fgets

gets函数向标准输出流stdin读入一串字符,逐个读入字符,在遇到换行符时停止,并自动丢弃换行符。fgetsgets的更通用版本,可以从任意的输出流读入字符串,也更安全,限制了读入的字符的数量。fgets的函数原型为:

char *fgets(char *s, int n, FILE *stream);

fgets函数逐个读入字符,并在遇到首个换行符时停止操作,或者已读到n-1个字符时停止操作,且fgets会将换行符和其他字符一起存储。

如果在读入过程中发生错误或者在读入任何字符前达到了输入流的末尾,则返回空指针,否则都返回读入字符串的指针。

/*************************************** stream_put_get.c                   **                                    ** C语言文件流的行输入和输出函数      ***************************************/#include <stdio.h>#define STR_LEN 32int main()
{FILE *fp = NULL;fp = fopen("test.txt", "w+");fputs("1: Hello World\n", fp);fputs("2: Hello World\n", fp);rewind(fp);char tmp[STR_LEN];fgets(tmp, STR_LEN, fp);printf("%s", tmp);fgets(tmp, STR_LEN, fp);printf("%s", tmp);fclose(fp);return 0;
}

块输入输出函数freadfwrite

freadfwrite函数运行程序一次读入大数据块,常用于二进制流。

fwrite将内存中的数组复制给流,其原型为:

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

fwrite函数的第一个参数是数组的地址,第二个参数是每个数组元素的大小,第三个参数为需要写的数组元素的数量,最后一个是指示写入位置的文件指针。函数返回值为实际写入元素的数量,若小于第三个参数则表示出现写入错误。

fread从流中读入数组的元素,其原型为:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

fread每个参数的意义和fwrite是对应的,返回值是读入的元素数目,可以通过与第三个参数比较来判断是否出现读入错误。

尽管freadfwrite是为写入数组设计的,但它可以用以全部类型的变量。

/*************************************** stream_block.c                     **                                    ** C语言中文件流的块输入输出          **************************************/#include <stdio.h>
#include <stdlib.h>int main()
{printf("输入整数个数:");int n;scanf("%d", &n);int *nums = malloc(n * sizeof(int));printf("输入每个整数:");int i = 0;for (; i < n; i++){scanf("%d", nums + i);}printf("nums: ");for (i = 0; i < n; i++){printf("%d ", nums[i]);}printf("\n");FILE *fp = NULL;fp = fopen("test.txt", "w+");fwrite(nums, sizeof(int), n, fp);fclose(fp);free(nums);//  system("cat test.txt");fp = fopen("test.txt", "r");int *nums2 = calloc(n, sizeof(int));fread(nums2, sizeof(int), n, fp);printf("nums2: ");for (i = 0; i < n; i++ ){printf("%d ", nums[i]);}printf("\n");fclose(fp);free(nums2);return 0;
}

文件的定位函数

在打开文件进行写操作时,可以通过模式设置从文件头开始,或以追加的方式在文件尾写入。C语言提供了fseek等5个函数支持更加灵活的定位方式。

fseek函数的原型为:

int fseek(FILE *stream, long int offset, int whence);

fseek函数改变stream指向的文件的文件位置,第三个参数whence说明第二个参数偏移量是想对于文件的起始处、当前位置还是末尾处,由3个宏表示:

-SEEK_SET: 文件的起始处
- SEEK_CUR:文件的当前位置
- SEEK_END:文件的末尾处。

在正常的情况下,fseek返回0,如果出现错误,则返回非零值。fseek最适合用于二进制流,对于文本流offset必须为0或者whence必须为SEEK_SET,且offset的值必须由ftell函数获得。对于二进制流来说,fseek函数不一定支持whenceSEEK_END的调用。

ftell函数以长整形方式返回当前文件位置,如果发生错误,返回-1L,并且将错误码放入errno中。ftell的原型为:

long int ftell(FILE *stream);

rewind函数将文件位置设置在开始处,并清除错误标记。

void rewind(FILE *stream);

fgetposfsettpos函数用于大型文件,利用fpos_t型值表示文件位置,它可以是一个结构体类型。调用成功则返回0,否则返回非零值,并将错误代码记录在errno中,这两个函数的原型为:

int fgetpos(FILE *stream, fpos_t *pos);
int fgetpos(FILE *stream, const fpos_t *pos);

字符串输入和输出函数sprintfsscanf

sprintf函数和sscanf函数用以将字符串作为流的输入源或输入目的读写数据,sprintfsscanf)与prinffprintf)唯一的不同就是读出和写入的流关联于字符串。sscanf的好处之一是可以多次进行测试输入行。它也返回成功读入并存储的数据项的数量。但如果在找到第一个数据之前就到达文件末尾,就返回EOF。类似的也有支持变长参数列表的svprintf函数。

/*************************************** stream_string.c                    **                                    ** C语言中的字符串输入输出函数        ***************************************/#include <stdio.h>#define STR_LEN 32
int main()
{char msg[STR_LEN];int x = 10;int y = 32;sprintf(msg, "%d,%d", x, y);int m = 0;int n = 0;sscanf(msg,"%d,%d", &m, &n);printf("m = %d, n = %d\n", m, n);return 0;
}

参考文献

  1. K.N. King 著,吕秀峰 译. C语言程序设计-现代方法. 人民邮电出版社

C语言流输入和输出函数相关推荐

  1. C语言-数据输入与输出函数

    1.字符数据输入/输出 1.1字符数据输出 字符数据输出可以使用 putchar() 函数,向控制台输出一个字符.函数定义: int putchar(int ch); 使用putchar() 函数需要 ...

  2. c语言程序输入与输出函数,C语言printf()和scanf()函数?其实就是输入输出

    在解释这两个函数之前,为了方便大家更容易理解,我们先来讲讲下面的这幅图. 这个图中的例子其实很简单,我们就是把题目通过输入设备(例如键盘鼠标)传输到计算机中,然后让计算机进行运算得出结果,再然后把结果 ...

  3. C语言字符串输入与输出函数

    字符串输入 如果想把一个字符串读取到程序中,必须首先预留存储字符串的空间,然后使用输入函数来获取这个字符串,C库提供了三个读取字符串的函数:scanf().gets()和fgets(). 创建存储空间 ...

  4. c语言字符串输出函数是,C语言字符串输入与输出函数

    字符串输入 如果想把一个字符串读取到程序中,必须首先预留存储字符串的空间,然后使用输入函数来获取这个字符串,C库提供了三个读取字符串的函数:scanf().gets()和fgets(). 创建存储空间 ...

  5. c语言printf函数中的格式控制字符串,C++_C语言格式化输入输出函数详解,一:格式输出函数printf() 1 - phpStudy...

    C语言格式化输入输出函数详解 一:格式输出函数printf() 1.调用形式一般为:printf("格式化控制字符串",输出表列): 2.格式化控制字符串用于指定输出格式,它有三种 ...

  6. c语言中常用的输入输出函数有哪些,C语言中常用的输入和输出函数

    C语言中常用的输入和输出函数 2020年03月11日 | 萬仟网IT编程 | 我要评论 1. scanf()函数 (Scan Format) + 函数原型: + 函数作用:从标准输入流 stdin ( ...

  7. c语言控制台输入输出函数库:conio.h

    c语言控制台输入输出函数库:conio:供自己以后使用. 1.cgets()函数--从控制台读字符串函数 cgets()函数用于从控制台输入一行字符串 语法: char* cgets(char*str ...

  8. C语言的输入输出函数

    C语言的输入输出函数 C语言所有的输入输出相关的内容包含在头文件stdio.h中,所以当我们需要用到输入输出功能时,需要将这个头文件包含到源文件中. 输入函数: ①int getchar(void) ...

  9. C语言字符串输入输出函数

    C语言字符串输入输出函数 putchar()函数 getchar()函数 puts()函数 gets()函数 getche()函数 getch()函数 putchar()函数 格式: putchar( ...

最新文章

  1. Android Studio 单刷《第一行代码》系列 02 —— 日志工具 LogCat
  2. Tensorflow入门——训练结果的保存与加载
  3. WCF4.0 –- RESTful WCF Services (1) (入门)
  4. 如何编写一个Systemd Service(转)
  5. MySQL数据库编译过程
  6. php 加tab键,php 生成Tab键或逗号分隔的CSV
  7. 《学习》13权限管理
  8. java递推_【Java】递归递推的应用
  9. 物料移动类型和后勤自动科目设置-SAP屠夫
  10. dvbbs 7.1版块图标感应渐变效果 From www.jfeng.cn
  11. USB 公,母头接口
  12. hashcat+john破解rar密码
  13. 淘宝app搜索排名优化技巧
  14. 软件工程师考试报名须知
  15. 通过脚手架安装Ant+react+umi+dva项目(一)
  16. 在新的固态硬盘中安装windows系统(旧固态硬盘已安装ubuntu系统)
  17. RecyclerView添加表格分割线
  18. Apollo + Springboot 整合(多环境版)
  19. 自己打包部署iOS app分发
  20. C# winform 打印预览

热门文章

  1. 纯css实现正方体图片旋转效果
  2. 毕业论文图片、公式自动编号和交叉索引教程——真的超好用
  3. java feature task同步_FetrueTask做java方法超时处理
  4. python——利用正则表达式爬取豆瓣读书中的图书信息
  5. Win11电脑一边耳机没声音怎么办
  6. online-DDL详细原理介绍及gh-ost讲解
  7. 华为eNSP 配置DHCP自动分配IP地址
  8. mysql 某个日期加七天_Mysql时间操作(当天,昨天,7天,30天,半年,全年,季度)...
  9. 计算机硬件的组成、python的开发层面及语法介绍
  10. angularjs2学习教程