6-5 错误的十进制整数 - 《C++编程基础及应用》- 习题21-1

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编程基础及应用》(高等教育出版社)配套在线课程

《C++编程基础及应用》(高等教育出版社)配套在线课程

《Python编程基础及应用》教材习题讲解

《C++编程基础及应用》教材习题讲解

代码长度限制

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;
}
  1. 初始化
    • int num = 0;:初始化一个整数 num 用于存储转换后的结果。
  2. 检查符号
    • if (s[0] == '+' || s[0] == '-'):判断字符串 s 的第一个字符是否为 '+' 或 '-'。
  3. 处理带符号的字符串
    • 如果第一个字符是 '+' 或 '-',则进入这个分支。
    • 从第二个字符(索引为 1)开始,通过循环将每个字符转换为数字并累加到 num 中。这里使用的是简单的基数 10 转换算法。
    • 在循环结束后,如果第一个字符是 '-',则将 num 取反。
  4. 处理不带符号的字符串
    • 如果第一个字符不是 '+' 或 '-',则进入这个分支。
    • 从第一个字符开始,通过循环将每个字符转换为数字并累加到 num 中。
  5. 非法字符检查
    • 在转换完成后,代码尝试检查字符串中是否包含非法字符。但是,这个检查是在已经进行了转换之后进行的,这可能导致问题。
    • 循环从第二个字符(索引为 1)开始,检查每个字符是否为数字。如果不是,则抛出一个异常。但是,这里的问题是,如果字符串以 '+' 或 '-' 开头,并且后面跟有非法字符,那么异常将在转换之后被抛出,而不是在转换之前。
  6. 返回结果
    • 返回转换后的整数 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 的末尾。

  • 37
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值