Jimmy Chen

A Programmer

C Primer Plus 第六版 第八章课后编程练习答案

编程环境Visual Studio 2017

此文为博主原创文章,转载请注明出处

  1. Ninw说道:

    第八题
    开始输出选项以外的字符,都能进入下一条语句。

    1. jimmychen说道:

      Thanks!有个逻辑判断没写对,已经改好了

      1. 是个新手说道:

        楼主,Practice 4 中 这个判断条件 if ((' ' == ch || '\n' == ch) && !isspace(ch_pre))
        若果输入 an , , , (字符后面跟空格和逗号)单词总数就增加。觉得在原有基础上加一个条件 if((' ' == ch || '\n' == ch) && !isspace(ch_pre) && !ispunct(ch_pre))

        1. jimmychen说道:

          是的,这里是我考虑不够周全,加上这个判断会更好

  2. ch说道:

    楼主第4题的ch_pre是什么意思

    1. jimmychen说道:

      记录前一个字符内容,用来判断连续空格使用的

  3. Nossier Ped说道:

    楼主你好,我现在也在做第八章的习题,关于第2题,我和您答案基本相同,但是题目中说“每次遇到换行符打印新的一行”,我理解的意思是程序允许输入多行,而不是在按下回车后就显示结果,应该是在按下Ctrl+D后才显示结果,所以感觉咱们的答案都不符合题意,但我水平有限,不知如何改正,望能得到您的答复,若我有表述不清的地方,还请您和我一同讨论,感谢您的博客,对我学习这本书有很大帮助。

    1. jimmychen说道:

      因为书不在身边,所以具体意思我这边暂时看不了了,那就先按照你的意思来理解。如果要做到按下Ctrl-D后才显示的话,一方面控制台要通过系统函数来直接获取到键盘的输入值,否则输入值都是会缓存在输入缓冲区的;其次就是通过char数组将所有的输入值缓存起来了,下面是我按照这个要求写的程序,与你交流:

      1. LandY说道:

        怎么贴代码啊?

  4. aiguo说道:

    https://blog.csdn.net/weixin_43481677/article/details/83245561 楼主 这是我自己写的书上第八章程序清单8.8 的链接 但是运行起来和书上不一样,我输入a 的时候 这个程序不打印case a 的内容 ,不知道哪里出问题了 麻烦有空帮忙看下

    1. jimmychen说道:

      你的main函数while循环后面多了个分号啊,自己好好检查一下。另外你打印的信息显示退出条件是输入d,但是你判断的条件是输入q,这里也不太对

      1. aiguo说道:

        谢谢楼主 按照你的指正 修改好 运行起来就和书上一样了

  5. aiguo说道:

    https://blog.csdn.net/weixin_43481677/article/details/83377919 第八章习题 有好几处问题,评论框太小了,装不下,麻烦楼主点看链接 解答下 谢谢

  6. 闵波路三舅说道:

    第4题我找到了一个简单的方法,可以模仿书上的程序 7.7 第195页的题目
    #include
    #include
    int main(void)
    {
    int lisd;
    lisd = 0;
    char ch;
    bool kad = false;
    while ((ch = getchar()) != EOF)
    {
    if (!isspace(ch) && !kad && !ispunct(ch))
    {
    kad = true;
    lisd++;
    }
    if ((isspace(ch) && kad)||ispunct(ch))
    {
    kad = false;
    }
    putchar(ch);
    }
    printf("单词数为 %d 个", lisd);
    }
    同时解决了标点符号问题

    1. 闵波路三舅说道:

      头文件用了 ctype.h

    2. 不吃鱼的汤姆猫说道:

      差不多啊大兄弟,书上7.7还统计了字符数和行数 :confused:

  7. UM-Li说道:

    楼主您好,第四题的解法似乎未处理“ch 为字母且 ch_pre 为标点”的情形,输入流中有标点紧跟的单词不被计入总词数。文本“Yes!”测试返回 0 单词、0 字母、-NaN 字母/词。

  8. Orcion祈祷说道:

    第五题优化了一下 这个可以有输入验证了 但不知道会不会啰嗦了一点

    #include
    int main()
    {
    char ch = 0;
    int upper = 100;
    int lower = 0;
    int guest = 50;

    printf("I guest the number is 50. Is it right(Y/N)?");
    scanf("%c", &ch);
    getchar();

    while ('Y' != ch)
    {
    if ('N' == ch)
    {
    printf("Ok, the number you chosen is bigger or smaller than I guest?(B/S) : ");
    scanf("%c", &ch);
    getchar();
    if ('B' == ch)
    {
    lower = guest;
    guest = (lower + upper) / 2;
    }
    else if ('S' == ch)
    {
    upper = guest;
    guest = (lower + upper) / 2;
    }
    else
    {
    printf("ATTENTION ! Sorry I can only understand B/S. Please enter again \n");
    continue;
    }

    printf("I guest the number is %d, Is it right(Y/N)?", guest);
    scanf("%c", &ch);
    getchar();
    continue;
    }
    if ('N' != ch)
    {
    printf("Is it %d? Please enter again: (Y/N)", guest);
    scanf("%c", &ch);
    getchar();
    continue;
    }
    }

    printf("It is %d. HAHA, I win!", guest);

    return 0;
    }

  9. LandY说道:

    /*
    * 通过前一个字符和当前字符判断是否是一个单词有三种情况
    * no prev current result action
    * 1 0 1 单词开始 n_char++
    * 2 1 1 单词中 n_char++
    * 3 1 0 单词结束 n_word++
    *
    * 而在只计算字符总数, 和单词总数的情况下情况1和情况2就简化,合并为一条语句,即只判断
    * 当前字符是不是字母即可.
    * 而在当前字符不是字母的情况下,前一个字符只有两种情况是或不是,如果是表示单词结束,
    * 如果不是,表示还未接收到单词. 当前题目下只需要对是的情况作出动作即可.
    * 所以第二个条件和简化后的第一个条件再次简化,合并为一条 if..else if.. 语句
    */
    # include
    # include

    int main(void)
    {
    int prev ; // 前一个字符
    int ch ; // 当前字符
    long n_char = 0 ; // 字符数量
    long n_word = 0 ; // 单词数量

    while ((ch = getchar()) != EOF)
    {
    if (isalpha(ch))
    n_char++ ;
    else if (isalpha(prev))
    n_word++ ;
    prev = ch ;
    }
    printf("Total words: %ld , Total characters: %ld , Characters per word:%.2lf",
    n_word , n_char , n_word == 0 ? 0.0 :(double)n_char / (double)n_word);

    return 0 ;
    }

    1. LandY说道:

      贴出来的样子都变了
      ___________________________________
      no prev current result action
      ....
      ...
      ____________________________________
      这一段是一个制表符对齐的真值表
      我用语言描述一下
      情况1: 前一个字符 不是字母 , 当前字符 是字母 ; 认为单词开始 , 字符数+1
      情况2:前一个字符 是字母 , 当前字符 是字母; 认为在单词中, 字符数+1
      情况3:前一个字符 是字母 , 当前字符 不是字符; 认为单词结束, 单词数+1

      还有后面的 笑脸我也是醉了, 我在重新贴一次代码

  10. LandY说道:

    /*第四题:编写一个程序,在遇到EOF之前,把输入作为字符流读取,该程序要报告平均每个单词的字母数,不要把空白统计为单词的字母.实际上标点符号也不应该统计,但时现在暂时不用考虑这么多(如果你比较在意这点,考虑使用ctype.h 系列中的ispunct()函数).

    * 通过前一个字符和当前字符判断是否是一个单词有三种情况
    * no prev current result action
    * 1 0 1 单词开始 n_char++
    * 2 1 1 单词中 n_char++
    * 3 1 0 单词结束 n_word++
    *
    * 而在只计算字符总数, 和单词总数的情况下情况1和情况2就简化,合并为一条语句,即只判断
    * 当前字符是不是字母即可.
    * 而在当前字符不是字母的情况下,前一个字符只有两种情况是或不是,如果是表示单词结束,
    * 如果不是,表示还未接收到单词. 当前题目下只需要对是的情况作出动作即可.
    * 所以第二个条件和简化后的第一个条件再次简化,合并为一条 if..else if.. 语句
    */
    # include
    # include

    int main(void)
    {
    int prev ; // 前一个字符
    int ch ; // 当前字符
    long n_char = 0 ; // 字符数量
    long n_word = 0 ; // 单词数量

    while ((ch = getchar()) != EOF)
    {
    if (isalpha(ch))
    n_char++ ;
    else if (isalpha(prev))
    n_word++ ;
    prev = ch ;
    }
    printf("Total words: %ld , Total characters: %ld , Characters per word:%.2lf",
    n_word , n_char , n_word == 0 ? 0 : (double)n_char / (double)n_word);

    return 0 ;
    }

    1. xzy说道:

      你好,你这个 n_word == 0 ? 0 : (double)n_char / (double)n_word;为什么放到前面就不行呐,可以用if else给解释下吗 ,麻烦您了

  11. Han Lu说道:

    你好楼主, 关于第八题对choice的判断,您写了
    while (getchar() != '\n‘)
    {
    continue;
    }
    continue;

    我有点疑惑,无论while是否为真,所执行的代码都是continue, 那为何不直接写一个continue呢?我是个新手,如果问了有哪里不对请多包涵。

    1. jimmychen说道:

      你截取的代码中,第一个continue是跳过while循环的,这个while循环主要是去除输入缓冲区中的输入,第二个continue主要是跳过外部的do循环的,之后会让用户再进行输入选择

  12. 888说道:

    // practice 5
    没有考虑选择的数字就是50 的情况吧,

    1. 888说道:

      问题搞错了,应该是 scanf_s("%c", &ch);应该提供一个数字以表明最多读取多少位字符;
      改成 scanf_s("%c", &ch,1);不然会出差。

回复 jimmychen 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注