C代码是如何工作的?

C代码是如何工作的?,c,arrays,C,Arrays,简介:我正在学习K&R的《C编程语言》,我遇到了下面一段我无法理解的代码 守则: 输出: 我理解代码在做什么,但我无法理解它是如何做的。 为什么我们要使用++ndigit[c-'0'];在代码中?0 2 2 1 1 1 1 1是每个数字0 0、2 1、2 2 2、2 3、1 4、1 5。。。 29-既不是数字也不是空白的符号数 c-“0”是从字符ASCII码中获取整数的常用方法。例如: '0' - '0' == 0 '1' - '0' == 1 '9' - '0' == 9 0 2 2 1 1

简介:我正在学习K&R的《C编程语言》,我遇到了下面一段我无法理解的代码

守则:

输出:

我理解代码在做什么,但我无法理解它是如何做的。
为什么我们要使用++ndigit[c-'0'];在代码中?

0 2 2 1 1 1 1 1是每个数字0 0、2 1、2 2 2、2 3、1 4、1 5。。。 29-既不是数字也不是空白的符号数

c-“0”是从字符ASCII码中获取整数的常用方法。例如:

'0' - '0' == 0
'1' - '0' == 1
'9' - '0' == 9

0 2 2 1 1 1 1 1 1 1是每一位数字0 0,2 1,2 2 2,2 3,1 4,1 5。。。 29-既不是数字也不是空白的符号数

c-“0”是从字符ASCII码中获取整数的常用方法。例如:

'0' - '0' == 0
'1' - '0' == 1
'9' - '0' == 9

该C代码分析输入文本,并提供有关该输入的一些信息

digits =  0 2 2 2 1 1 1 1 1 1
是0、1、2、3、4、5、6、7、8和9的数目

white space = 7
是空格、换行符和表格的数量

other = 29

不是数字或空格的字符数。

该C代码分析输入文本并提供有关该输入的一些信息

digits =  0 2 2 2 1 1 1 1 1 1
是0、1、2、3、4、5、6、7、8和9的数目

white space = 7
是空格、换行符和表格的数量

other = 29

不是数字或空格的字符数。

NDIGTS数组记录输入的每个数字的频率。您没有输入0,因此数字0的计数为零,您输入数字1两次,因此位置1处数字1的计数为2,依此类推

nwhite变量保存空格计数、制表符和回车键


另一个变量保存所有其他变量的计数。

NDIGTS数组记录输入的每个数字的频率。您没有输入0,因此数字0的计数为零,您输入数字1两次,因此位置1处数字1的计数为2,依此类推

nwhite变量保存空格计数、制表符和回车键


另一个变量包含所有其他变量的计数。

算法中最麻烦的部分是数字频率的计算。具体而言,其中使用的索引机制

该算法通过使用计数器数组来工作。具体而言,这:

int ndigit[10];
是存储计数的位置。最初,该数组为零,并填充了后续的for循环:

for (i = 0; i < 10; i++)
{
    ndigit[i] = 0;
}
结果是x等于5。注意我没有说“5”这个字;我说的是整数5。这是因为实际的ASCII编码意味着您实际得到的整数计算是:

//      '5'  '0'
int x = 53 - 48;
你经常听到人们谈论魔术数字编程,这通常是一个例子。当您看到这样的代码时:

if (c == 48)
    do something with the char because it's a zero character
不要那样做。保持代码整洁并使用文字常量。它更容易阅读

if (c == '0')
目的是更干净

不管怎样,这在代码中是如何发挥作用的呢?嗯,它在这里起作用:

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

if ('7' >= '0' && '7' <= '9')
    ++ndigit['7' - '0'];
if (55 >= 48 && 55 <= 57)
    ++ndigit[55 - 48];
这是对输入文件中的所有数字字符执行的,最后显示每个数字字符被发现的次数的累积


我希望这能把事情弄清楚。剩下的我想你明白了。

算法中你似乎最麻烦的部分是数字频率的计算。具体而言,其中使用的索引机制

该算法通过使用计数器数组来工作。具体而言,这:

int ndigit[10];
是存储计数的位置。最初,该数组为零,并填充了后续的for循环:

for (i = 0; i < 10; i++)
{
    ndigit[i] = 0;
}
结果是x等于5。注意我没有说“5”这个字;我说的是整数5。这是因为实际的ASCII编码意味着您实际得到的整数计算是:

//      '5'  '0'
int x = 53 - 48;
你经常听到人们谈论魔术数字编程,这通常是一个例子。当您看到这样的代码时:

if (c == 48)
    do something with the char because it's a zero character
不要那样做。保持代码整洁并使用文字常量。它更容易阅读

if (c == '0')
目的是更干净

不管怎样,这在代码中是如何发挥作用的呢?嗯,它在这里起作用:

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

if ('7' >= '0' && '7' <= '9')
    ++ndigit['7' - '0'];
if (55 >= 48 && 55 <= 57)
    ++ndigit[55 - 48];
这是对输入文件中的所有数字字符执行的,最后显示每个数字字符被发现的次数的累积


我希望这能把事情弄清楚。其余的我想你明白了。

代码正在打印输入中每个数字0到9的出现次数。 在您的输入中:

sample text for stackoverflow
try 123
123456789
有: 数字“0”的0次出现 2次出现数字“1” 2次出现数字“2” 2次出现数字“3” 1出现数字“4” 1出现数字“5” 1出现数字“6” 1出现数字“7” 1出现数字“8” 1出现数字“9”

因此,输出为数字=0 2 2 1 1 1 1

空白=7 空格或换行符的数量。 other=29表示既不是数字也不是空格的字符数。


至于++ndigit[c-'0'];,我们使用[c-'0']通过替换ASCII值来获得等效的[c-48],但如果不使用幻数'48',使用幻数通常是一种不好的做法。

代码将打印输入中每个数字0到9的出现次数。 在您的输入中:

sample text for stackoverflow
try 123
123456789
有: 数字“0”的0次出现 2次出现数字“1” 2次出现数字“2” 2次出现数字“3” 1出现数字“4” 1出现数字“5” 1出现数字“6” 1出现数字“7” 1出现数字“8” 1出现数字“9”

因此,输出为数字=0 2 2 1 1 1 1

空格=7表示空格或换行符的数量。 other=29表示既不是数字也不是空格的字符数。


至于++ndigit[c-'0'];,我们使用[c-'0']通过替换ASCII值来获得等效的[c-48],但不使用幻数'48',使用幻数通常是一种不好的做法。

这本书详细描述了发生的情况。K&R文本的哪一段不清楚?@alk此代码在“数组”部分给出,我发现代码下的这一段不清楚。第22页,如果需要参考,我认为这是相当清楚的。我认为你的困惑在于它是如何做的。例如,计数器阵列是一个相当简单的概念。但用于定位在何处执行增量的索引(看起来很奇怪的c-“0”)很可能是一个混淆点。对吗?如果是这样或其他情况,您的问题可能会突出显示哪些特定代码让您感到困惑。@HarshitJindal我们不太可能比K&R做得更好。在调试器下运行代码,逐步检查代码,检查值,并告诉我们哪些行/行为/哪些内容让您感到困惑。”解释“很多”过于宽泛:在调试和询问之前重构可能会有所帮助。如果c-'0'不清楚,请将它拉到另一个变量中,这样您就可以更轻松地调试它并询问它。一旦你理解了它,你就可以给变量起一个名字,在你忘记它之后,这个名字可以把这个知识传达给未来的读者,包括你自己。或者,使用调试器的监视表达式、断点操作或类似功能,以便查看有问题的值。[读取它的一种方法是沿字符编号线与字符“0”的距离。参考:@alk]这本书详细描述了发生的情况。K&R文本的哪一段不清楚?@alk此代码在“数组”部分给出,我发现代码下的这一段不清楚。第22页,如果需要参考,我认为这是相当清楚的。我认为你的困惑在于它是如何做的。例如,计数器阵列是一个相当简单的概念。但用于定位在何处执行增量的索引(看起来很奇怪的c-“0”)很可能是一个混淆点。对吗?如果是这样或其他情况,您的问题可能会突出显示哪些特定代码让您感到困惑。@HarshitJindal我们不太可能比K&R做得更好。在调试器下运行代码,逐步检查代码,检查值,并告诉我们哪些行/行为/哪些内容让您感到困惑。”解释“很多”过于宽泛:在调试和询问之前重构可能会有所帮助。如果c-'0'不清楚,请将它拉到另一个变量中,这样您就可以更轻松地调试它并询问它。一旦你理解了它,你就可以给变量起一个名字,在你忘记它之后,这个名字可以把这个知识传达给未来的读者,包括你自己。或者,使用调试器的监视表达式、断点操作或类似功能,以便查看有问题的值。[读取它的一种方法是沿着字符编号线与字符“0”的距离。Ref:@alk]这似乎回答了我的问题。谢谢:-非常彻底-一如既往。我已经看到对计数器数组和频率数组的引用,对于这种类型的数组可以互换使用,其中每个元素都保存相应索引值的计数或出现频率。不知道其中一个是否比另一个更合适。计数器阵列当然符合要求。@davidc.rankin:计数器很好。频率,虽然也常用,但我觉得它有误导性,不能说错,因为它实际上被定义为1/s。这里没有时间测量,这似乎回答了我的问题。谢谢:-非常彻底-一如既往。我已经看到对计数器数组和频率数组的引用,对于这种类型的数组可以互换使用,其中每个元素都保存相应索引值的计数或出现频率。不知道其中一个是否比另一个更合适。计数器阵列当然符合要求。@davidc.rankin:计数器很好。频率,虽然也很常用,但我觉得这是一种误导,不能说是错误的,因为它是真实的 y定义为1/s。这里不涉及时间测量。