| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3778 人关注过本帖, 1 人收藏
标题:当for循环体是getchar时,是怎么执行的?
只看楼主 加入收藏
duanlt8
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:70
专家分:107
注 册:2011-9-15
结帖率:90.91%
收藏(1)
已结贴  问题点数:5 回复次数:10 
当for循环体是getchar时,是怎么执行的?
int i;
    char c;
    for (①i = 0; ②i<=5; ③i++)
    {
        ④c = getchar();
        ⑤putchar( c );
    }

执行顺序是1  2  4  5  3 后面在来5次2 4 5 3
最后编译运行时是输入6个字符  输出6个字符.
我想问的是当执行到4的时候,它是手动输入,然后在执行5输出,这其中为什么不是立即输入输出(就是一个个的输入输出)然后在执行第二轮循环呢?  而是等到最后连续输入6个字符
2011-11-15 22:44
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:5 

授人以渔,不授人以鱼。
2011-11-15 22:53
woshiaokeman
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:60
专家分:123
注 册:2011-4-5
收藏
得分:0 
我看书的时候他是说把你输入的数据放到缓冲区,回车后再到计算机。最后再输出。不晓得是不是这样。
2011-11-16 00:32
duanlt8
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:70
专家分:107
注 册:2011-9-15
收藏
得分:0 
回复 3楼 woshiaokeman
2楼神人啊
2011-11-16 01:14
duanlt8
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:70
专家分:107
注 册:2011-9-15
收藏
得分:0 
回复 2楼 TonyDeng
原来如此   谢谢啦!
不过16楼 现在看的还不太懂 以后估计会懂!
不过仔细想了下,还想问下到底是那种方式:
一:调试运行之后,我输入第一个字符完后,在这之前是不是只执行到了第一个循环的4,输入完第一个字符后,在执行5,然后吧字符放到什么缓冲区,在执行3,  是不是这样的一个循环,然后6个字符输入完之后 按回车, 才从缓冲区调出6个字符输出?
二:还是调试运行,  执行到4之后,把这个字符空间放入缓冲区,然后执行5 吧这个输出空间也放出缓冲区,然后在3; 最后循环结束之后, 缓冲区有6个字符空间, 然后在dos界面输入6个字符 ,回车之后在释放这6个输出空间?

char a[80]="AB"    ,b[80]="LMNP";
    int i = 0;
    strcat (a,b);
    puts(a);
    while (a[i++]!='\0')
    {
        b[i] = a[i];
    }
    puts(b);

    return 0;


结果:

ABLMNP
LBLMNP

为神马第二个结果第一个字符不是a?

[ 本帖最后由 duanlt8 于 2011-11-16 01:37 编辑 ]
2011-11-16 01:34
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
循环时一定会到第一个getchar()函数处,如果此时控制台输入缓冲区为空(现在你的程序此时就是如此),那么它会开始进入等待输入数据状态,而控制台流输入的机制,是没遇到'\n'不会启动接收处理动作的,此时一定让你任意地敲键盘,但程序流程指针仍然停留在刚才的getchar()处。一旦你敲入回车,这个getchar()继续运行,它从你刚才键入的字符序列中提取出第一个字符'1'赋给变量c,然后到putchar(c)马上输出'1';程序循环,再到getchar()处,此时getchar()发现输入缓冲区已经有数据,于是它不会再像刚才那样停下来等待输入了,直接从剩下的序列中提取第一个字符'2'(因为先前的'1'已被提走),然后到putchar(c)输出'2'。如此运作下去。

现象的关键,是你什么时候敲下回车键。循环是6次,而你键入5个字符之后就回车,那么只执行了5次getchar(),还有一次,此时输入缓冲区已空,那么getchar()就得等待。你再键入5个字符,则循环内最后一次getchar()把第一个字符提走,缓冲区中还剩下4个(这些残留的字符会一直留在缓冲区中,它们将被后续的任何流输入函数接收,这是很困惑人的,所以一般要用fflush(stdin)函数把输入缓冲区清空,换言之,你如果在for循环内每次getchar()之后都fflush(stdin),那么就可以实现敲一次键输出一次的目的)。

与此问题相关的一个实例,是如下这个帖子的第9楼:https://bbs.bccn.net/thread-355275-1-1.html

注意:getchar()函数不接收空格,你没办法用它收到空格字符,这是我曾经测试过的效果,具体情形记不太清楚,你可以自己设计测试一下。

第二个问题:while(a[i++]!='\0')这里,刚进入循环时,i=0,a[0]!='\0',然后下一行时,i已为1,此时执行的是b[1]=a[1],因此就是你看到的结果。写程序时,如果你没有把握这样的i++动作是否影响b[i]=a[i]的执行,就不要把i++那样写,让它清晰化,单独一行写在你希望起作用的位置,这样多写一行,不会影响程序的执行效率(因为编译器会优化出应有的效率),但你程序出错的可能性就变为零——这在程序设计规范中叫“避免不必要的优化”,亦即不要总是手工优化,那样通常增加出错的概率,没人说这样的代码风格是很好的。也不是代码行数越少程序效率越高的,事实往往与此相反,对C这种编译型程序来说,执行的是编译后的机器码,不是你写的源代码,你并不了解或精通编译器如何处置你的源代码为机器码,就不必做这种没有意义的事情——你写的无论是长是短,编译后的长短未必跟你写的一样。程序代码是写给人看的,清晰性第一,这是稍有实践经验的程序员都知道的道理,未出校门的学生才会以效率为第一优先顺序。

写程序代码时,脑子中一定要有清晰的程序流程图像,每写一行,都要十分清楚此时程序指针的动向——从什么地方来、将到什么地方去、数据如何变化等等。代码的复杂性,程序设计规范中有一种有强连通图衡量的方法,通俗来讲是根据程序片段的判断语句来计数,如果一段代码中(子函数)中的判断语句在3到9之间,是合适的,超过了,就可以断定为过于复杂,应考虑用函数分解它。这种衡量依据的理由是判断语句分支呈树状时,逻辑的支路会太多,人脑难以分析和记忆,则无论编写还是阅读、审核这样的代码,都比较容易出错。经验表明,程序的错误,往往就在这样的地方出现。因此,如果你看到某些人写的程序代码,一大堆if、while、for语句、甚至嵌套超过三层的,那就是这种应避免的情形,千万不要学这种风格。

[ 本帖最后由 TonyDeng 于 2011-11-16 03:12 编辑 ]

授人以渔,不授人以鱼。
2011-11-16 02:43
duanlt8
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:70
专家分:107
注 册:2011-9-15
收藏
得分:0 
回复 6楼 TonyDeng
听君一席话,胜看几个月的书啊,   这都是实际经验啊!

不过 b[1]=a[1]   不是字符B 嘛?难道调用的不是新的数组a[80]="ABLMNP"?  也不对啊,  我用putchar输出b[1]的值为B 啊
怎么会是L 呢 ,难不成是调用原来的b[80]="LMNP"  ?

[ 本帖最后由 duanlt8 于 2011-11-16 13:20 编辑 ]
2011-11-16 13:18
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
strcat(a,b)是把b追加在a的后面,b本身没变。b[1]=a[1]的时候,正是改变了b[1]的'M'为'B',b[0]仍然是'L',然后b[2]=a[2],因为a先前已经被追加,所以从a[2]开始是原来的b[]="LMNP",输出puts(b)就是"LBLMNP"。不过这样写出来的b[]没有'\0'结束符,我不知道你的程序为什么没有出错,正常情形应会崩溃。

strcat(a,b)后,a有6个字符,循环中把a从下标1开始的5个字符抄给b[1]开始,b[4]覆盖了原来的'\0',但循环遇到a[6]='\0'结束,故应该没有把'\0'抄到b[6]中,b[6]是未定义字符,那么b是一个没有结束符的字符数组。

[ 本帖最后由 TonyDeng 于 2011-11-16 14:36 编辑 ]

授人以渔,不授人以鱼。
2011-11-16 14:16
duanlt8
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:70
专家分:107
注 册:2011-9-15
收藏
得分:0 
回复 8楼 TonyDeng
//        a[10]="ABLMNP\0"

//    b[0]     ="L"
//i=0;    b[1]=a[1]="B"  ==>  b[10]="LBNP"
//i=1;    b[2]=a[2]="L"
//i=2;    b[3]=a[3]="M"  ==>  b[10]="LBLM"  //到这里原来的b值已被改了下面就添加了np\0;
//i=3;    b[4]=a[4]="N"
//i=4;    b[5]=a[5]="P"
//i=5;    b[6]=a[6]="\0"


这样的.  i=5的时候 执行的是a[6]  所以有\0
2011-11-16 15:44
zhaoxd
Rank: 1
等 级:新手上路
威 望:1
帖 子:7
专家分:0
注 册:2019-8-30
收藏
得分:0 
char a[80]="AB"    ,b[80]="LMNP";
    int i = 0;
    strcat (a,b);
    puts(a);
    while (a[i++]!='\0')
    {
        b[i] = a[i];
    }
    puts(b);

    return 0;
//这个是不是相当于下面这样,可是还是搞不懂为什么是这个顺序。。。
char a[80]="AB"    ,b[80]="LMNP";
    int i = 0;
    strcat (a,b);
    puts(a);
    while (a[i]!='\0')
    {
        i++;
        b[i] = a[i];
    }
    puts(b);

    return 0;

[此贴子已经被作者于2019-9-2 17:46编辑过]


学习学习
2019-09-02 17:32
快速回复:当for循环体是getchar时,是怎么执行的?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.037664 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved