繁体   English   中英

Ritchie和Kernighan混淆的C程序

[英]C program confusing from Ritchie and Kernighan

我到处都读到,如果您是计算机科学专业的学生,​​那么在大学毕业之前,C是必不可少的语言。 我已经拿到了我的教授推荐的Ritchie and Kernighan第二版。 我对该程序的工作方式感到困惑。 如果有人可以解释,那就太好了! 该程序计算每个数字,空格和其他字符的出现次数。 我为已经了解的事情写了评论,并且在不了解它如何工作的地方添加了问题。

#include <stdio.h>

int main()
{
     int c, i, nwhite, mother;   //Declaring variables
     int ndigit[10];             //Declaring an array that holds indexes from 0-9

     nwhite = nother = 0;        //Initializes two variables to 0

     for (i = 0; i < 10; ++i)    //Does this for loop keep going through and for each index
             ndigit[i] = 0;      //0-9 set the value of it to 0?

     white ((c = getchar()) !=EOF)  //While loop to check if char at EOF
     {
          if (c>='0' && c <= '9')        //Completely lost on how this works?
               ++ndigit[c - '0'];
          else if (c == ' ' || c == '\n' || c == '\t')     //Checks for white space 
               ++nwhite;
          else                                   //If nothing else increment char variable
               ++nother;

     printf("digits ");               //First for loop traverses and prints each value of
     for (i=0; i<10; ++i)             //the index. The next printf prints white space and
          printf(" %d", ndigit[i]);   //other characters
      printf(", white space = %d, other = other = %d\n", nwhite, nother);
}

是的,这会遍历整个ndigit数组并将每个元素设置为0。

for (i = 0; i < 10; ++i)   
    ndigit[i] = 0; 

这里:

if (c>='0' && c <= '9')
    ++ndigit[c - '0'];

条件(上如果直插式)可能是最困难的事情理解:

像这样成像:

if( A and B)
    ...

有:

A = c>'0'

B = c<= '9'

也就是说,如果c在0到9之间(包括)。

希望这可以帮助。

(c >= '0' && c <= '9')        //Completely lost on how this works?

C语言中的char类型只是一个8位整数,通常是带符号的。 字符(如19与整数(如63)之间的对应关系由ASCII码定义。 如果c是数字,则上面截断的代码的值为1。 用C写'1'等效于写49

声明的整数数组的类型为auto,在C自动存储类中,整数数组将具有垃圾值。 因此,这些分配为零。

for (i = 0; i < 10; ++i)   
   ndigit[i] = 0; 

对于if语句,您正在检查给定字符是否在0-9之间。 由于其getchar()-(获取字符),因此将值与单引号进行比较

if (c>='0' && c <= '9') 

您也可以将此语句更改为

if (c>=48 && c <= 57)

由于ASCII 字符 “ 0”为48,而“ 9”为57

++ndigit[c - '0'];

您要对输入到数组中的数字进行计数,即假设输入为5,则将索引5处的数组计数增加1。

这里提到c-'0'是因为,如上所述,'5'的ASCII字符为53。因此,以上语句的结果为c-'0' = 5 (数组的索引5)

 int ndigit[10];             //Declaring an array that holds indexes from 0-9

 for (i = 0; i < 10; ++i)    //Does this for loop keep going through and for each index

在C数组中,索引从0开始,因此在这种情况下, ndigit的有效索引为0到9(含0和9)。 for循环开始从i = 0和增量i被一个( ++i ),只要i < 10 ,所以循环体获取的值来执行i从0到9,包括端值。

在此程序中,由读者自己确定这两个10字面是同一回事。 可以说,最好是#define一个常量并在两个地方都使用它(但是在这种情况下,可以原谅,因为小数位数恒定为10)。

 while ((c = getchar()) !=EOF)  //While loop to check if char at EOF

getchar返回一个字符从标准输入读取, EOF (其具有从任何不同的值char )如果标准输入是在文件末尾。 没有EOF字符可表示此情况。

      if (c>='0' && c <= '9')        //Completely lost on how this works?

十进制数字0到9的字符值在ASCII和大多数其他字符集中是连续的,因此此代码利用了这一点并检查c是否等于或大于'0' 并且&& )也等于或小于而不是'9' 换句话说,这将检查c是否在'0''9'之间的范围内(包括'0''9' '0''9'是字符文字,具有字符集中相应字符的整数值–这样, if (c>=48 && c<=57) ,程序员不必知道并写入它们的值。该代码适用于不兼容的字符集,只要数字字符具有连续的值即可。

           ++ndigit[c - '0'];

这将计算每个数字出现的次数。 同样,由于代表数字的字符是连续的,因此从读取的字符中减去第一个数字的值( '0' )得出对应字符的值0到9,这也是数组ndigit的有效索引,如以上讨论。 当然,该减法仅适用于数字字符,这就是前面的if对此进行检查的原因。

例如,在ASCII中, '0'值为48, '1'为49,依此类推。因此,如果c'1' ,则减法c - '0''1'-'0' ,即,49-48或1。

++运算符增加ndigit数组的相应索引中的ndigit (第一个for循环将ndigit的初始值设置为零。)

EOF End-of-file的缩写-是在stdio.h头文件中定义的宏。 宏是已命名的代码片段。 无论在何处使用该名称,该名称都将替换为宏的内容。 它是一个值,表示当无法从源中读取更多字符时的条件,在这种情况下,该源为stdin标准输入流,通常是键盘。 简而言之,对于任何字符c ,条件ch == EOF始终为false。 因此,在您通过* nix系统上的Ctrl+D和Windows系统上的Ctrl+Z发出EOF信号之前,以下条件将一直从stdin读取:

white((c = getchar()) != EOF) {
}

接下来,此条件检查读取的字符c是否为数字字符,即十进制数字。

if(c>='0' && c <= '9') {  // check if c is a numeric character.
} 

C中的字符实际上是整数值(认为它们是1-byte整数),并且等于相应字符的ASCII码(尽管C标准没有强制要求)。 在ASCII中,字符09的代码值按升序排列。 因此,如果满足上述条件,则意味着c是数字字符。

++ndigit[c - '0'];

在上面的语句中, c - '0'是转换为整数值的数字字符。 因此,如果c的值为'8' ,则c - '0'计算结果为8 接下来,它在索引为8的数组ndigit中获取值,该值保留数字8计数,并将其递增1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM