各种输入、输出方法总结(C语言)

为了避免反复造轮子,我就当一回牛顿(站在dalao的肩膀上),把他们已经做好的高质量轮子打包到这篇博客里

参考博客:C语言中(字符串)输入scanf()、gets()、fgets()以及getchar()、getc()函数的联系与区别
参考博客:输入函数scanf,gets,getchar简单区别测试
参考博客:c语言的getchar()与getc()详解
参考博客:gets()和fgets()在输入中的差异(fgets会多吃一个回车符号’\n’)
参考博客:c语言gets()函数与它的替代者fgets()函数
参考博客:getc、fgetc、getchar、ungetc
参考博客:(转)getch getche getchar的区别和缓冲区的概念
参考博客:fprintf fscanf等函数的用法
参考博客:C语言中的getchar()与putchar()详解
参考博客:puts()函数详解
参考博客:c语言的getchar()与getc()详解
参考博客:随笔–C语言–putchar()和putc()函数
参考博客:C语言 fgets函数与fputs函数用法
参考博客:putc、fputc、putchar
参考博客:fputc、putc、putchar


本文包含的输入方法有(按照顺序):
scanf、getchar、gets、getc、fgetc、fgets、ungetc、getche、getch 不包含(fread、fscanf)
本文包含的输出方法有(按照顺序):
print、putchar、puts、putc、fputs、fputc 不包含(fwrite、fprintf)


引用某篇博客的话(仅供参考):
在这里插入图片描述


输入方法:

scanf()

#include <stdio.h>
int main()
{
    char ch1, ch2;
    scanf("%c", &ch1);
    scanf("%c", &ch2);
    printf("%d %d\n", ch1, ch2);
    return 0;
}

运行结果如下:
在这里插入图片描述
原因如下:
scanf从输入流缓冲区中提取数据,并非在键盘缓冲区里面提取数据。
1.当我们用键盘输入一个a的时候,然后会按enter,在按enter之前,a在键盘缓冲区,而输入流缓冲区里面并没有东西,scanf处于等待状态。
2.当我按下enter之后,字符a和enter都进入输入流缓冲区,scanf开始读取一个字符a,然后再读取一个enter,输入流缓冲区已经没有东西了。此时我们也输出了。

对于输入两个字符:

#include <stdio.h>
int main(){
    char ch1,ch2;
    //注意第一个scanf里面的空格
    scanf("%c %c",&ch1,&ch2);
    printf("%d %d\n",ch1,ch2);

    scanf("%c%c",&ch1,&ch2);
    printf("%d %d\n",ch1,ch2);
    return 0;
}

第一个scanf和第二个scanf,都输入a b,会出现什么不同的结果?
在这里插入图片描述
这是为什么呢?
过程是这样的:
第一个scanf里面%c %c之间有一个空格,所以在输入字符a之后,我们可以输入空格,enter,或者任何一个字符,scanf都会自动忽略它,从而当我们输入字符b 的时候scanf准确无误的读入。因此printf得到的就是a和b对应的ASCII码97和98。此时输入流缓冲区里面仍然有一个enter(键入b之后按下的enter),所以第二次输入a和b,其实只读取了一个enter和a,于是得到的就是10和97。

对于字符串:

char str[20];
scanf("%s",str);

使用scanf()把一串字符串读进一个字符数组时,不使用&

#include <stdio.h>
int main()
{
    char str1[20], str2[20];
    scanf("%s",str1);
    printf("%s\n",str1);

    scanf("%s",str2);
    printf("%s",str2);
    return 0;
}

运行结果如下:
在这里插入图片描述
分析如下:
其实这里的原因和字符读入是一样的。
hello world!在按下enter以后,包括enter都进入到输入流缓冲区,
而scanf遇到 回车(enter),空格,TAB 就会停止,所以当第一个scanf遇到了hello以后的第一个空格时,就停止读取数据了.
因此str1就是hello (包括空格),而 C!还在缓冲区中,所以第2个scanf会直接从输入流缓冲区中读取 C!

补充_1:
scanf()函数调用成功,则返回成功读入的数据项数,否则,读入数据时遇到了"文件结束",则返回EOF(可以当作 - 1)

如:scanf("%d %d",&a,&b);

函数返回值为int型。如果a和b都被成功读入,那么scanf的返回值就是2

如果只有a被成功读入,返回值为1

如果a和b都未被成功读入,返回值为0

补充_2:
什么是非法数据 ? 如:
对于%d来说,除了 int 型都是非法数据

getchar()

#include <stdio.h>
int main(){
    char ch1,ch2;
    ch1=getchar();
    ch2=getchar();
    printf("%d %d\n",ch1,ch2);
    return 0;
}

运行结果如下:
在这里插入图片描述
原因如下:
getchar从输入流缓冲区中提取数据,并非在键盘缓冲区里面提取数据。
1.当我们用键盘输入一个a的时候,然后会按enter,在按enter之前,a在键盘缓冲区,而输入流缓冲区里面并没有东西,getchar处于等待状态。
2.当我按下enter之后,字符a和enter都进入输入流缓冲区,getchar开始读取一个字符a,然后再读取一个enter,输入流缓冲区已经没有东西了。此时我们也输出了。

可以利用循环将字符依次读入到字符串数组,getchar()可以接收换行符,因此需要在循环读入的过程中消除换行字符。

char s[20];
int n=0;
while(1)
{
	s[n]=getchar();   // 读入1个字符
	if (s[n]=='\n')
	{
		break;  // 如果是换行符,则结束循环;相当于清除缓存中输入确定的换行符
	}
	n++;
} 
int getchar(void);

注意getchar()返回的是int型哦~

gets()

#include <stdio.h>
int main()
{
    char str1[20], str2[20];
    gets(str1);
    printf("%s\n",str1);

    gets(str2);
    printf("%s\n",str2);
    return 0;
}

运行结果如下:
在这里插入图片描述
这是因为:gets可以接受空格
而且gets()函数从标准输入(键盘)读入一行数据,所谓读取一行,就是遇到换行符就返回。gets()函数并不读取换行符’\n’,它会把换行符替换成空字符’\0’,作为C语言字符串结束的标志

而且gets()读取字符是没有上限的

char* gets(char *s);

注意gets()返回的是char型指针哦~
所以还可以这么用:

char str[20];
char *ptr;
ptr = gets(str);

关于 scanf、getchar、gets 总结如下:

1. scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中)。
2. getchar()以Enter结束输入,也不会舍弃最后的回车符。
3. gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!

getc()

函数原型:

int getc(FILE *stream)//表示从文件读取字符

注意getc()返回的是int型哦~

从键盘输入一个字符

a = getc(stdin)//从输入缓冲区读取字符

如果读取失败或者到了文件结束标志返回EOF(-1)

fgetc()

在C语言中fgetc()和getc()的用法是一样的,但是最大的区别在于:fgetc()是函数,getc()是宏(其中fget前面的字母f即为function函数的意思)使用这两个函数时,需要注意如下几点:

1、 getc的参数不应当是具有副作用的表达式。有副作用的表达式,指的是表达式执行后,会改变表达式中某些变量的值。比如++i * ++i
2、 因为fgetc一定是一个函数,所以可以得到其地址。这就允许将fgetc的地址作为一个参数传送给另一个函数
3、 调用fgetc所需时间很可能长于调用getc,因为调用函数通常所需的时间长于调用宏

所以一般情况下用getc()就好了

fgets()

gets()和fgets()的相同点

  1. fgets的参数stream指定为stdin时,两者都能从标准输入中读取字符串。

  2. 读取成功都返回地址,失败都返回NULL

gets()和fgets()的不相同点

  1. 用法不同,fgets()可以设置接收字符个数
  2. fgets()会多吃一个回车符号’\n’(即fgets()函数会读取换行符)

举例

#include <stdio.h>
#include <string.h>
 
int main()
{
	char buf[1024] = {0};
	gets(buf);
	int len = strlen(buf);
 
	printf("len = %d\n", len);	
 
	char buf2[1024] = {0};	
	fgets(buf2, sizeof(buf2), stdin);
	
	len = strlen(buf2);
	printf("len = %d\n", len);
 
	return 0;
}

结果如下:
在这里插入图片描述
说明虽然fgets()设置读取3个字符,但实际最后吃掉了换行符(即把’\n’作为最后一个字符)

因为gets()没有接收上限,且gets()不会检查数组是否能够装的下输入行,所以总的来说,fgets()比gets()安全

ungetc

原型:

int ungetc(int c, FILE *stream);//一般写stdin

作用:能向流stream中放回一个字符(除了EOF字符)
尽管ISO C支持放回任何个的字符,但是实现中我们不应该放回超过一个字符

不能使用ungetc()将字符放回文件或者设备,因为它们保存在标准IO库的缓冲区中

举例

#include <stdio.h>
int main()
{
	int i,sum = 0;
	char ch;
	while(scanf("%d",&i) == 1) //一直输入一直循环
	{
		sum+=i;
		while((ch = getchar()) == ' ') //屏蔽空格
			;
		if(ch == '\n') break;
		ungetc(ch,stdin);
	}
	printf("%d",sum);
	return 0;
}
input: 22 33 33 44
output: 132

ungetc()在此的作用是返回getchar()多接收的一个字符(非空格字符)给 标准输入流(stdin)

getche()

在头文件< conio.h>中

#include<stdio.h>
#include<conio.h>
int main()
{
    char ch;
    for(int i=0;i<5;i++)
    {
        ch=getche();
        printf("%c",ch);
    }
	return 0;
}

结果如下:
在这里插入图片描述
getche()是用于获取单个字符的,与getchar()的区别就是:getche()实际是一个输入命令,作用是从键盘接收一个字符,而且并把这个字符显示出来,就是说,你按了一个键后它在屏幕上显示,并继续运行后面的代码

getch()

在头文件< conio.h>中

#include<stdio.h>
#include<conio.h>
int main()
{
    char ch;
    for(int i=0;i<5;i++)
    {
        ch=getch();
        printf("%c",ch);
    }
	return 0;
}

结果如下:
在这里插入图片描述
getch()也是用于获取单个字符的,作用与getche()类似,唯一的区别就是:getch()从键盘接收一个字符,却不把这个字符显示出来,就是说,你按了一个键后它在屏幕上不显示,但是继续运行后面的代码

缓冲区刷新

缓冲区刷新是非常重要的,不然容易导致数据混乱,对我们的程序造成很大的影响。
这里只简述 C 里面最常用的刷新方式:

int fflush(FILE *stream);//里面写 stdin,即标准输入流
//成功返回0

输出方法:

print()

printf()函数的输出格式很多,可以根据不同格式加转义字符,达到格式化输出
(因为经常用,所以我就不讲了)

putchar()

作用是输出一个字符

#include <stdio.h>
int main()
{
    char ch = 's';
    putchar(ch);//打印字符 s
    return 0;
}

注意:putchar()和getchar()都是把字符当做int类型而不是char类型来使用的

puts()

puts()只能输出字符串、Space、Enter、Tab

#include<stdio.h>
int main()
{
    char token[20] = "12 \n12";
    puts(token);
	return 0;
}

结果如下:
在这里插入图片描述
注意:使用 puts() 后,系统会在自动在其后添加换行符(’/n’)

putc()

作用是输出一个字符

#include<stdio.h>
int main()
{
    putc('a',stdout);
    putc('\n',stdout);
    putc(97,stdout); //97的 ASCII码是 a
	return 0;
}

结果如下:
在这里插入图片描述

fputs()

fputs()也是用于输出字符串,但是fputs()的函数原型不大一样是:

#include<stdio.h>
int main()
{
    char token[20] = "12 \n12";
    fputs(token,stdout); //第二个参数可以指向任意流,这里写的是输出流
	return 0;
}

结果如下:
在这里插入图片描述
fputs()和 puts()有两个小区别:

  1. puts()只能向标准输出流输出,而 fputs()可以向任何流输出

  2. 使用 puts()时,系统会在自动在其后添加换行符,而使用 fputs()时,系统不会自动添加换行符

fputc()

类似于fgetc和getc之间的关系,fputc()的用法与putc()一样
区别在于:putc()是宏定义,fputc()是函数,putc()的调用效率相对会比fputc()高一些(宏高于函数)


感言:我觉得有关于 输入、输出方法(C语言),这应该是在CSDN博客平台上写的最全的一篇博客吧(毕竟都是总结别人的…)

如有问题请及时在评论区反馈,若还想看有关于C++的输入方法总结,传送门在此

发布了92 篇原创文章 · 获赞 35 · 访问量 6385

猜你喜欢

转载自blog.csdn.net/CourserLi/article/details/102972614