6-5 错误的十进制整数 - 《C++编程基础及应用》- 习题21-1
分数 15
作者 海洋饼干叔叔
单位 重庆大学
函数toInteger()负责把一个字符串,比如“-719”转换成整数。当函数发现字符串不符合十进制整数的格式要求,比如包含了非数字母,则应放弃转换并抛出一个异常。请实现该函数,使得下述代码能正常运行:当输入为一个合法整数时,转换并打印该整数;当输入为不合法整数时,打印错误信息。
错误信息应为:
illegal integral format
函数接口定义:
int toInteger(const string& s);
输入样例:
+123
输出样例:
123
错误的整数格式举例:
-+123
1+123
--123
1-123-1
请注意:函数题只需要提交相关代码片段,不要提交完整程序。
感觉不会? 那试着听听免费的B站网课
《Python编程基础及应用》(高等教育出版社)配套在线课程
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
int toInteger(const string& s){
int num=0;
if(s[0]=='+'||s[0]=='-'){
for(int j=1;s[j]!='\0';j++){
num=(s[j]-'0')+num*10;
}
if(s[0]=='-'){
num=-num;
}
}else{
for(int j=0;s[j]!='\0';j++){
num=(s[j]-'0')+num*10;
}
}
for(int i=1;s[i]!='\0';i++){
if(!isdigit(s[i])){
throw "illegal integral format";
}
}
return num;
}
- 初始化:
int num = 0;
:初始化一个整数num
用于存储转换后的结果。
- 检查符号:
if (s[0] == '+' || s[0] == '-')
:判断字符串s
的第一个字符是否为 '+' 或 '-'。
- 处理带符号的字符串:
- 如果第一个字符是 '+' 或 '-',则进入这个分支。
- 从第二个字符(索引为 1)开始,通过循环将每个字符转换为数字并累加到
num
中。这里使用的是简单的基数 10 转换算法。 - 在循环结束后,如果第一个字符是 '-',则将
num
取反。
- 处理不带符号的字符串:
- 如果第一个字符不是 '+' 或 '-',则进入这个分支。
- 从第一个字符开始,通过循环将每个字符转换为数字并累加到
num
中。
- 非法字符检查:
- 在转换完成后,代码尝试检查字符串中是否包含非法字符。但是,这个检查是在已经进行了转换之后进行的,这可能导致问题。
- 循环从第二个字符(索引为 1)开始,检查每个字符是否为数字。如果不是,则抛出一个异常。但是,这里的问题是,如果字符串以 '+' 或 '-' 开头,并且后面跟有非法字符,那么异常将在转换之后被抛出,而不是在转换之前。
- 返回结果:
- 返回转换后的整数
num
。
- 返回转换后的整数
问题所在:
因此,if (!isdigit(s[i]))
的意思是:“如果 s[i]
不是一个数字字符,则执行接下来的代码块”。这通常用于检查字符串中是否包含非数字字符。
这个循环会持续进行,直到字符串 s
的末尾,从而将整个字符串转换为整数。需要注意的是,如果字符串中包含非数字字符或负数符号(-
),你需要在循环之前或之后进行适当的处理。
- 非法字符检查应该在转换之前进行,以确保字符串只包含有效的数字字符和可能的符号。
- 如果字符串以 '+' 开头,但后面包含非法字符,则转换将成功执行(因为
+
被忽略了),但随后会抛出异常。这可能导致部分非法的输入被错误地转换为整数。 -
在原始的代码示例中,非法字符检查确实是在已经进行了部分或全部转换之后才进行的,这可能导致以下问题:
-
错误的处理:如果字符串中包含非法字符(例如字母、标点符号等),并且这些字符位于数字序列之后,那么异常将在已经完成了对前面数字序列的转换之后才会被抛出。这意味着程序可能会错误地尝试处理一个不完整的或非法格式的输入字符串,并生成一个不准确或不可预测的结果。
-
误导性的异常信息:由于异常是在转换之后抛出的,异常消息可能无法准确地反映问题的本质。例如,异常可能会表明“illegal integral format”,但实际上可能只是因为在数字序列之后出现了非法字符。
-
性能问题:虽然在这个特定的例子中性能问题可能不太明显,但在更大的系统中,执行不必要的转换操作(在发现非法字符之后)可能会浪费计算资源。
-
代码逻辑不清晰:将非法字符检查放在转换之后可能会导致代码逻辑变得不清晰和难以维护。理想情况下,验证和转换应该作为两个独立的步骤进行,以确保输入的有效性,并在无效输入的情况下提供明确的反馈。
-
if (!isdigit(s[i]))
是一个条件判断语句,用于检查字符串s
中索引为i
的字符是否不是一个数字字符。 -
这里是它的详细解释:
-
s[i]
:这表示字符串s
中索引为i
的字符。在 C++ 中,字符串是通过字符数组或std::string
类来表示的,你可以通过索引来访问字符串中的字符,就像访问数组的元素一样。 -
isdigit()
:这是一个 C/C++ 标准库函数,定义在<cctype>
或<ctype.h>
头文件中。它用于检查一个字符是否是数字字符(即 '0' 到 '9')。 -
!
:这是一个逻辑非运算符。它将isdigit(s[i])
的结果反转。如果s[i]
是一个数字字符,isdigit(s[i])
会返回非零值(通常是 1),但!
运算符会将其转换为 0(即false
)。如果s[i]
不是一个数字字符,isdigit(s[i])
会返回 0,但!
运算符会将其转换为非零值(即true
)。 -
num=(s[j]-'0')+num*10;
是 C++ 或 C 语言中常见的将字符数组(字符串)中的数字字符转换为整数的一个步骤。这行代码通常出现在将字符串转换为整数的函数中。 -
具体解释如下:
-
s[j]
:这是从字符串s
中取出索引为j
的字符。假设这个字符是一个数字字符,比如'3'
。 -
'0'
:在 ASCII 编码中,字符'0'
到'9'
是连续的。'0'
的 ASCII 值是 48,'1'
是 49,依此类推,'9'
是 57。 -
s[j]-'0'
:通过从s[j]
的 ASCII 值中减去'0'
的 ASCII 值(即 48),你可以得到该字符所代表的整数值。例如,如果s[j]
是'3'
,那么s[j]-'0'
就是51-48
,结果为3
。 -
num*10
:这是将当前累积的整数num
乘以 10,以便为下一个数字字符腾出位置。例如,如果你已经解析了字符串的前两个字符'1'
和'2'
,那么num
的当前值应该是12
。当你要处理下一个字符(比如'3'
)时,你需要将num
乘以 10,得到120
,以便添加下一个数字3
,从而得到123
。 -
num=(s[j]-'0')+num*10;
:将上述两步的结果相加,即将新解析的数字字符添加到num
的末尾。