目录
前言:
从今天起开启全新专栏
c语言基础语法编程题100题!
专栏链接
1、题目展示:

2、问题分析:
1、首先先要解决输入问题。
要求:输入多组数据,每组占一行,有三个字符组成,之间无空格
有空格的输入需要使用fgets或者gets_s
输入三个字符中间无空格,那么只需要用scanf即可
char a,b,c;
scanf("%c%c%c",&a,&b,&c);
那么关键在于如何一次输入多组数据呢?
这里就会联想到循环,本题每一组输入3个字符,那么循环条件是输入的字符个数为3,如果不等于3就跳出循环
那么循环条件要怎么写,我们应该还记得scanf的返回值和我们输入的数的个数有关
以scanf("%d%d",&a,&b);举例
* 输入两个数:返回2。
* 输入部分正确(如一个数字和一个非数字):返回1。
* 输入完全无法解析(如两个非数字):返回0。
* 遇到EOF:返回EOF(-1)
那么只要我们让循环条件为scanf返回值始终等于3,那么我们一直每组输入3个数就不会跳出循环,如下
while(scanf("%c%c%c",&a,&b,&c)==3){
printf("%c %c %c",a,b,c);
}
但是上面的代码忽略了一个问题
先介绍缓冲区的概念
输入缓冲区是临时存储用户输入数据的内存区域。例如,当用户通过键盘输入 `Hello\n` 时:
* **缓冲区内容**:`H`, `e`, `l`, `l`, `o`, `\n`。
* **换行符的提交作用**:按下回车键(生成 `\n`)会将缓冲区内容提交给程序。
问题场景:
若程序仅读取部分数据(如 `scanf("%s", str)` 读取 `"Hello"`),剩余的 `\n` 会残留在缓冲区中,导致后续输入函数(如 `fgets()` 或 `getchar()`)意外读取到换行符
也就是第一次输入abc之后\n留在了缓冲区,导致下一次while循环scanf读取的第一个字符是换行符\n,导致程序错乱,输入不了多组字符如下

因此我们 在输完每一行之后,要让电脑去掉换行符,清理缓冲区。怎么做呢?
先把代码写下来,我们慢慢来分析
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
第一行定义一个叫ch的整型变量
第二行一个while语句,语句内部没有需要循环体语句和条件控制语句
那么就是只要满足括号内的条件判断语句,就不断的把上一次变量的ch值覆盖掉,让下一次getchar的值可以赋值进来,仅通过不断读取并覆盖 `ch` 变量来清空缓冲区。
那么现在着重分析括号内的条件判断语句
(ch = getchar()) != '\n' && ch != EOF
一个复杂的表达式,进行拆解
(ch = getchar()) != '\n' )&&( ch != EOF)
就是当两边的不等于关系运算符都成立时,条件判断语句成立
先看左边
getchar是一个系统函数,包含在头文件stdio.h里
作用是:从标准化输入设备(比如键盘)读取一个字符,不需要传参数(也就是括号里什么东西都不用写)
返回值是读取字符的ASCII码值
那么ch = getchar()) != '\n'的意思就是,getchar把读取的字符的返回值赋值给变量ch,与‘\n换行符的ASCII码值进行比较
当ch的值不等于‘\n换行符的ASCII码值时,成立
也就是如果getchar读取到换行符,则ch = getchar()) != '\n'这个表达式不成立
再看右边
ch != EOF,EOF时文件结束符,时程序结束的标志
那么如果getchar读取的字符是EOF,并且赋值给了ch
那么ch=EOF,表达式不成立
因此while ((ch = getchar()) != '\n' && ch != EOF);整句话的意思就是
只要遇到换行符和EOF文件结束符循环就结束了,那么你肯定有疑问,循环结束了怎么清理缓冲区里的换行符
当你输入一行字符(例如`abc`后按回车),`getchar()`会逐个读取字符`a`、`b`、`c`,最后读取换行符`\n`。此时,`ch`被赋值为`\n`,循环条件失败,**循环终止**。关键点在于:**换行符`\n`已经被`getchar()`读取到`ch`中**,因此输入缓冲区中不再残留该换行符
**EOF的处理**:如果输入以`EOF`结束(例如通过`Ctrl+D`或`Ctrl+Z`触发),`getchar()`会返回`EOF`,循环同样终止。需要注意的是:
* 在终端输入中,若`EOF`之前无换行符(例如输入`abc`后直接`Ctrl+D`),`EOF`会被“吃掉”(即不被`getchar()`读取),输入缓冲区中仅保留已处理的字符。
* 若`EOF`之前有换行符(例如输入`abc\n`后`Ctrl+D`),则换行符会被读取,`EOF`作为文件结束标志终止输入。
**缓冲区的最终状态**在循环终止后,**所有字符(包括换行符或`EOF`)均已从缓冲区中取出**。因此,无需额外清理缓冲区
当用户从键盘输入数据时,数据首先存储在输入缓冲区中,而不是直接传递给程序。只有当用户按下回车键或缓冲区满时,缓冲区中的数据才会被传递给程序。输入缓冲区通常在遇到换行符时刷新,这意味着程序会读取缓冲区中的数据直到遇到换行符为止
当第一次while循环时,输入的字符都存在缓冲区里,当你换行时,虽然前面输入的字符被刷新了但,换行符留了下来
while(scanf("%c%c%c",&a,&b,&c)==3){ printf("%c %c %c",a,b,c);}
那么整个多组数据输入并且输出的代码是怎么样的,电脑又是怎么处理的

2、解决排序问题
随意输入三个字符,要把他们进行排序
排序问题我们这里介绍利用变量转换的思想的方法,这是大家总结经验验证出来的方法,从小到大排序就用这个方法,也非常好记
char a,b,c,t;
scanf("%c%c%c",&a,&b,&c);
//假设a=3,b=4,c=1 拿数字举例是一样的
if(a>b){
t=a,a=b,b=t; //不满足,不执行这一句
}
if(a>c){
t=a,a=c,c=t; //a=1,c=3
}
if(b>c){
t=b,b=c,c=t; //b=3,c=4
}
printf("%c %c %c\n",a,b,c);//这样按顺序输出a b c,就是按ASCII码值从小到大 的顺序了
扩展 从大到小怎么排序
char a,b,c,t;
scanf("%c%c%c",&a,&b,&c);
//假设a=3,b=4,c=1
if(a<b){
t=a,a=b,b=t; // a=4, b=3
}
if(a<c){
t=a,a=c,c=t; //不执行
}
if(b<c){
t=b,b=c,c=t; //不执行
}
printf("%c %c %c\n",a,b,c);//这样按顺序输出a b c,就是按按ASCII码值从大到小的顺序了
再优化一下,我们把这个排序的代码变成函数,用到了指针
void paixu(char*a,char*b,char*c){ //void是没有返回值的函数,所以我们不用写return 返回值 //a,b,c是传入的参数
char t;
if(*a>*b){
t=*a,*a=*b,*b=t;
}
if(*a>*c){
t=*a,*a=*c,*c=t;
}
if(*b>*c){
t=*b,*b=*c,*c=t;
}
}
3、最终代码展示:
注意在main函数里a,b,c的值要传进paixu函数,涉及值传递,需要用到指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void paixu(char* a, char* b, char* c) {
char t;
if (*a > *b) {
t = *a, * a = *b, * b = t;
}
if (*a > *c) {
t = *a, * a = *c, * c = t;
}
if (*b > *c) {
t = *b, * b = *c, * c = t;
}
}
int main() {
char a, b, c;
while (scanf("%c%c%c", &a, &b, &c) == 3) {
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
paixu(&a, &b, &c);
printf("%c %c %c\n", a, b, c);
}
return 0;
}

5万+

被折叠的 条评论
为什么被折叠?



