场景引入:
你是否在刷题过程中,经常遇到以下场景呢?
场景一:
场景二:
从这些题上都能看见输入描述中提出了一条多组输入,那啥是多组输入?如何实现它呢?
多组输入:在输入数据时,有多组数据需要分别处理的情况
接下来探究如何利用循环实现它。
如果还有不会循环的小伙伴可以看我之前写的一篇文章:初阶C语言-分支与循环结构-CSDN博客
📚常用的输入函数的介绍
📖字符类
📝getchar(字符输入函数,包含头文件stdio.h即可使用)
getchar
int getchar (void)
可用cplusplus官网查找到函数原型如下:
📌函数讲解
函数名 getchar
函数的参数 void
函数的返回类型 int
1.成功读取到字符则返回字符的ASCII码值
2.读取失败则返回EOF(-1)
选择EOF右击鼠标找到转到定义选项,点击。
可发现,EOF就是#define定义的常量,它的值就是-1,EOF的意思是the end of file,文件末尾标志。
💌举例:
#include <stdio.h>
int main()
{
int ch;
ch = getchar();
return 0;
}
☑️getchar函数的作用是从标准输入流读取(获得)一个字符,可以简单的理解为接收键盘输入的一个字符。这里我是从键盘输入字符a,可以看见ch这个变量存储的就是字符a对应的ASCII码值97
💌举例:
☑️这里我输入的是2,但是getchar会默认把我输入的2当做字符,输出字符2对应的ASCII码值50赋值给ch。
🤔如果输入字符串或者多位数的整数会有啥结果?
😶只会取第一个读到的字符。
📝putchar(字符输出函数,包含头文件stdio.h即可使用)
putchar
int putchar (int character)
📌函数讲解
函数名 putchar
函数的参数 int character
函数的返回类型 int
1.成功读取到字符则返回字符的ASCII码值,并在屏幕上输出读取到的字符
2.读取失败则返回EOF(-1)
💌举例:
#include <stdio.h>
int main()
{
int ch;
int a;
ch = getchar();
a = putchar(ch);
return 0;
}
☑️第一个a是我输入给getchar函数,第二个a是程序执行到putchar函数,在屏幕上(终端)上打印的字符a。ch接收了getchar函数的返回值,a接受了putchar函数的返回值,这里都是字符a对应的ASCII码值97。
📝字符类的多组输入
💌举例:设置一个程序,只有当输入的字符为数字时才将其输出
#include <stdio.h>
int main()
{
int ch;
while ((ch = getchar()) != EOF)
{
if (ch >= '0' && ch <= '9')
{
putchar(ch);
printf("\n");//单纯打印一个字符换个行,方便观察
}
}
return 0;
}
☑️多组输入按control+z+回车即可退出。
💌举例:场景一
#include <stdio.h>
int main()
{
int ch;
while ((ch = getchar()) != EOF)
{
if (ch >= 'A' && ch <= 'Z')//大写字母
putchar(ch + 32);
else if (ch >= 'a' && ch <= 'z')//小写字母
putchar(ch - 32);
printf("\n");//换行方便观察
}
return 0;
}
☑️大小写字母的ASCII码值之间相差了32。
🤔思考:同样是换行方便观察,为啥输出结果是这样呢?
😶事实上你输入的是字母然后按了个回车(ASCII码值是10),回车是转义字符'\n',等于你输入了两个字符。
☑️细心的你会发现上一个例题是满足条件才printf("\n"),而这次是经过一次循环就会进行一次printf("\n")。
改进:
#include <stdio.h>
int main()
{
int ch;
while ((ch = getchar()) != EOF)
{
if (ch >= 'A' && ch <= 'Z')//大写字母
{
putchar(ch + 32);
printf("\n");
}
else if (ch >= 'a' && ch <= 'z')//小写字母
{
putchar(ch - 32);
printf("\n");
}
}
return 0;
}
📖万能类
📝scanf(包含头文件stdio.h即可使用)
💌举例:
#include <stdio.h>
int main()
{
char password[20];
printf("请输入密码:");
scanf("%s", password);//数组名就是地址,可以不加&
printf("请确认你的密码:(Y/N)");
int ch = getchar();
if (ch == 'Y')
printf("确认成功\n");
else
printf("确认失败\n");
return 0;
}
🤔思考:为啥都没有让我输入Y/N就确认失败了呢?
😶输入缓冲区的引入
注:因为getchar读到的是缓冲区内的字符'\n'(回车),故出现了bug。
改进:在引入一个getchar读走\n,这个操作叫做清空缓冲区。
#include <stdio.h>
int main()
{
char password[20];
printf("请输入密码:");
scanf("%s", password);//数组名就是地址,可以不加&
printf("请确认你的密码:(Y/N)");
getchar();//处理掉缓冲区的\n
int ch = getchar();
if (ch == 'Y')
printf("确认成功\n");
else
printf("确认失败\n");
return 0;
}
其他清理缓存区的办法:
使用gets函数代替scanf函数接收字符串的输入
#include <stdio.h>
int main()
{
char password[20];
printf("请输入密码:");
gets(password);
printf("请确认你的密码:(Y/N)");
int ch = getchar();
if (ch == 'Y')
printf("确认成功\n");
else
printf("确认失败\n");
return 0;
}
gets函数还会顺带把缓冲区的\n一起带走。
🤔思考:若是读取整数的函数需要单独处理掉缓冲区的\n吗?
😶不需要,因为\n不是整数不会被读取。
📝scanf函数的多组输入
#include <stdio.h>
int main()
{
char arr[20];
while (scanf("%s", arr) != EOF)
{
printf("%s\n", arr);
}
return 0;
}
注:按三次control+z+回车即可退出多组输入。可以思考一下为啥这次不需要清空缓冲区。
可见scanf函数读取时以空格或者回车作为一次读取结束标志,当是循环时,输入空格分隔开的一串字符串会被识别为两串字符串。
若要对scanf输入字符串中就是含有空格可使用以下格式:
scanf("%[^\n]", arr);
#include <stdio.h>
int main()
{
char arr[20];
scanf("%[^\n]", arr);
{
printf("%s\n", arr);
}
return 0;
}
#include <stdio.h>
int main()
{
char arr[20];
while (scanf("%[^\n]", arr) != EOF)
{
printf("%s\n", arr);
}
return 0;
}
比较可惜的是这样会死循环,因为这种格式带不走缓冲区的内容,他只是把\n之前的字符拷贝一份放到了arr中,所以缓冲区一直有abcd abc,所以死循环了。
改进:
#include <stdio.h>
int main()
{
char arr[20];
while (scanf("%[^\n]", arr) != EOF)
{
printf("%s\n", arr);
int ch;
while ((ch = getchar()) != EOF && ch != '\n')//清空缓冲区
{
;
}
}
return 0;
}
注:按两次control + z +回车即可退出多组输入。
📚总结
本节介绍了多组输入以及相关输入函数,如何清空(输入)缓冲区的一些方法。在进行多组输入时,尤其使用能读取字符,字符串的函数时,小心未清理缓冲区而产生bug。