1

我目前正在阅读 Kernighan & Richie 的“The C Programming Language”,我正在努力弄清楚一行的作用。我想我只是有点愚蠢,并不太理解他们的解释。

++ndigit[c-'0'];

我不得不稍微改变程序,就像ndigit以前给我垃圾值一样,所以我只是将数组实例化为 0,而不是用 for 循环遍历它,并以这种方式更改值。

#include <stdio.h>

main()
{
    int c, i, nwhite, nother;
    int ndigit[10]= {0};

    nwhite = nother = 0;

    while ((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];
        else if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;
        else
            ++nother;

    printf("digits =");
    for (i = 0; i < 10; i++) 
        printf (" %d", ndigit[i]);
    printf (", white space = %d, other = %d\n", nwhite, nother);
}  

使用程序作为输入,我们将其打印到控制台 -

digits = 7 2 0 0 0 0 0 0 0 1, white space = 104, other = 291

我知道这7 2 0 0 0 0 0 0 0 1是单个数字出现在输入中的次数 0 出现 7 次,1 出现两次等)

但是,...[c-'0'];“工作”如何?

4

8 回答 8

4

你问下面的表达式是如何工作的

 c-'0'

输入字符的 ASCII 代码从 0 的 ASCII 代码中减去,它定义了数组中必须存储计数的位置。

假设您从键盘输入1,1的 ASCII 码是49,0的 ASCII 码是48。因此

   49-48 =1 

并且计数将存储在数组索引位置 1 中。

于 2013-07-23T10:37:57.587 回答
3

c-'0'是将 int 值 == 赋予字符数的技术,例如1for '1'5for '5'

char 符号'0', '1', '2' ..... '9'被分配继续编码值,因此数字 char 常量与'0'给出十进制数的差异。(在您的编译器中,例如在 ASCII char 中,它们被分配继续 acsii 值)。

因此,例如在变量c中是'7',然后c - '0'== 7;

在您声明为的代码数组中:

int ndigit[10]= {0};   
                // default initialized with `0`

所以索引可以是 from09。所以在你的代码中:

++ndigit[c-'0'];  // ndigit[c-'0'] = ndigit[c-'0'] + 1;

1在数字字符的相应数字处 增加数字的频率。

于 2013-07-23T10:32:53.003 回答
3

在 C 中,当你有一个cchar 类型的变量时,它实际上存储了 char 的一些整数编码(通常是ASCII码)。所以表示包含的字符和字符c-'0'的代码的区别。由于数字是自然顺序的,因此它会转换相关数字中的数字。c0

于 2013-07-23T10:34:40.103 回答
2

C 标准要求字符“0”到“9”具有连续值。

'0'将值零表示为字符,c 是您输入的值,它计算如下:

'1' - '0' == 1

'2' - '0' == 2

依此类推...即等于cif的值c是一个数字

于 2013-07-23T10:34:07.083 回答
2

Ascii 是一种将连续 id 赋予连续数字的编码。正如 Eric Postpischil 指出的那样,标准要求该属性,即使底层编码不必是 ascii。不过,Ascii 很常见。

char c1 = '0';
char c2 = '1';

因此,无论'0'映射到什么数字,'1'都将是该数字 + 1。本质上:

c2 == c1 + 1

从作为数字的字符中减去'0',将返回其数值:

'1' - '0' == 1
于 2013-07-23T10:34:07.650 回答
1

在 ASCII维基百科上查找。

美国信息交换标准代码 (ASCII /ˈæski/ ass-kee) 1是一种字符编码方案,最初基于英文字母表,对 128 个指定字符进行编码 - 数字 0-9、字母 az 和 AZ、一些基本标点符号符号、一些源自电传打字机的控制代码和一个空格 - 到 7 位二进制整数中。

所以在 ASCII 方案中,“0”字符是数字 48,字符“1”是 41,依此类推。所以 c - '0' 等价于 c - 48。如果 c 是 '1',则表达式变为 49 - 48 = 1。所以在几个单词中 'c' - '0' 转换一个数字字符 ['0'-'9 '] 转换为整数 [0-9]。

编辑 1 正如@Eric Postpischil 所建议的,ASCII 不是 ANSI C(也不是 c++)的一部分。但是很常见,我知道的所有编译器都使用 ASCII 集。

于 2013-07-23T10:38:17.280 回答
1
((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];

c给你当前的字符。通过范围检查,您可以通过使用其 ASCII 值 检查chr列来确认它是一个数字0,它说48,并且8它说56。所以,'8'- '0'给出56 - 48=8

ndigit用于跟踪数字出现的次数,数组的每个元素表示其下标出现的次数。 ndigit[0]会给你0发生的次数等等..给出出现ndigit[x]的次数x

[c - '0']

假设您的cie 当前角色8将给'8' - '0'8。所以你得到了那个值[你在开始时将它ndigit[8]初始化]++0

于 2013-07-23T10:38:32.900 回答
0

'0' 是一个字符,其值为 48。您可以在 google 中查找任何 ASCII 表。它是这样工作的,因为您从输入 char 值而不是 int 中读取,所以如果您不添加“-'0'”部分,它将增加数组的第 48 个单元格。你可以用“-48”代替“-'0'”,在我看来,这种方式更具可读性。

于 2013-07-23T10:34:59.263 回答