鱼C论坛

 找回密码
 立即注册
查看: 43|回复: 1

[已解决]缓冲区只有一个回车符getche/getch函数为什么会这样读?

[复制链接]
发表于 昨天 14:28 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我的源码1(getche):
  1. #include <stdio.h>
  2. int main(){
  3.         char a;
  4.         a=getche();
  5.         printf("*****getche*****|n");
  6.         printf("###%c###",a);
  7.         return 0;
  8. }
复制代码

键盘输入一个回车,运行结果:
  1. *****getche*****
  2. ###
  3. --------------------------------
  4. Process exited after 1.042 seconds with return value 0
  5. 请按任意键继续. . .
复制代码


我的源码2(换成了getch):
  1. #include <stdio.h>
  2. int main(){
  3.         char a;
  4.         a=getch();
  5.         printf("*****getch*****\n");
  6.         printf("###%c###",a);
  7.         return 0;
  8. }
复制代码

键盘输入一个回车,运行结果:
  1. *****getch*****
  2. ###
  3. --------------------------------
  4. Process exited after 0.6937 seconds with return value 0
  5. 请按任意键继续. . .
复制代码

我的源码3(换成了getchar):
  1. #include <stdio.h>
  2. int main(){
  3.         char a;
  4.         a=getchar();
  5.         printf("*****getchar*****\n");
  6.         printf("###%c###",a);
  7.         return 0;
  8. }
复制代码

键盘输入一个回车,运行结果:

  1. *****getchar*****
  2. ###
  3. ###
  4. --------------------------------
  5. Process exited after 0.7316 seconds with return value 0
  6. 请按任意键继续. . .
复制代码


疑问:
getchar是正常读且输出了回车符,为什么getche和getch运行出来是那样?
最佳答案
昨天 14:30
你的问题涉及到 `getche`、`getch` 和 `getchar` 处理回车键的区别。以下是详细分析:

### 核心原因
1. **回车键的本质**:  
   - Windows 系统中,按下 `Enter` 键实际产生 **两个字符**:`\r`(回车符,ASCII 13)和 `\n`(换行符,ASCII 10)。  
   - Unix/Linux 中 `Enter` 只产生 `\n`,但你的环境是 Windows(从输出中的 `请按任意键继续` 可确认)。

2. **函数行为差异**:  
   - `getche` 和 `getch` 是 **非缓冲输入函数**(来自 `<conio.h>`),直接读取键盘输入,**不处理转换**。  
   - `getchar` 是 **缓冲输入函数**(来自 `<stdio.h>`),会处理 `\r\n` 并转换为 `\n`。

---

### 逐代码解析
#### 源码1:`getche`
  1. #include <conio.h>
  2. #include <stdio.h>
  3. int main() {
  4.     char a = getche();      // 直接读取键盘输入,按回车后 a = '\r'(ASCII 13)
  5.     printf("*****getche*****\n");
  6.     printf("###%c###", a);  // 输出时,'\r' 将光标移回行首,覆盖了前面的 ###
  7.     return 0;
  8. }
复制代码

**输出分析**:  
- 第一行 `*****getche*****` 正常输出。  
- 第二行 `###` 后遇到 `\r`,光标回到行首,接着输出 `###` **覆盖**了开头的 `###`,最终显示为 `###`(看似正常,实则是覆盖效果)。

---

#### 源码2:`getch`
  1. #include <conio.h>
  2. #include <stdio.h>
  3. int main() {
  4.     char a = getch();       // 直接读取键盘输入,按回车后 a = '\r'(ASCII 13)
  5.     printf("*****getch*****\n");
  6.     printf("###%c###", a);  // 同上,'\r' 导致覆盖
  7.     return 0;
  8. }
复制代码

**输出与 `getche` 相同**:原理一致,只是 `getch` 不回显输入字符。

---

#### 源码3:`getchar`
  1. #include <stdio.h>
  2. int main() {
  3.     char a = getchar();      // 从缓冲区读取,将 "\r\n" 转换为 '\n'(ASCII 10)
  4.     printf("*****getchar*****\n");
  5.     printf("###%c###", a);   // 输出 '\n' 会换行
  6.     return 0;
  7. }
复制代码

**输出分析**:  
- 输入回车后,`getchar` 读取到 `\n`。  
- `printf("###%c###", '\n')` 实际输出:  
  1. ###   // 先输出 "###"
  2.         // %c 对应 '\n' 换行
  3.   ###   // 再输出 "###"
复制代码

- 最终显示为两行 `###`。

---

### 疑问解答
> 为什么 `getche/getch` 的输出看起来只有一行 `###`,而 `getchar` 有两行?

- **`getche/getch`**:  
  读取到的是 `\r`(回车符),输出 `\r` 会使光标**回到行首**,导致后续字符覆盖前面的内容。看似一行,实则是覆盖效果。

- **`getchar`**:  
  读取到的是 `\n`(换行符),输出 `\n` 会**真正换行**,因此显示为两行。

---

### 验证方法
修改代码,输出字符的 ASCII 码值(避免转义字符影响):
  1. #include <stdio.h>
  2. int main() {
  3.     char a = getche();  // 或 getch()/getchar()
  4.     printf("\nASCII: %d", (int)a); // 回车键下:getche/getch 输出 13,getchar 输出 10
  5.     return 0;
  6. }
复制代码


---

### 总结
| 函数     | 所属头文件 | 输入处理方式         | 回车键读取结果 |
|----------|------------|----------------------|----------------|
| `getche` | `<conio.h>`| 非缓冲,直接读键盘   | `\r` (ASCII 13) |
| `getch`  | `<conio.h>`| 非缓冲,直接读键盘   | `\r` (ASCII 13) |
| `getchar`| `<stdio.h>`| 缓冲,转换 `\r\n` 为 `\n` | `\n` (ASCII 10) |

建议:  
- 需要处理回车键时,优先使用 `getchar`(跨平台兼容性好)。  
- 避免混用 `<conio.h>` 和 `<stdio.h>` 的输入函数。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 14:30 | 显示全部楼层    本楼为最佳答案   
你的问题涉及到 `getche`、`getch` 和 `getchar` 处理回车键的区别。以下是详细分析:

### 核心原因
1. **回车键的本质**:  
   - Windows 系统中,按下 `Enter` 键实际产生 **两个字符**:`\r`(回车符,ASCII 13)和 `\n`(换行符,ASCII 10)。  
   - Unix/Linux 中 `Enter` 只产生 `\n`,但你的环境是 Windows(从输出中的 `请按任意键继续` 可确认)。

2. **函数行为差异**:  
   - `getche` 和 `getch` 是 **非缓冲输入函数**(来自 `<conio.h>`),直接读取键盘输入,**不处理转换**。  
   - `getchar` 是 **缓冲输入函数**(来自 `<stdio.h>`),会处理 `\r\n` 并转换为 `\n`。

---

### 逐代码解析
#### 源码1:`getche`
  1. #include <conio.h>
  2. #include <stdio.h>
  3. int main() {
  4.     char a = getche();      // 直接读取键盘输入,按回车后 a = '\r'(ASCII 13)
  5.     printf("*****getche*****\n");
  6.     printf("###%c###", a);  // 输出时,'\r' 将光标移回行首,覆盖了前面的 ###
  7.     return 0;
  8. }
复制代码

**输出分析**:  
- 第一行 `*****getche*****` 正常输出。  
- 第二行 `###` 后遇到 `\r`,光标回到行首,接着输出 `###` **覆盖**了开头的 `###`,最终显示为 `###`(看似正常,实则是覆盖效果)。

---

#### 源码2:`getch`
  1. #include <conio.h>
  2. #include <stdio.h>
  3. int main() {
  4.     char a = getch();       // 直接读取键盘输入,按回车后 a = '\r'(ASCII 13)
  5.     printf("*****getch*****\n");
  6.     printf("###%c###", a);  // 同上,'\r' 导致覆盖
  7.     return 0;
  8. }
复制代码

**输出与 `getche` 相同**:原理一致,只是 `getch` 不回显输入字符。

---

#### 源码3:`getchar`
  1. #include <stdio.h>
  2. int main() {
  3.     char a = getchar();      // 从缓冲区读取,将 "\r\n" 转换为 '\n'(ASCII 10)
  4.     printf("*****getchar*****\n");
  5.     printf("###%c###", a);   // 输出 '\n' 会换行
  6.     return 0;
  7. }
复制代码

**输出分析**:  
- 输入回车后,`getchar` 读取到 `\n`。  
- `printf("###%c###", '\n')` 实际输出:  
  1. ###   // 先输出 "###"
  2.         // %c 对应 '\n' 换行
  3.   ###   // 再输出 "###"
复制代码

- 最终显示为两行 `###`。

---

### 疑问解答
> 为什么 `getche/getch` 的输出看起来只有一行 `###`,而 `getchar` 有两行?

- **`getche/getch`**:  
  读取到的是 `\r`(回车符),输出 `\r` 会使光标**回到行首**,导致后续字符覆盖前面的内容。看似一行,实则是覆盖效果。

- **`getchar`**:  
  读取到的是 `\n`(换行符),输出 `\n` 会**真正换行**,因此显示为两行。

---

### 验证方法
修改代码,输出字符的 ASCII 码值(避免转义字符影响):
  1. #include <stdio.h>
  2. int main() {
  3.     char a = getche();  // 或 getch()/getchar()
  4.     printf("\nASCII: %d", (int)a); // 回车键下:getche/getch 输出 13,getchar 输出 10
  5.     return 0;
  6. }
复制代码


---

### 总结
| 函数     | 所属头文件 | 输入处理方式         | 回车键读取结果 |
|----------|------------|----------------------|----------------|
| `getche` | `<conio.h>`| 非缓冲,直接读键盘   | `\r` (ASCII 13) |
| `getch`  | `<conio.h>`| 非缓冲,直接读键盘   | `\r` (ASCII 13) |
| `getchar`| `<stdio.h>`| 缓冲,转换 `\r\n` 为 `\n` | `\n` (ASCII 10) |

建议:  
- 需要处理回车键时,优先使用 `getchar`(跨平台兼容性好)。  
- 避免混用 `<conio.h>` 和 `<stdio.h>` 的输入函数。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-14 12:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表