【八组输入输出你都了解多少】
目录:
- 前言
- 一、总览
- (一)只能从标准流(std)中输入和输出数据
- (二)可以从所以流中读取和写入数据
- (三)只能从字符串中读取和写入数据
- 二、详细描述
- (一)scanf、fscanf、sscanf
- 1.scanf
- 2.fscanf
- 3.sscanf
- (二)printf、fprintf、sprintf
- 1.printf
- 2.fprintf
- 3.sprintf
- (三)getchar、fgetc
- 1.getchar
- 2.fgetc
- (四)putchar、fputc
- 1.putchar
- 2.fputc
- (五)gets、fgets、fread
- 1.gets
- 2.fgets
- 3.fread
- (六)puts、fputs、fwrite
- 1.puts
- 2.fputs
- 3.fwrite
- 三、
- 总结
前言
大家好,我是熊猫,今天我们来了解了解C语言<stdio.h>头文件中的那些输入输出函数。
在开始之前,大家可以先回想回想自己了解到的输入输出函数都有哪些,
我想很多朋友第一反应为scanf和printf,
再之后可能会有putchar,getchar,以及puts和gets。
不过我们今天要讲解的是包含上面这部分以及从文件读取和写入的各种常用函数,下面我们进入正题。
一、总览
我们如果按照使用范围分类的话可以分为两大类:
1.只能从标准输入流(stdin)输入数据,只能往标准输出流(stdout)输出数据;
2.可以从任何流中读取和写入数据。
补充:这里我们要先理解:输入就是从流中读取数据,输出就是往流中写入数据。(输出到屏幕 == 写到屏幕上)
(一)只能从标准流(std)中输入和输出数据
scanf、printf;
getchar、putchar;
gets、puts。
(二)可以从所以流中读取和写入数据
fscanf、fprintf;
fgetc、fputc;
fputs、fgets;
fread、fwrite;
(三)只能从字符串中读取和写入数据
sscanf、sprintf;
二、详细描述
下面我们并不会按照上面的分类进行讲解,而是,
将同一种形式的函数放在一起分析,
通过这样的对比更有利于我们理解和记忆。
(一)scanf、fscanf、sscanf
函数原型:
int scanf (const char* const _Formet, …);
int fscanf (const FILE* const _Stream, const char* const _Formet, …);
int sscanf ( const char * s, const char * format, …);
1.scanf
int scanf (const char* const _Formet, …);
看到了我们平时使用的scanf会不会有一种既熟悉又陌生的感觉,
返回值我们应该都知道,是输入数据的个数,不过,
上面的参数列表里的是一个格式字符串,以及省略号。
哎~!我平时就是写上需要输入的数据,然后在后面写上变量的地址,
他怎么只要一个格式字符串呢?
其实,这个格式字符串就是我们平时所写的需要输入的数据的格式,后面的省略号表示随便你输入多少数据,具体是根据格式字符串来定的。
示例:
#include<stdio,h>
int main()
{
int a = 0;
float fl = 0.0f;
char ch = 0;
printf("请输入一个整形,浮点型和字符型数据:\n");
int con = scanf("%d %f %c", &a, &fl, &ch);
//前面的字符串是我们我们需要输入的数据的类型,后面是数据需要存放的地址
//这里要注意scanf的返回值:输入数据的个数,
//是输入数据的个数而不是输入字符的个数
printf("scanf返回值:%d\n\n", con);
char str[20] = {0};
printf("请输入字符串:\n");
con = scanf("%s", str);
//这里只输入了一个数据:一个字符串
printf("scanf返回值:%d\n", con);
return 0;
}
运行实例:
补充:
1.scanf只能从标准输入流(stdin)–也就是键盘中读取数据。
2.这里如果输入格式出错,就会返回EOF(EOF是文件结束标志,在VS中的定义是 - 1),所以我们可以在输入的时候进行判断:
假设输入三个数据,如果返回值 == 3、或者返回值 != EOF,就说明我们输入正确了。
2.fscanf
int fscanf (const FILE* const _Stream, const char* const _Formet, …);
fscanf的返回值也是输入数据的个数,
与scanf的区别只是前面多了一个 流(stream),
我们平时描述数据的传输时会形象的描述说数据从发送方流向了接收方,就会说的流动就是数据流,
fscanf是从流里面读取数据,可以是标准输入流(stdin),亦可以是文件流(我们写入数据到文件流使用的是文件指针)
>示例:
int main()
{
FILE* pf = fopen("test.txt", "r");
//以只读的方式打开文件
int a = 0;
float fl = 0.0f;
char ch = 0;
printf("从文件test.txt中读取一个整形,浮点型和字符型数据:\n");
fscanf(pf, "%d %f %c", &a, &fl, &ch);
printf("输出:%d %f %c\n\n", a, fl, ch);
char str[20] = { 0 };
printf("从文件test.txt中读取一个字符串:\n");
fscanf(pf, "%s", str);
printf("输出:%s\n\n", str);
fclose(pf);
pf = NULL;
//关闭文件
printf("从stdin中读取一个字符串:\n");
fscanf(stdin, "%s", str);
printf("输出:%s\n", str);
return 0;
}
注意:读取文件时文件必须存在。
此时文件中的内容:
运行实例:
补充:
1.从文件中读取数据时:因为数据已经存在,所以不需要进行输入,但是从stdin(键盘)中读取时需要我们进行输入
因此我们在屏幕上看到了两个“哈哈”。
2.fscanf读取字符时遇到空格就认为该数据读取结束,之后知道找到下一个非空字符时才开始读取下一个数据。
3.sscanf
int sscanf ( const char * s, const char * format, …);
sscanf和fscanf就很相似了,
不同之处在于:fscanf第一个参数为 流,而 sscanf为常量字符指针–也就是指向一个字符串常量
示例:
int main()
{
char arrc[] = "10 3.14 a hello world";
char* ps = arrc;
int a = 0;
float fl = 0.0f;
char ch = 0;
printf("从ps指向的字符串中读取一个整形,浮点型和字符型数据:\n");
sscanf(ps, "%d %f %c", &a, &fl, &ch);
//ps也可以换成数组名arrc
printf("%d %f %c\n\n", a, fl, ch);
char str[20] = { 0 };
printf("从ps指向的字符串中读取一个字符串:\n");
sscanf(ps, "%s", str);
printf("%s\n", str);
return 0;
}
运行实例:
补充:
为什么这里字符串读取到的是"10",而不是"hello" 呢“?
答:
从文件中读取数据,在关闭文件之前我们读取到哪里都可以保存下来,之后继续往后读取,
但是从字符串中读取数据时没有“关闭字符串”这个操作,所以在每次读取字符串时都会从最开始进行读取。
(二)printf、fprintf、sprintf
函数原型:
int printf(const char* const _Formet, …);
int fprintf(FILE* const _Stream, const char* const _Formet, …);
int sprintf ( char * str, const char * format, … );
1.printf
int printf(const char* const _Formet, …);
printf函数的参数列表里也是一个格式字符串和一串省略号,和scanf一样,按照格式字符串的形式进行输出。
并且,printf只能将数据写入到stdout(屏幕)上;
和scanf不同的是:虽然他们的返回值都是int类型,但是,scanf返回值为输入变量的个数,而,printf返回值却是输出字符的个数。
示例:
int main()
{
int a = 1;
float fl = 3.14f;
char ch = 'a';
int ret = printf("%d\n", a);
printf("printf返回值:%d\n\n", ret);
char str[] = "hello world";
ret = printf("%s\n", str);
printf("printf返回值:%d\n\n", ret);
return 0;
}
运行实例:
补充:
第一个printf输出一个字符’1’,和’\n’,所以返回值为2;
第二个printf输出字符串"hello world"和’\n’,一共 11 + 1 = 12 个字符,所以返回值为12.
2.fprintf
int fprintf(FILE* const _Stream, const char* const _Formet, …);
fprintf和printf的区别是fprintf参数列表中多了一个参数:流,表示我们可以把数据写入任何数据流中,
这里可以类比fscanf和scanf的区别。
示例:
int main()
{
int a = 1;
float fl = 3.14f;
char ch = 'a';
printf("写入到stdout:\n");
fprintf(stdout, "%d %f %ch\n", a, fl, ch);
char str[] = "hello world";
fprintf(stdout, "%s\n", str);
FILE* pf = fopen("ppp.txt", "w");
printf("\n写入ppp.txt文件\n");
fprintf(pf, "%d %f %c\n", a, fl, ch);
fprintf(pf, "%s\n", str);
fclose(pf);
pf = NULL;
return 0;
}
运行实例:
3.sprintf
int sprintf ( char * str, const char * format, … );
sprintf和fprintf的区别就是第一个参数,sprintf是想字符串中写入数据。
示例:
int main()
{
char buf[100] = { 0 };
int a = 1;
float fl = 3.14f;
char ch = 'a';
printf("写入到buf字符串\n\n");
sprintf(buf, "%d %f %c\n", a, fl, ch);
printf("输出buf字符串:\n");
fprintf(stdout, "%s\n", buf);
return 0;
}
运行实例:
(三)getchar、fgetc
函数原型:
int getchar(void);
int fgetc(FILE* _Stream);
1.getchar
int getchar(void);
getchar只可以从stdin中读取字符,读取成功就返回该字符,失败则返回EOF
这里返回值为 int类型是对 char类型进行了整形提升
示例:
int main()
{
int ch = 0;
/*while(scanf("%c",&ch)!=EOF)*/
while ((ch = getchar()) != EOF)
{
getchar();//吸收后面的 空格字符(空格、换行、tab键)
printf("%c\n\n", ch);
}
return 0;
}
运行实例:
补充:结束输入操作:Ctrl + z
有的时候需要输入三次才能退出。
2.fgetc
int fgetc(FILE* _Stream);
fgetc与getchar的区别在于fgetc可以从任何数据流中读取数据,类比scanf和fscanf
示例:
int main()
{
int ch = 0;
/*while(scanf("%c",&ch)!=EOF)*/
while ((ch = fgetc(stdin)) != EOF)
{ // 从stdin流中读取数据
getchar();//吸收后面的 空格字符(空格、换行、tab键)
printf("%c\n\n", ch);
}
return 0;
}
运行实例:
(四)putchar、fputc
int putchar( int character);
int fputc(int character, FILE* _Stream);
1.putchar
int putchar( int character);
putchar的参数为需要输出的字符,如果输入正确就返回一个非负数(不一定就是该字符),错误就返回EOF
示例:
int main()
{
int ch = 0;
/*while(scanf("%c",&ch)!=EOF)*/
while ((ch = fgetc(stdin)) != EOF)
{
getchar();//吸收后面的 空格字符(空格、换行、tab键)
putchar(ch);
putchar('\n');
putchar('\n');
/*printf("%c\n\n", ch);*/
}
return 0;
}
运行实例:
2.fputc
int fputc(int character, FILE* _Stream);
示例:
int main()
{
int a= 'b';
fputc(a,stdout);
putchar(a);
//两者等同,都是向stdout中输出数据
return 0;
}
运行实例:
之后的介绍将不会和之前那么详细(啰嗦),这里我们需要注意的就是流的位置和fscanf不同,是位于最后的
(五)gets、fgets、fread
char* gets(char* str);
char* fgets(char* str, int num, FILE* _Stream);
size_t fread(void* _Buffer, size_t size, int count, FILE* _Stream);
1.gets
char* gets(char* str);
从stdin中获取字符串,直到\n或者EOF时结束,读取成功后返回该字符串
注意:该函数在c和c++中已经不可使用(从c11开始)
2.fgets
char* fgets(char* str, int num, FILE* _Stream);
从文件流中读取数据放到字符串中,
遇到空格字符、文件结尾、或者读取了 num - 1 个字符就结束读取,
读取成功就返回字符串首地址,
如果是读取到文件末尾失败则返回NULL,并且设置eof指示器(feof),
如果是读取过程中出错也返回NULL,不过设置的是错误指示器(ferror)。
示例:
int main()
{
char str[100];
//从stdin流中读取(10 - 1)个字符放入str中
while(fgets(str, 10, stdin)!=NULL)
printf("%s\n\n", str);
return 0;
}
运行实例:
补充:
1.fgets每次最多读取num-1个字符,最后一位会自动放入 ‘\0’
2.读取过程中 ‘\n’ 也会被当做正确字符读入字符串中
3.fread
size_t fread(void* _Buffer, size_t size, int count, FILE* _Stream);
以二进制形式从文件流中读取数据,
size为一个数据的大小,
count为数据的个数
它的返回值为读取的数据个数,如果不等于 count则表示读取出问题了。
放到后面与fwrite一起介绍
(六)puts、fputs、fwrite
int puts(char* str);
int fputs(char* str, FILE* _Stream);
size_t fwrite(void* _Buffer, size_t size, int count, FILE* _Stream);
1.puts
int puts(char* str);
向stdout写入字符串,成功就返回非负数,否则返回EOF
2.fputs
int fputs(char* str, FILE* _Stream);
向流中写入字符串,写入文件时只有遇到’\0’才停止,并且’\0’不会被写入文件中,
成功就返回非负数,否则返回EOF。
示例:
int main()
{
char str[100] = { 0 };
while (fgets(str, 20, stdin) != NULL)
{
fputs(str, stdout);
//等同于:puts(str);
putchar('\n');
}
return 0;
}
运行实例:
补充:puts、fputs会在输出结束时自动换行
3.fwrite
size_t fwrite(void* _Buffer, size_t size, int count, FILE* _Stream);
以二进制形式进行写入
示例:
int main()
{
FILE* pf = fopen("ppp.txt", "wb");
printf("以二进制形式将字符串信息写入ppp.txt文件\n\n");
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
fwrite(arr, sizeof(int), 10, pf);
fclose(pf);
pf = NULL;
int an[10] = { 0 };
char str[100] = { 0 };
pf = fopen("ppp.txt", "rb");
printf("以二进制形式从ppp.txt文件中读取字符串信息\n\n");
fread(an, 4, 10, pf);
for(int i=0;i<10;i++)
printf("输出:%d\n", an[i]);
fclose(pf);
pf = NULL;
return 0;
}
运行实例:
三、
总结
以上就是我们C语言常用输入输出函数的全部内容,如果有什么疑问或者建议都可以在评论区留言,感谢大家的支持,欢迎来评论区一起探讨,大家的鼓励是继续更新的巨大动力。