鱼C论坛

 找回密码
 立即注册
查看: 1870|回复: 15

[已解决]getchar() != \n 和 while语句结合统计字符数,count = count + 1的作用

[复制链接]
发表于 2022-1-6 12:20:55 | 显示全部楼层 |阅读模式

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

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

x
​
今天学了一个统计字符数的代码(使用的编译器是code blocks 20.03):

  1. #include <stdio.h>

  2. int main()
  3. {
  4.     int count = 0 ;

  5.     printf("请输入英文字符:");

  6.     while ( getchar() != '\n')
  7.     {
  8.         count = count + 1;//这个算式不是用来计数的吗?为什么中文会计对应两个字符?
  9.     }

  10.     printf("你总共输入了%d个字符", count);

  11.     return 0;
  12. }
复制代码


本来我理解&#160;&#160;count = count + 1&#160; 这个表达式是用来统计字符数的。

但是我在试着输入中文的时候,程序统计中文是2个字符,结果如下:

请输入英文字符:你好
你总共输入了4个字符

&#160;所以,我想重新了解一下这个程序是怎么统计字符的?能否对代码的每一个作用部位有一个详细解释?谢谢

&#160;

&#8203;
最佳答案
2022-1-8 10:02:35
一只高傲的鹤 发表于 2022-1-7 22:04
还有个问题,那我输入的回车键是先缓存,还是直接执行while循环体?
1.如果是先缓存,那为什么我按回车 ...

你好好看看这个文章就懂了:输入缓冲区
回车相当于开关,输入回车,开始从输入缓冲区(或称是:输入流)中读取数据,注意回车也是存在其中的,getchar(每次读一个字符),你输入“你好回车”,在输入缓冲区里相当于“xxyy\n”,(有回车才开始读)
第一次循环:从输入流里读出x1(“你”的前一半),即ch = x1 ,不等于‘\n’,进入循环,执行count++,此时count = 1;
第二次循环:从输入流里读出x2(“你”的后一半),即ch = x2 ,不等于‘\n’,进入循环,执行count++,此时count = 2;
第三次循环:从输入流里读出y1(“好”前一半),即ch = y1 ,不等于‘\n’,进入循环,执行count++,此时count = 3;
第四次循环:从输入流里读出y2(“好”后一半),即ch = y2 ,不等于‘\n’,进入循环,执行count++,此时count = 4;
第五次循环:从输入流里读出\n(回车),即ch =  ‘\n’,退出循环,执行printf,此时count = 4;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-1-6 12:46:44 | 显示全部楼层
对,这个程序就是用来统计字符个数的;
之所以你输入“你好”,
打印出是4,是因为每个中文占用2个字符;所以结果就是2*2 = 4;

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-6 15:01:59 | 显示全部楼层
番杰 发表于 2022-1-6 12:46
对,这个程序就是用来统计字符个数的;
之所以你输入“你好”,
打印出是4,是因为每个中文占用2个字符; ...

我知道一个中文是2个字符,但是我想知道这串代码为什么输出这个结果。

按理  count = count + 1 的作用的只是循环体里面的一个计数器,我输入多少次它计多少次?难道 getchar  函数是会将我的输入的汉字拆分成两个字符分别输入两次?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-6 15:37:02 From FishC Mobile | 显示全部楼层
一只高傲的鹤 发表于 2022-1-6 15:01
我知道一个中文是2个字符,但是我想知道这串代码为什么输出这个结果。

按理  count = count + 1 的作 ...

对,就是一个中文当成两个字符来看的,执行了两次count=count+1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-6 16:27:12 | 显示全部楼层
番杰 发表于 2022-1-6 15:37
对,就是一个中文当成两个字符来看的,执行了两次count=count+1

有原理解释吗?我上面那个只是根据结果推导的猜想,我想知道是如何拆成两次?并且为什么执行两次 count = count + 1 ?一个汉字是一次输入进去的系统为什么会拆分成两次输入?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-6 16:59:13 | 显示全部楼层
本帖最后由 番杰 于 2022-1-6 17:00 编辑
一只高傲的鹤 发表于 2022-1-6 16:27
有原理解释吗?我上面那个只是根据结果推导的猜想,我想知道是如何拆成两次?并且为什么执行两次 count = ...

在计算机中存储中文使用的编码规则是GB2312或GB2312-80,规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,连在ASCII里本来就有的数字、标点、字母都通通重新编了两个字节长的编码,这就是常说的“全角”字符,而原来在127号以下的那些就叫“半角”字符。

就这么说吧,字母和英文输入法下的一些标点符号都可以用ascii码形式表示,占一个字符,
而汉字和中文下的标点符号就用到了其他的解码标准来实现,像GB2312之类的标准,还有其他的感兴趣自行百度。它是占两个字符的,这也是为啥你打代码的时候,英文的分号可以,而中文的分号不可以,他俩代表着不同的数值;

再说回你的这个问题,你输入“你好”,在计算机看来就相当于输入了四个字符:“xxyy ”(具体是啥我也不知道,xx合在一起表示“你”,yy合在一起表示“好”,这个具体的值根据使用到解码规则有关),所以在循环的时候就一共执行了4次count++;所以结果是4.

另外,我之前已经说了中文占2个字节,你问有什么原理解释,但凡你想知道,百度一下什么都有了,学习不是只知道去问别人,而是自己去找答案的过程。

再另外,我之前也是单纯的知道中文占两个字符,也没具体的去了解过,为了你这个问题,我还特意去百度的,这些应该都是你自己去完成,而不是等着别人把答案告诉你。

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
kkk聪 + 5 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-1-7 12:47:21 | 显示全部楼层
中文为什么占两个字符我知道,在很久之前我了解过这个问题了,我并不是疑惑中文为什么占两个字符!
我想要了解的是:
1. 汉字的编码是一个整体,输入一个汉字为什么是计两次输入?
2. 像你说的,“你”二进制表示的可能是xx,xx是一起输入的,为什么程序为什么不是只读取x1,然后丢掉x2 ?
3. 有时候回复可能表述不是很清楚,但我从始至终表达的是想弄清楚这串代码运行的逻辑,这是我的目标。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-7 14:21:38 | 显示全部楼层
在输入 “你好” 的时候,在没有按回车之前只是存在缓存区,while里面的count = count + 1;这句并没有执行。
在你按下回车之后,我们的输入才被送进去了输入缓冲区,这个时候,while循环才开始工作,内部机制才将一个中文转换成两个字符进行计算。
你可以将代码改成这样验证一下
  1. #include "stdio.h"



  2. int main()
  3. {
  4.     int count = 0 ;
  5.     char c;
  6.     printf("请输入英文字符:");

  7.     while ( (c = getchar()) != '\n')
  8.     {
  9.         printf("%c\n",c);
  10.         count = count + 1;//这个算式不是用来计数的吗?为什么中文会计对应两个字符?
  11.     }

  12.     printf("你总共输入了%d个字符", count);

  13.     return 0;
  14. }
复制代码


关于getchar函数可参考这里getchar的使用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-7 21:54:25 | 显示全部楼层
fishc_zmf 发表于 2022-1-7 14:21
在输入 “你好” 的时候,在没有按回车之前只是存在缓存区,while里面的count = count + 1;这句并没有执行 ...

懂了,你太优秀了,向你学习,验证的代码也很有用,谢谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-7 22:04:23 | 显示全部楼层
fishc_zmf 发表于 2022-1-7 14:21
在输入 “你好” 的时候,在没有按回车之前只是存在缓存区,while里面的count = count + 1;这句并没有执行 ...

还有个问题,那我输入的回车键是先缓存,还是直接执行while循环体?
1.如果是先缓存,那为什么我按回车程序直接运行了?
2.如果是直接执行,那while语言拿什么来结束循环?
我这个不是杠,只是有点没想明白。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-8 09:54:31 | 显示全部楼层
一只高傲的鹤 发表于 2022-1-7 22:04
还有个问题,那我输入的回车键是先缓存,还是直接执行while循环体?
1.如果是先缓存,那为什么我按回车 ...

回车也是缓存了的而且也返回了。执行getchar函数时,在没有缓存区里没有回车(换行符)时程序就等着用户在输入按键,存在回车(换行符)后,才将缓存区的第一个字符返回,然后并且释放。
while结束可以不用'\n'结束,这个可以由你决定。
你可以试着写这个程序
  1. while ( (c = getchar()) != 'z')
  2.     {
  3.         printf("%c\n",c);//或者putchar(c);
  4.     }
复制代码

输入不带'z'的几个字符,相信你会有所发现,另外可以多变换一下程序验证下自己的猜想。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-8 10:02:35 | 显示全部楼层    本楼为最佳答案   
一只高傲的鹤 发表于 2022-1-7 22:04
还有个问题,那我输入的回车键是先缓存,还是直接执行while循环体?
1.如果是先缓存,那为什么我按回车 ...

你好好看看这个文章就懂了:输入缓冲区
回车相当于开关,输入回车,开始从输入缓冲区(或称是:输入流)中读取数据,注意回车也是存在其中的,getchar(每次读一个字符),你输入“你好回车”,在输入缓冲区里相当于“xxyy\n”,(有回车才开始读)
第一次循环:从输入流里读出x1(“你”的前一半),即ch = x1 ,不等于‘\n’,进入循环,执行count++,此时count = 1;
第二次循环:从输入流里读出x2(“你”的后一半),即ch = x2 ,不等于‘\n’,进入循环,执行count++,此时count = 2;
第三次循环:从输入流里读出y1(“好”前一半),即ch = y1 ,不等于‘\n’,进入循环,执行count++,此时count = 3;
第四次循环:从输入流里读出y2(“好”后一半),即ch = y2 ,不等于‘\n’,进入循环,执行count++,此时count = 4;
第五次循环:从输入流里读出\n(回车),即ch =  ‘\n’,退出循环,执行printf,此时count = 4;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-1-8 16:54:46 | 显示全部楼层
fishc_zmf 发表于 2022-1-8 09:54
回车也是缓存了的而且也返回了。执行getchar函数时,在没有缓存区里没有回车(换行符)时程序就等着用户在 ...

谢谢,学到了你解决问题的思路,楼下的贴输入缓冲区解释更清晰。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-8 16:56:41 | 显示全部楼层
番杰 发表于 2022-1-8 10:02
你好好看看这个文章就懂了:输入缓冲区
回车相当于开关,输入回车,开始从输入缓冲区(或称是:输入流) ...

谢谢,很感谢你提供 输入缓冲区 资料,让我有一个新的认知。
但是关于我这个帖子的最佳答案是楼上那位好友前面回答的内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-1-8 20:10:43 | 显示全部楼层
fishc_zmf 发表于 2022-1-7 14:21
在输入 “你好” 的时候,在没有按回车之前只是存在缓存区,while里面的count = count + 1;这句并没有执行 ...

你好,本来我想选你这个贴子为 最佳答案 ,但是你里面有个概念说错了。不是回车之后数据才进入 “输入缓冲区”,而是我们键盘输入的数据先在“输入缓冲区”,按下回车之后才输送到程序中,建议你也可以看一下楼下好心人发的贴子链接。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-22 14:53:27 | 显示全部楼层
fishc_zmf 发表于 2022-1-7 14:21
在输入 “你好” 的时候,在没有按回车之前只是存在缓存区,while里面的count = count + 1;这句并没有执行 ...

感谢你的链接呀,朋友!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-2 20:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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