使用 n[c-'0'] 的真正用途是什么?

What's the real use of using n[c-'0']?

本文关键字:是什么 使用      更新时间:2023-10-16

我是一个C新手,我遇到了这样的代码:

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

if循环中,为什么我们必须在0周围使用单引号,它的用途是什么,为什么我们不能直接将0定义为整数?在第二行代码++n[c-'0']中,像这样使用数组有什么用,在某种意义上为什么我们需要从数组索引中的c中减去0(再次说明为什么在这种情况下使用单引号?)?

如果我喜欢这个n[c-'0'],索引操作(c-'0')的结果将是一个字符或整数?

有人能告诉我,这种数组的真正用途是什么,缺点是什么?

提前感谢。

在C语言中,'0'是一个整数,其值表示数字0作为字符,而不是值0,它将是空字符。其他答案省略了这一点,但重要的是要注意C语言强制要求十进制数字具有连续值,因此,如果c是一个数字,c-'0'是该数字的数值,即

'0'-'0' = 0
'1'-'0' = 1
'2'-'0' = 2
.
.
.
'9'-'0' = 9

c(可能)是char,它也具有整数表示,并且在C中可以隐式转换。'0'是字符0,数字字符的一个方便的特性是它们按照整数表示顺序排列。

那么,现在您知道每个字符都有整数表示,并且数字字符是按顺序排列的,您可以使用简单的减法将字符转换为整数表示。

'0' - '0' == 0
'1' - '0' == 1
'2' - '0' == 2
/* and so on and so forth */

因此,如果您想计算字符串中数字的出现次数,您可以使用它:

int n[10]; /* 10 digits */
n['0' - '0'] /* where we store the counts for the character 0, aka n[0] */
n['1' - '0'] /* where we store the counts for the character 1, aka n[1] */

你可能已经知道,计算机把字符表示为数字。C标准要求这种表示必须确保数字必须彼此紧跟着。如果n是'0'的代码,那么n + 9就是'9'的代码。对于ASCII,这些值分别是48和57。

你发布的代码示例试图是编码不可知的,而不是对48或57检查,它使用'0'作为一个可移植的常数。

看一下ASCII表,因为它本身可能已经很好地解释了它。字符'0'的十进制表示为48,'1'为49,等等。大多数(如果不是所有的话)编译器都遵循这个转换表。

通过减去'0'(很可能是数字48),您实际上将变量c的字符表示转换为数字表示。

edit:正如在注释中提到的,我应该指出'0'或'9'的数字表示不一定遵循ASCII转换表(尽管我相信所有通用编译器都遵循)。这是一个技术细节,属于ANSI C规范的讨论,而不是针对学习该语言的人的回答。

如果Ant碰巧写了int number = '0';,并且想知道为什么它存储数字48,那是因为他的编译器遵循ASCII转换。这个对于一个学习c基础知识的人来说既有用又有帮助。如果有哪个编译器不这样做,那就不是什么罕见的事情了,我很乐意把它留在那里,但我认为更多的时候,比起有用的回复,SO更看重迂腐。

也就是说,不使用实际的数字表示仍然是一件好事。也就是说,总是更喜欢写"0"而不是"48"。但很高兴知道为什么"0"最有可能由数字48表示。

'0''9'属于int类型。它们的值分别是48和57(因为48和57是字符'0''9'的ASCII值)。

所以你可能在n中保存一个数组来计数数字。

所以这个表达式(如果你在c上存储数字字符):

++n[c-'0'];

的意思是:

  1. 取n的位置号c-'0' (c上有一个数字)
  2. 将该位置增加1。

所以n将是:

n[0] = x; // count of 0 characters
n[1] = x; // count of 1 characters
n[2] = x; // count of 2 characters
n[3] = x; // count of 3 characters
n[4] = x; // count of 4 characters
n[5] = x; // count of 5 characters
n[6] = x; // count of 6 characters
n[7] = x; // count of 7 characters
n[8] = x; // count of 8 characters
n[9] = x; // count of 9 characters

例如,假设c等于字符22的ascii值为50。所以n[50-48]变成了n[2]。因此,您最终使用数组n的第三个元素来存储2字符数。

首先,if不是一个循环,它是一个语句。只需要通过一次代码。

这意味着第一行可以读取if c is a digit,第二行将ascii数字转换为整数(并增加n数组中的元素以计数该数字)。

脱离上下文,很难说为什么作者会这样做。

代码所做的是将字符'0'循环到'9',可能是将它们与某些用户输入进行比较。在循环体中,为了索引数组n,这些字符被映射到整数0..9

C中的字符在进行算术运算时可以表现得像整数,通过将其转换为ASCII整数表示。第一次循环时,c0, '0' - '0'为整型0,与'0'的整型值无关。也就是说,x - x总是等于0;在这种情况下,x的实际值并不重要。

考虑到这一点,并且ASCII值是顺序的,从0递增到9,您可以告诉第二次通过循环时,c将是'1', '1' - '0'是整数1,以此类推。

'0'表示一个字符值,它可以无声地转换为整数,结果(通常)是字符'0'的ASCII值(碰巧是48)。if条件验证c是(可转换为)一个包含数字的字符值。这是可能的,因为数字0到9在ASCII图中分别由48到57的连续值表示。如果从任意数字字符的ASCII值中减去'0'的ASCII值(即48),则得到该数字的数值(从0到9)。

所以上面的代码索引到一个计数器数组,可能是为了计算某些文本中每个数字的出现次数。

因为c是字符而不是整数

'0'的ASCII值是48,所以'0'在n[c]语句中将是索引48,程序员希望'0'是索引0,因为n被定义为n[10],所以ASCII值通过减去'0'的代码转换为其等效的整数,因此:'0' - '0' = 0, '1' - '0' = 1等。从"0"到"9"的ASCII码是48到57,所以转换是合理的。

至于为什么,我猜有人在计算数字"0"到"9"在某些文本中的频率。

允许使用char作为数组的索引。例如,您可以定义字符串"012345"(可能从外部文件读取),并计算每个字符c-'0',这将分别给出整数012345

这段(可怕的)代码映射了数字0的ASCII值。从9到0的索引。'0'的类型是数字类型char'0'的数值通常为48。从表示数字的char中减去48将为您提供char的"值"

这是将某物的ascii值转换为其数字的一种方法。在C语言中,字符'0'的ascii值是48。所以减去:

'0' - '0' = 0
'1' - '0' = 1
 ...
 c - '0' = <whatever the decimal number of c is>

方便的是,ASCII十进制数的增量是连续的,否则这个技巧将不起作用。换句话说,c必须是'0'之一。"9"才行。这解释了限制:

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

-'0'从给定的个位数整数中减去0(48)的ASCII值(应该只包含1位数字),从'0'到'9'的数字按顺序存储在ASCII码中,因此从给定的个位数整数中减去0的ASCII值将得到整数本身的数值。例如:- '4'的ascii值是52减去'0'的ascii值是48从52将给我们的数值4等于给定的整数,因此我们使用减法,而不是+'0'的加法,也减法或任何其他值的加法也不会导致给定整数的相同数值。

相关文章: