c语言进阶指南(21)——其他的输入\输出函数

欢迎来到博主的专栏——C语言进阶指南

输入输出函数

输入输出函数其实在C语言的初学阶段就一直在使用,比如printf函数,scanf函数;getc函数,gets函数。

C语言的输入\输出函数包含在<stdio.h>头文件中(没错,就是那个所有初学者都会引用的那个头文件)

#include<stdio.h>

输入\输出函数的对象都是输入“流”或输出“流”

标准流

有些人觉得有点疑惑了,因为前文提到了“流”在进行输入或者输出的操作时,都需要将这个“流”进行打开。但是初学者在使用printf函数,scanf函数时,并没有打开过任何的“流”。

这是因为<stdio.h>中,包含了一些标准“流”,这些流在引用头文件<stdio.h>时,就默认打开了这些流,这些“流”被称为标准流

标准流有以下三个

标准输出流——stdout。大多数标准输出流都是输出到显示器上,比如printf函数就是将字符串显示在屏幕上。
标准输入流——stdin。大多数标准输入流都是从键盘上输入,比如scanf函数就是在键盘上获取输入的数据。
标准误差流——stderr,这个标准流的作用是将错误信息输出到显示器上,后续会讲到这个流的使用方法

“流”的输入输出函数

在这里插入图片描述
有些输入\输出函数并非能作用于所有类型的“流”,这里先来介绍一些适用性高一些的输入\输出函数

输出函数

fputc

在这里插入图片描述
fputc的函数原型有两个参数

c是一个int类型的数据,是一个字符的ascii码形式。也可以直接使用字符作为参数。
stream是一个FILE*类型的指针,是一个已经打开的任意输出流

fputc是字符输入函数。其作用是向“流”输出字符类型的数据。

这个函数可以向任意的输出“流”输出。所以可以用于标准输出流(stdout)或者是一个文件流。以向文件“data.txt”输出字符为例。

FILE*pf=fopen("data.txt", "w");//打开一个文件输出流
//"w"是说明流的模式是写入数据,即创建一个输出流。
if (pf == NULL)
{
   
	exit(EXIT_FAILURE);
}
fputc('h',pf);//向文件输出流输出'h'.
fputc('e', pf);//输出'e'
fputc('l', pf);
fputc('l', pf);
fputc('o', pf);
fclose(pf);//关闭文件输出流

运行程序,打开文件“data.txt”。
在这里插入图片描述
(这可不是手打的哈- -!)
其原理如下(后续的输出函数原理类似,不再画图说明)
在这里插入图片描述

fputs

fputs的作用是向文件输出流输出一串字符串。
在这里插入图片描述
fputs的函数原型有两个参数

string是一个const char *类型的指针,可以是一个常量字符串,也可以是字符数组里的一串字符串。
stream是一个FILE*的指针,已经打开的待输出的输出流,

	FILE* pf = fopen("data.txt", "w");//打开data.txt文件的文件输出流
	char buf[10] = "world";//包含在字符数组中的字符串"world"
	if (pf == NULL)
	{
   
		exit(EXIT_FAILURE);
	}
	fputs("hello,", pf);//向文件输出流输出"hello,"
	fputs(buf, pf);//向文件输出流输出"world"
	fclose(pf);

运行程序,打开data.txt文件。
在这里插入图片描述

fprintf

在这里插入图片描述
fprintf函数时格式化输出函数。

fprintf函数的第一个参数,stram是一个已打开的待输出的输出流。
重点在于第二个参数format。这是一个格式串

格式串大家已经见识过很多了。比如

printf("hello,world");

中的字符串就是一个格式串。格式串的讲解在C语言入门指南中已经谈过了,这里不在过多介绍。

我们对比下面两行代码

	fprintf(stdout,"hello,world");
	printf("hello,world");

运行发现,这两段代码的结果都是在屏幕上打印“hello,world”

这是因为,printf函数的作用,是默认向标准输出流输出数据的,也就是说使用fprintf函数向标准输出流(stdout)输出数据,和使用printf函数直接输出数据是一样作用的。

fprintf可以向任意输出流输出数据,那么fprintf也可以向文件流输出数据。

	FILE*pf=fopen("data.txt", "w");
	fprintf(pf, "%s\n,%d\n","hello",2024);
	fclose(pf);

这段代码是将格式串

“%s\n,%d\n”

输出到文件输出流中。

运行程序,打开“data.txt”文件。可以发现数据已经输出到“data.txt”文件中了。
在这里插入图片描述

输入函数

fgetc

在这里插入图片描述
fgetc函数的函数原型中只有一个参数

stram是一个FILE*类型的指针,是一个已经打开的文件输入流

fgetc从文件输入流读取一个字符,并且将该字符的ASCII码值作为函数的返回值

还是以“data.txt”为例,我们在与程序文件的同一目录下创建一个文本文件“data.txt”。并在该文本文件中输入“hello,world”
在这里插入图片描述
在这里插入图片描述
以下面的代码为例

	char a, b, c, d;
	FILE*pf=fopen("data.txt", "r");//打开"data.txt"的文件流
	//"r"是限定这个文件流为只读,即文件输入流
	a=fgetc(pf);//读取'h'
	b = fgetc(pf);//读取'e'
	c = fgetc(pf);//读取'l'
	d = fgetc(pf);//读取'l'
	fclose(pf);//关闭文件流

运行可以发现,a,b,c,d四个变量都读取了“data.txt”的文本信息

读取的原理如下图(其他的输入函数也是如此,后续不在说明)
在这里插入图片描述
文件被读取时,会将文件内的数据读入至文件流当中,并且在文件的末尾处加上一个EOF(end of file——文件结束标志)。

当我们使用fgetc时,计算机会向文件输入流中读取一个字符,并且将光标移动至下一个字符,直至读取到了EOF。

如果fgetc函数读取到了EOF(EOF的值为-1),函数的返回值为-1,因此可以用此来判断程序是否读取完了整个文本文件

	FILE* pf = fopen("data.txt", "r");
	char a;
	a = fgetc(pf);
	if (a == EOF)
	{
   
		//文件到了末尾应执行语句
	}
fgets

在这里插入图片描述
fgets是字符串输入函数,其作用是在打开的输入流中读取一串字符串。

fgets的函数原型有三个参数

string是一个char*类型的指针,是用来存放从流中读取的数据的字符串,通常是一个字符数组。
n是一个整型变量,限定了一次读取的字符串中最大字符数。
stream是一个输入流

以文件输入流为例。
fgets会依次读取字符,直到读取了换行符(\n)或者文件结束标志(EOF)时停止。

当fgets发生了读取错误,或者读取了EOF时,函数的返回值为NULL,因此通过判断函数的返回值,可以判断文件是否读取完成。

以文件“data.txt”为例,我们在其输入一段文本。
在这里插入图片描述
使用fgets将文本中的数据传递进字符数组中。

int main()
{
   
	FILE* pf = fopen("data.txt", "r");//打开"data.txt"的文本输入流
	if (pf==NULL)
	{
   
		exit(EXIT_FAILURE);//说明程序运行发生错误
	}
	char buf[256] = {
    0 };//buf是用来接收数据的数组
	if (fgets(buf, 20, pf) == NULL)//检测读取信息
	//并将文件输入流中的数据读取至buf中
	{
   
		exit(EXIT_FAILURE);
	}
	printf("%s", buf);
	return 0;
}

运行可以发现,buf成功读入了“data.txt”中的第一行的文本。
在这里插入图片描述
在这里插入图片描述

将限定的最大字符数改成10

fgets(buf, 10, pf)

运行这段程序,可以发现buf并没有读取到\n为止。
在这里插入图片描述
buf只读取了9个字符,这是由于fgets如果读取到了限定的最大字符数时,只读取最大字符数-1个字符,并在最后一个字符的后面加上‘\0’。
在这里插入图片描述

使用fgets函数读取文本行时,一次只能读取到“\n”,或者读取到了限定的最大字符数(n-1)处停止。

fscanf

fscanf是格式化输入函数,既然提到了格式化,那么参数中就应该存在格式串。

对比两个使用格式串的函数——fscanf和scanf的函数原型
在这里插入图片描述
在这里插入图片描述
可以发现,fscanf的参数只比scanf多了一个输入流

fscanf的第二个参数是可变参数列表,可变参数列表则说明参数的数量不具体。

虽然可变参数列表大家不太了解,但是可以将fscanf函数的参数分为两个部分 函数的第一个参数是一个流,这个流是已经打开的输入流
函数的第二个参数是一个格式串,这个格式串在scanf函数中已经使用过很多次了。
比如scanf(“%d”,&i);这个“%d”就是一个格式串。

关于格式串在C语言入门指南中已经提过了,这里不再说明

对比下面两个代码

	char str[24] = {
    0 };
	scanf("%s", str);
	printf("%s", str);
	char str[24] = {
    0 };
	fscanf(stdin,"%s", str);//stdin是标准输入流
	printf("%s", str);

运行可以发现,这两段代码的效果没有区别。

这是因为scanf函数默认从标准输入流(stdin)中读取信息,而将fscanf函数读取的流设定为stdin,那么fscanf的作用就和scanf函数的作用一致了

那么fscanf函数是如何读取文件流的呢?

以文件“data.txt”为例。我们在该文件中输入“hello,world”
在这里插入图片描述
运行下列代码,将“data.txt”中的信息输入至字符数组buf中

=int main()
{
   
	char buf[256] = {
    0 };
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
   
		exit(EXIT_FAILURE);
	}
	fscanf(pf, "%s", buf);
	printf("%s", buf);
	return 0;
}

运行程序,buf成功读取了pf中的数据。
在这里插入图片描述

相关推荐

  1. C语言输入输出详解

    2024-01-13 10:32:02       36 阅读
  2. C语言标准输入输出

    2024-01-13 10:32:02       38 阅读
  3. C语言指针

    2024-01-13 10:32:02       45 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-13 10:32:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-13 10:32:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-13 10:32:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-13 10:32:02       18 阅读

热门阅读

  1. Ubuntu搭建OpenCV环境(C++)

    2024-01-13 10:32:02       37 阅读
  2. LocalDateTime与时间戳转换的全局配置

    2024-01-13 10:32:02       37 阅读
  3. golang学习-结构体

    2024-01-13 10:32:02       28 阅读
  4. No Feign Client for loadBalancing defined. 错误解决

    2024-01-13 10:32:02       37 阅读
  5. MYSQL学习——聚合函数

    2024-01-13 10:32:02       28 阅读
  6. 30天精通Nodejs--第十五天:Websocket

    2024-01-13 10:32:02       34 阅读
  7. 深度学习基础教程

    2024-01-13 10:32:02       28 阅读
  8. 「HDLBits题解」Module add

    2024-01-13 10:32:02       29 阅读
  9. 在Python中调用狄拉克gamma矩阵

    2024-01-13 10:32:02       29 阅读
  10. leaflet聚类——leaflet.markercluster

    2024-01-13 10:32:02       28 阅读