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

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

文章目录

输入输出函数

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

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

c 复制代码
#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"输出字符为例。

c 复制代码
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*的指针,已经打开的待输出的输出流,

c 复制代码
	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。这是一个格式串

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

c 复制代码
printf("hello,world");

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

我们对比下面两行代码

c 复制代码
	fprintf(stdout,"hello,world");
c 复制代码
	printf("hello,world");

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

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

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

c 复制代码
	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"

以下面的代码为例

c 复制代码
	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,因此可以用此来判断程序是否读取完了整个文本文件

c 复制代码
	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将文本中的数据传递进字符数组中。

c 复制代码
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

c 复制代码
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语言入门指南中已经提过了,这里不再说明

对比下面两个代码

c 复制代码
	char str[24] = { 0 };
	scanf("%s", str);
	printf("%s", str);
c 复制代码
	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中

c 复制代码
=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中的数据。

相关推荐
飞飞-躺着更舒服31 分钟前
【QT】实现电子飞行显示器(改进版)
开发语言·qt
武昌库里写JAVA1 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
ZSYP-S1 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos1 小时前
c++------------------函数
开发语言·c++
程序员_三木2 小时前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
是小崔啊2 小时前
开源轮子 - EasyExcel01(核心api)
java·开发语言·开源·excel·阿里巴巴
tianmu_sama2 小时前
[Effective C++]条款38-39 复合和private继承
开发语言·c++
黄公子学安全2 小时前
Java的基础概念(一)
java·开发语言·python
liwulin05062 小时前
【JAVA】Tesseract-OCR截图屏幕指定区域识别0.4.2
java·开发语言·ocr
jackiendsc2 小时前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法