我遇到了一个编程问题,我只知道答案的一部分。
int f( char *p )
{
int n = 0 ;
while ( *p != 0 )
n = 10*n + *p++ - '0' ;
return n ;
}
这就是我认为该计划正在做的事情。 p是一个指针而while循环是DE-refrencing指针的值,直到它等于0.但是我不明白n赋值行,'0'在做什么?我假设p的值最初是负的,这是增量后它达到0的唯一方法。
答案 0 :(得分:3)
您将数字零(无,无)与字符0
(一个圆圈,可能带有斜线)混淆。请注意,零位于刻度线中,因此它是字符“0”,而不是数字零。
'0' - '0'= 0
'1' - '0'= 1
'2' - '0'= 2
......
因此,通过从数字中减去字符零,您将获得与该数字对应的数字。
所以,假设你有这个数字序列:'4','2','1'。你怎么从那里得到这个数字441?你将'4'变为四。然后你乘以十。现在你有四十岁了。将'2'转换为两个并添加它。现在你有四十二岁。乘以十。将“1”转换为一个,然后添加,现在你有一百二十一个。
这就是将数字序列转换为数字的方法。
答案 1 :(得分:2)
n
局部变量累积在字符串中传递给此函数的十进制数的值。这是atoi
的实现,没有有效性检查。
以下是循环体的工作原理:
n = 10*n + *p++ - ‘0';
将n
的先前值乘以10加上指针n
的当前字符代码减去零代码的结果分配给p
;在解除引用后增加p
。
由于数字字符是按顺序编码的,因此*p-'0'
表达式表示数字的十进制值。
假设您正在解析字符串"987"
。当你完成循环时,n
从零开始;然后它被赋予以下值:
n = 10*0 + 9; // That's 9
n = 10*9 + 8; // That's 98
n = 10*98 + 7; // That's 987
答案 2 :(得分:1)
至少可以这么写。
0)使用格式化!:
int f(char* p)
{
int n = 0;
while (*p != 0)
n = 10*n + *p++ - ‘0?;
return n;
}
1)?
语法无效。它应该是一个'
,如chris所述(你现有的‘
也是错误的,但这可能是因为你从网站而不是源文件中复制了它),给出了:
int f(char* p)
{
int n = 0;
while (*p != 0)
n = 10 * n + *p++ - '0';
return n;
}
2)参数类型不应该像它应该的那样。因为*p
永远不会被修改(根据我们的目标),我们应该强制执行以确保我们不犯任何错误:
int f(const char* p)
{
int n = 0;
while (*p != 0)
n = 10 * n + *p++ - '0';
return n;
}
3)原始程序员显然对可读代码过敏。让我们分开我们的行动:
int f(const char* p)
{
int n = 0;
for (; *p != 0; ++p)
{
const int digit = *p - '0';
n = 10 * n + digit;
}
return n;
}
4)现在操作更加明显,我们可以看到这个函数中嵌入了一些独立的功能;这应该被分解出来(这称为反应)到一个单独的函数中。
即,我们看到converting a character to a digit:
的操作int todigit(const char c)
{
// this works because the literals '0', '1', '2', etc. are
// all guaranteed to be in order. Ergo '0' - '0' will be 0,
// '1' - '0' will be 1, '2' - '0' will be 2, and so on.
return c - '0';
}
int f(const char* p)
{
int n = 0;
for (; *p != 0; ++p)
n = 10 * n + todigit(*p);
return n;
}
5)现在很明显,该函数逐个字符地读取字符串,并逐位生成一个数字。此功能已exists under the name atoi
, and this function is an unsafe implementation:
int todigit(const char c)
{
// this works because the literals '0', '1', '2', etc. are
// all guaranteed to be in order. Ergo '0' - '0' will be 0,
// '1' - '0' will be 1, '2' - '0' will be 2, and so on.
return c - '0';
}
int atoi_unsafe(const char* p)
{
int n = 0;
for (; *p != 0; ++p)
n = 10 * n + todigit(*p);
return n;
}
它作为练习留给读取检查溢出,无效字符(那些不是数字),等等。但是这应该让正在发生的事情变得更加清晰,并且首先应该如何编写这样的函数。
答案 3 :(得分:1)
这是一个字符串到数字转换功能。与atoi类似。
字符串是一系列字符。所以内存中的“123”将是: '1', '2', '3',NULL
p指向它。
现在,根据ASCII,digits are encoded from '0' to '9'。 '0'被赋值48,'9'被赋值57.因此,'1','2','3',内存中的NULL实际上是:49,50,51,0
如果要将字符“0”转换为整数0,则必须从内存中的值中减去48。你知道这是怎么回事吗?
现在,不是减去数字48,而是减去'0',这使得代码更容易阅读。