一只高傲的鹤 发表于 2022-1-6 12:20:55

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


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

#include <stdio.h>

int main()
{
    int count = 0 ;

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

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

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

    return 0;
}

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

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

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

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

 

番杰 发表于 2022-1-6 12:46:44

对,这个程序就是用来统计字符个数的;
之所以你输入“你好”,
打印出是4,是因为每个中文占用2个字符;所以结果就是2*2 = 4;

一只高傲的鹤 发表于 2022-1-6 15:01:59

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

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

按理count = count + 1 的作用的只是循环体里面的一个计数器,我输入多少次它计多少次?难道 getchar函数是会将我的输入的汉字拆分成两个字符分别输入两次?

番杰 发表于 2022-1-6 15:37:02

一只高傲的鹤 发表于 2022-1-6 15:01
我知道一个中文是2个字符,但是我想知道这串代码为什么输出这个结果。

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

对,就是一个中文当成两个字符来看的,执行了两次count=count+1

一只高傲的鹤 发表于 2022-1-6 16:27:12

番杰 发表于 2022-1-6 15:37
对,就是一个中文当成两个字符来看的,执行了两次count=count+1

有原理解释吗?我上面那个只是根据结果推导的猜想,我想知道是如何拆成两次?并且为什么执行两次 count = count + 1 ?一个汉字是一次输入进去的系统为什么会拆分成两次输入?

番杰 发表于 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个字节,你问有什么原理解释,但凡你想知道,百度一下什么都有了,学习不是只知道去问别人,而是自己去找答案的过程。

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

一只高傲的鹤 发表于 2022-1-7 12:47:21

中文为什么占两个字符我知道,在很久之前我了解过这个问题了,我并不是疑惑中文为什么占两个字符!
我想要了解的是:
1. 汉字的编码是一个整体,输入一个汉字为什么是计两次输入?
2. 像你说的,“你”二进制表示的可能是xx,xx是一起输入的,为什么程序为什么不是只读取x1,然后丢掉x2 ?
3. 有时候回复可能表述不是很清楚,但我从始至终表达的是想弄清楚这串代码运行的逻辑,这是我的目标。

fishc_zmf 发表于 2022-1-7 14:21:38

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



int main()
{
    int count = 0 ;
    char c;
    printf("请输入英文字符:");

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

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

    return 0;
}

关于getchar函数可参考这里getchar的使用

一只高傲的鹤 发表于 2022-1-7 21:54:25

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

懂了,你太优秀了,向你学习,验证的代码也很有用,谢谢!

一只高傲的鹤 发表于 2022-1-7 22:04:23

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

还有个问题,那我输入的回车键是先缓存,还是直接执行while循环体?
1.如果是先缓存,那为什么我按回车程序直接运行了?
2.如果是直接执行,那while语言拿什么来结束循环?
我这个不是杠,只是有点没想明白。

fishc_zmf 发表于 2022-1-8 09:54:31

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

回车也是缓存了的而且也返回了。执行getchar函数时,在没有缓存区里没有回车(换行符)时程序就等着用户在输入按键,存在回车(换行符)后,才将缓存区的第一个字符返回,然后并且释放。
while结束可以不用'\n'结束,这个可以由你决定。
你可以试着写这个程序
while ( (c = getchar()) != 'z')
    {
      printf("%c\n",c);//或者putchar(c);
    }
输入不带'z'的几个字符,相信你会有所发现,另外可以多变换一下程序验证下自己的猜想。

番杰 发表于 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;

一只高傲的鹤 发表于 2022-1-8 16:54:46

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

谢谢,学到了你解决问题的思路,楼下的贴输入缓冲区解释更清晰。

一只高傲的鹤 发表于 2022-1-8 16:56:41

番杰 发表于 2022-1-8 10:02
你好好看看这个文章就懂了:输入缓冲区
回车相当于开关,输入回车,开始从输入缓冲区(或称是:输入流) ...

谢谢,很感谢你提供 输入缓冲区 资料,让我有一个新的认知。
但是关于我这个帖子的最佳答案是楼上那位好友前面回答的内容

一只高傲的鹤 发表于 2022-1-8 20:10:43

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

你好,本来我想选你这个贴子为 最佳答案 ,但是你里面有个概念说错了。不是回车之后数据才进入 “输入缓冲区”,而是我们键盘输入的数据先在“输入缓冲区”,按下回车之后才输送到程序中,建议你也可以看一下楼下好心人发的贴子链接。{:5_110:}

哎呀呀呀呀12138 发表于 2022-4-22 14:53:27

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

感谢你的链接呀,朋友!!
页: [1]
查看完整版本: getchar() != \n 和 while语句结合统计字符数,count = count + 1的作用