我构建了一个小程序,它将给定的char数组转换为整数:
#include <stdio.h>
int char_to_int(char* value);
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Illegal argument count!");
return 1;
}
printf("As char array: %s\n", argv[1]);
printf("As integer: %i", char_to_int(argv[1]));
return 0;
}
int char_to_int(char* value)
{
return *value - '0';
}
问题是,当我输入一个多数字数字时,整数只包含一个数字,这是合乎逻辑的,但我不知道如何重写代码。我也不知道为什么只有第一个字符被转换。
我知道这是非常基本的东西,但我想知道如何正确实现它。
我还想避免在STL中使用ato()函数。
使用错误处理重写代码:
#include <stdio.h>
int char_to_int(char* value);
int illegal_conversion = 0;
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Illegal argument count!");
return 1;
}
int result = char_to_int(argv[1]);
if (illegal_conversion)
{
printf("Illegal arguments");
return 1;
}
printf("As char array: %s\n", argv[1]);
printf("As integer: %i", result);
return 0;
}
int char_to_int(char* value)
{
int result = 0;
int negative_integer = 0;
while (*value)
{
if (*value == 43)
{
*value++;
continue;
}
else if (*value == 45)
{
*value++;
negative_integer = 1;
continue;
}
else if (*value < 48 || *value > 57)
{
illegal_conversion = 1;
return 1;
}
result *= 10;
result += *value++ - '0';
}
if (negative_integer)
result *= -1;
return result;
}
答案 0 :(得分:3)
因为您只返回第一个数字的数值。
此函数转换但没有任何检查,它仅适用于有效的非负十进制数,否则它是一个UB
int char_to_int(char* value)
{
int result = 0;
while(*value)
{
result *= 10;
result += *value++ - '0';
}
return result;
}
或更聪明一点:
int char_to_int(char* value, int *res)
{
int sign = 0;
int status = 0;
int result = 0;
if (value != NULL && res != NULL)
{
while (*value)
{
switch (*value)
{
case '+':
case '-':
if (sign) status = -1;
sign = *value == '-' ? -1 : 1;
break;
default:
if (!isdigit(*value)) status = -1;
if(!sign) sign = 1;
*result *= 10;
*result += *value - '0';
break;
}
value++;
if (status) break;
}
if(!status)*res = sign * result;
}
return status;
}
答案 1 :(得分:0)
在可以避免的情况下,重写代码会导致未定义的行为。
(2的补码)int
char buf[100];
sprintf(buf, "%d", INT_MIN); // e.g. -2147483648
int y = char_to_int(buf);
while
中的char_to_int()
循环最终会执行
// before
// result: 214748364
// *value: '8'
result += *value++ - '0';
// after
// `int` overflow, this is undefined behavior
为了避免,而不是将答案累积为正值,然后如果找到“ - ”则否定否定,将答案累积为负值,然后如果未找到“ - ”则否定。这不太直观,但避免了UB。
使用unsigned
作为扩展范围是另一种方式,但在INT_MAX == UINT_MAX
的稀有机器上失败。我只遇到过一次这样的机器而且它的最大整数。
评论中提到的其他改进。
#include <ctype.h>
int char_to_int(const char *value) { // use const
int sign = *value;
if (sign == '-' || sign == '+') {
value++;
}
bool digit_found = false;
int result = 0;
// while (isdigit(*value)) { // avoid this as it is UB when *value < 0, not EOF
while (isdigit((unsigned char) *value)) { // or (*value >= '0' && *value <= '9')
result *= 10;
result -= *value - '0'; // notice the `-=`
value++;
digit_found = true;
}
if (sign != '-') {
result = -result;
}
// Error detection
if (*value != '\0' || !digit_found) {
; //Handle_Invalid_String();
}
return result;
}
注意:不包括溢出检测。