纪叶 发表于 2023-11-17 11:54:43

要求是实现atoi函数的类似功能,求助帮忙看看bug

题目要求:
C 语言中有个 atoi 函数,用于将字符串中的值解析为对应的整型数字。现在要求我们自己写一个程序,实现类似的功能。
A. 将用户输入的字符串中代表数字的字符转换为整型数值e;
B. 打印转换结果
C. 只打印第一组数字

D. 如果字符串中不存在任何表示数值的字符,则打印“并未找到任何数值”.
E.检测数值是否超出整型变量(int)可存放的范围,如果超出范围,则打印“数值超出范围,结果未定义!”的提醒。
F.为了达到锻炼的效果,整型变量的范围需要自己计算,不使用 <limits.h> 头文件。

我的代码如下:
#include <stdio.h>
#include <math.h>

int main()
{
        char ch;
        long long num = 0;    //最终结果
        long long temp;      //判断是否超出范围
        int is_overflow = 0;    //记录是否超出范围
       
        const int max_int = pow(2, sizeof(int)* 8) / 2 - 1;    //int的最大值
        const int min_int = pow(2, sizeof(int)* 8) / 2 * (-1); //int 的最小值
       
        printf("请输入待转换的字符串:");
       
        do
        {
                ch = getchar();
               
                if(ch >= '0' && ch <='9')
                {
                        temp = num *10 +(ch - '0');
                       
                        if(temp > max_int || temp < min_int)
                        {
                                is_overflow = 1;
                                break;
                        }
                        else
                        {
                                num = temp;
                        }
                }
                else if(num != 0)
                        {
                                break;             //只打印第一组数字
                        }                  
        }
       
        while((ch = getchar()) != '\n');

       
        if(is_overflow == 1)
        {
                printf("数值超出范围,结果未定义!\n");
        }
        else if(num != 0)
        {
                printf("结果是 %d",num);
        }
        else printf("并未找到任务数值!\n");
       
        return 0;
}


运行出来得不到全部数字 帮我看看哪里有问题吧谢谢大佬【玫瑰】【玫瑰】

isdkz 发表于 2023-11-17 11:55:00

您的代码有一个小问题。在每次循环中,您读取了一个字符并检查它是否是数字。如果是数字,您将其转换为整数并检查是否超出 int 类型的范围。如果没有超出范围,您将其添加到num中。但是,当您遇到非数字字符时,您立即退出了循环,这意味着您只会处理字符串中的第一个数字。

要解决这个问题,您需要修改循环逻辑,以便能够处理整个字符串而不仅仅是第一个数字。另外,您需要在程序中添加一些逻辑来处理字符串中不存在任何表示数值的字符的情况。

以下是修改后的代码:

#include <stdio.h>
#include <math.h>

int main()
{
    char ch;
    long long num = 0;    // 最终结果
    long long temp;       // 用于判断是否超出范围
    int is_overflow = 0;// 记录是否超出范围
    int has_digit = 0;    // 记录是否找到数字

    const int max_int = pow(2, sizeof(int) * 8) / 2 - 1;    // int 的最大值
    const int min_int = pow(2, sizeof(int) * 8) / 2 * (-1); // int 的最小值

    printf("请输入待转换的字符串:");

    while ((ch = getchar()) != '\n')
    {
      if (ch >= '0' && ch <= '9')
      {
            temp = num * 10 + (ch - '0');

            if (temp > max_int || temp < min_int)
            {
                is_overflow = 1;
                break;
            }
            else
            {
                num = temp;
                has_digit = 1; // 标记找到数字
            }
      }
      else if (has_digit)
      {
            break; // 已经找到数字,遇到非数字字符则退出循环
      }
    }

    if (is_overflow == 1)
    {
      printf("数值超出范围,结果未定义!\n");
    }
    else if (has_digit)
    {
      printf("结果是 %lld\n", num);
    }
    else
    {
      printf("并未找到任何数值!\n");
    }

    return 0;
}


这个修改后的代码会一直读取输入的字符,直到遇到换行符为止。它会处理整个字符串,并根据题目要求进行相应的处理。

Mike_python小 发表于 2023-11-17 11:56:43

你的代码有几个问题需要修复:

1. 在 do-while 循环内部,你使用 getchar() 获取下一个字符。然而,你在循环条件中也使用了 getchar()。这会导致在判断循环条件之前多读取了一个字符,可能会导致跳过部分数字。

2. 在打印结果时,你使用了 %d 格式字符串来打印 num,但是 num 是一个 long long 类型的变量,应该使用 %lld 格式字符串。

3. 你的代码尚未实现只打印第一组数字的要求。你需要在找到第一个数字后,终止循环以避免继续读取后续数字。

4. 在计算整型变量范围时,你使用了 pow(2, sizeof(int)* 8) / 2 - 1 和 pow(2, sizeof(int)* 8) / 2 * (-1),但是这种方法可能会引入浮点数误差。可以使用移位运算和按位取反来计算最大值和最小值。

基于以上问题,我给你提供一个修改后的代码:


#include <stdio.h>

int main()
{
    char ch;
    long long num = 0;      // 最终结果
    long long temp;         // 判断是否超出范围
    int is_overflow = 0;    // 记录是否超出范围

    const int max_int = (1 << (sizeof(int) * 8 - 1)) - 1;      // int的最大值
    const int min_int = -(1 << (sizeof(int) * 8 - 1));         // int 的最小值

    printf("请输入待转换的字符串:");

    do
    {
      ch = getchar();

      if (ch >= '0' && ch <= '9')
      {
            temp = num * 10 + (ch - '0');

            if (temp > max_int || temp < min_int)
            {
                is_overflow = 1;
                break;
            }
            else
            {
                num = temp;
            }
      }
      else if (num != 0)
      {
            break;      // 只打印第一组数字
      }

    } while (ch != '\n');

    if (is_overflow == 1)
    {
      printf("数值超出范围,结果未定义!\n");
    }
    else if (num != 0)
    {
      printf("结果是 %lld\n", num);
    }
    else
    {
      printf("并未找到任何数值!\n");
    }

    return 0;
}


这个修改后的代码考虑了你提到的问题,并进行了如下改动:

1. 修改了循环条件,将 getchar() 移至循环体内部,以避免多读取一个字符。

2. 使用 %lld 格式字符串来打印 long long 类型的变量。

3. 添加了终止循环的条件,使得在找到第一个数字后就可以终止循环。

4. 使用移位运算和按位取反来计算整型变量的最大值和最小值,避免了浮点数误差。

希望这些修改能够修复你的问题。如果还有其他疑问,请随时提问。

纪叶 发表于 2023-11-17 12:18:18

Mike_python小 发表于 2023-11-17 11:56
你的代码有几个问题需要修复:

1. 在 do-while 循环内部,你使用 getchar() 获取下一个字符。然而,你在循 ...

谢谢大佬的回复,我还有几个地方不太懂:

1.计算整型变量范围用pow这个方法可能引入浮点数误差是因为‘/’ 引入了浮点数吗
我记得计算机处理浮点数是有误差的

2. 用移位运算和按位取反来计算最大值和最小值的这个操作不是很懂,
原本是   00000001
然后左移01111110吗?
嗯好吧我完全不懂(挠头

纪叶 发表于 2023-11-17 13:07:43

isdkz 发表于 2023-11-17 11:55
您的代码有一个小问题。在每次循环中,您读取了一个字符并检查它是否是数字。如果是数字,您将其转换为整数 ...

噢噢明白了谢谢大佬!【玫瑰】【玫瑰】

我有个小疑问就是:用pow求int范围不会引入浮点数导致误差吗?还是说这个问题不大?
页: [1]
查看完整版本: 要求是实现atoi函数的类似功能,求助帮忙看看bug