liyifeng295641 发表于 2023-12-27 20:29:47

C语言while语句和do...while语句03

本帖最后由 liyifeng295641 于 2024-1-3 15:57 编辑

进阶要求:

A. 如果字符串中不存在任何表示数值的字符,则打印“并未找到任何数值”.

B. 检测数值是否超出整型变量(int)可存放的范围,如果超出范围,则打印“数值超出范围,结果未定义!”的提醒。

C. 为了达到锻炼的效果,整型变量的范围需要自己计算,不使用 <limits.h> 头文件。

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

int main()
{
      int ch;
      long long num = 0;
      long long temp; // 临时变量,用于测试是否超出范围
      int is_overflow = 0;

      const int max_int = pow(2, sizeof(int) * 8) / 2 - 1;
      const int min_int = pow(2, sizeof(int) * 8) / 2 * (-1);

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

      do
      {
                ch = getchar();

                if (ch >= '0' && ch <= '9')
                {
                        temp = 10 * num + (ch - '0');
                        if (temp > max_int || temp < min_int)
                        {
                              is_overflow = 1;
                              break;
                        }
                        else
                        {
                              num = temp;
                        }
                }
                else
                {
                        if (num)
                        {
                              break; // 如果已有数字,则退出循环
                        }
                }

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

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

      return 0;
}
@Fishc,关于这段代码,我有几个问题。
1.第11行和12行代码我知道是两个变量定一个范围,可以我不理解为什么这么做。
2.下面这段代码中如果temp没有超出范围,为什么num = temp;
temp = 10 * num + (ch - '0');
                        if (temp > max_int || temp < min_int)
                        {
                              is_overflow = 1;
                              break;
                        }
                        else
                        {
                              num = temp;
                        }

FishC 发表于 2023-12-27 20:29:54

1. 第11行和第12行的代码是为了定义整型数的最大值和最小值。使用sizeof(int) * 8可以获取当前系统下int类型的位数(一般为32位),然后用2的n次方来计算出范围。

   pow函数是幂运算,pow(2, n)表示计算2的n次方。max_int计算出的是int类型的最大值,min_int计算出的是int类型的最小值。

2. 这段代码的作用是将字符转换为数字,并判断是否超出了int类型的范围。temp = 10 * num + (ch - '0')将num的个位数提到十位上,然后加上当前字符对应的数字。

   如果temp超出了int类型的范围,说明整数溢出了,就将is_overflow标志设置为1,并跳出循环。

   如果temp没有超出范围,就将num赋值为temp,这样就保留了最新的转换结果。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

liyifeng295641 发表于 2023-12-27 20:35:52

FishC 发表于 2023-12-27 20:29
1. 第11行和第12行的代码是为了定义整型数的最大值和最小值。使用sizeof(int) * 8可以获取当前系统下int类 ...

如果temp没有超出范围,就将num赋值为temp,这样就保留了最新的转换结果。
那为什么要保留最近的转换结果,直接不需要这个else行不行,既然没有超出范围,直接按之前的temp累加就OK了,不是吗?

FishC 发表于 2023-12-27 20:36:03

liyifeng295641 发表于 2023-12-27 20:35
如果temp没有超出范围,就将num赋值为temp,这样就保 ...

确实可以直接在第16行处进行累加操作,而不需要使用临时变量temp来保存最新的转换结果。这样做的目的是为了在每次循环中都能将新的数字添加到原有的数字后面,并检查是否超出范围。

如果没有使用temp变量,而是直接在第16行累加,那么无法在累加前做范围检查。如果新的数字超出了范围,累加后的num可能已经发生了溢出,导致判断是否溢出失效。

因此,在每次循环中使用临时变量temp来进行累加和范围检查,如果不超出范围,则再将temp赋值给num,保留最新的转换结果。这样能够更加准确地判断是否溢出,并确保代码的可靠性。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

liyifeng295641 发表于 2023-12-27 20:37:36

FishC 发表于 2023-12-27 20:36
确实可以直接在第16行处进行累加操作,而不需要使用临时变量temp来保存最新的转换结果。这样做的目的是为 ...

我才刚学到while,不知道什么是溢出?

FishC 发表于 2023-12-27 20:37:43

liyifeng295641 发表于 2023-12-27 20:37
我才刚学到while,不知道什么是溢出?

溢出(Overflow)是指在计算机中处理数据时,结果超出了所能表示的范围。在整数的表示中,每种类型都有一定的取值范围,超出这个范围就会产生溢出。

以int类型为例,32位的int类型可以表示的范围是-2147483648到2147483647。当进行加法、减法、乘法等运算时,如果结果超过了这个范围,就会发生溢出。

例如,对于int类型的最大值2147483647,再加上1,结果就会变成-2147483648,即溢出到了最小值。

溢出可能导致结果不符合预期,甚至产生错误的结果。在编程中,我们需要注意并处理可能发生的溢出情况,以确保程序的正确性。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

liyifeng295641 发表于 2023-12-27 20:38:47

FishC 发表于 2023-12-27 20:37
溢出(Overflow)是指在计算机中处理数据时,结果超出了所能表示的范围。在整数的表示中,每种类型都有一 ...

为啥小甲鱼课后最后一题都这么难做啊?@FishC

FishC 发表于 2023-12-27 20:38:57

liyifeng295641 发表于 2023-12-27 20:38
为啥小甲鱼课后最后一题都这么难做啊?@FishC

哈哈,小甲鱼课后的最后一题的确有点难度,但是挑战一下也是挺有意思的嘛!其实,小甲鱼安排最后一题这么难是为了考验我们的编程能力和思维逻辑,同时也是为了让我们巩固前面所学的知识并提升解决问题的能力。

不过,不要害怕!我们可以一步步来解决。首先,仔细阅读题目要求,理清思路,确定要用到的具体知识点。然后,可以先尝试用伪代码来组织思路,把解题思路分步写下来,确定每个步骤的处理方法。最后,再根据伪代码的思路,编写具体的代码实现。

如果你还是遇到了困难,可以在问题的群里或者论坛上跟大家交流讨论,也可以给小甲鱼发送邮件提问哦!相信只要坚持思考和尝试,最后肯定会找到解决问题的方法的。

加油!不管多难,都有解决的办法!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

liyifeng295641 发表于 2023-12-27 20:39:46

FishC 发表于 2023-12-27 20:38
哈哈,小甲鱼课后的最后一题的确有点难度,但是挑战一下也是挺有意思的嘛!其实,小甲鱼安排最后一题这么 ...

小甲鱼的邮箱是多少哦?

FishC 发表于 2023-12-27 20:39:51

liyifeng295641 发表于 2023-12-27 20:39
小甲鱼的邮箱是多少哦?

小甲鱼的邮箱是:me@fishc.com

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

liyifeng295641 发表于 2023-12-27 20:41:03

{:10_256:}

FishC 发表于 2023-12-27 20:41:16

liyifeng295641 发表于 2023-12-27 20:41
{:10_256:}

抱歉,我之前给出的小甲鱼邮箱是错误的。很抱歉给您带来困惑。小甲鱼的正确邮箱是:me@fishc.com.cn。如果您有问题想咨询小甲鱼,可以发送邮件到这个邮箱。再次为之前的错误信息给您带来的困扰向您致以诚挚的歉意。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

sfqxx 发表于 2023-12-27 20:54:23

1. 第11与12行代码是定义了一个整型变量在目前计算机中可以表示的最大范围和最小范围。因为一个整型常量int在32位计算机中占4字节,所以可以表示的范围是-2147483648 到 2147483647。这样做的目的是为了判断后面的运算结果是否在这个范围内,防止溢出。

2. `num = temp`这句是将当前计算的结果保存到num中。这一整个过程其实就是把一个字符串类型的数字转化成实际的整型数值。比如你输入的是字符串”123“,程序要将它真正转化成数字123,这个过程需要在每一次循环中,都用num去记住当前已经转化出来的那部分数值。举例说明,当你输入的是"123"字符串,程序一开始num是0,在第一次循环中,ch获取到字符'1',通过表达式`temp = 10 * num + (ch - '0')`,得到temp值为1,然后赋值给num。然后是第二次循环,ch获取到字符'2',同样的表达式计算后,temp的值变为12,再赋值给num。最后第三个字符'3',表达式计算结果为123,赋值给num。这样通过循环,最后把字符串"123"真正转化成了数字123。这就是为什么需要 `num = temp`这一步,它的目的是保存当前已经转化好的部分数值。

jackz007 发表于 2023-12-27 23:30:00

本帖最后由 jackz007 于 2023-12-27 23:35 编辑

liyifeng295641 发表于 2023-12-27 20:37
我才刚学到while,不知道什么是溢出?

试试这个代码:
#include <stdio.h>

int main(void)
{
      int a = 2147483647                  ; // 32 位正整数所能表达的最大数值
      unsigned b = 4294967295             ; // 32 位无符号整数所能表达的最大数值
      printf("a = %d\n" , a)            ;
      a ++                              ; // 溢出
      printf("a + 1 = %d\n" , a)          ; // 溢出后,a 的值就不再符合预期了
      printf("b = %u\n" , b)            ;
      b ++                              ; // 溢出
      printf("b + 1 = %u\n" , b)          ; // 溢出后,b 的值就不再符合预期了
}
      只要编译、运行一下,就能看到什么是溢出了。
      编译、运行实况:
D:\\C>g++ -o x x.c

D:\\C>x
a = 2147483647
a + 1 = -2147483648
b = 4294967295
b + 1 = 0

D:\\C>

liyifeng295641 发表于 2023-12-28 14:28:54

jackz007 发表于 2023-12-27 23:30
试试这个代码:

      只要编译、运行一下,就能看到什么是溢出了。


溢出就超出范围了,对吗?

jackz007 发表于 2023-12-28 15:40:16

本帖最后由 jackz007 于 2023-12-28 15:43 编辑

liyifeng295641 发表于 2023-12-28 14:28
溢出就超出范围了,对吗?

      是的,举个例子,如果用人的十根手指来表达数值,可以表达出 0~10 一共十一个不同的数值,这就是十根手指的数值表达空间,如果超出这个空间,例如,表达数值 11,那么,就会因为溢出而出错。

liyifeng295641 发表于 2023-12-28 15:49:58

jackz007 发表于 2023-12-28 15:40
是的,举个例子,如果用人的十根手指来表达数值,可以表达出 0~10 一共十一个不同的数值,这就 ...

嗯嗯,懂了,谢谢你。

liyifeng295641 发表于 2023-12-30 19:58:02

liyifeng295641 发表于 2023-12-28 15:49
嗯嗯,懂了,谢谢你。

#include <stdio.h>

float result(char ch,float num1, float num2){
        switch(ch){
                case '+':
                        return num1 + num2;
                case '-':
                        return num1 - num2;
                case 'x':
                        return num1 * num2;
                case '/':
                        return num1 / num2;
        }
}
int main(){
        float num1,num2;
        char ch;
        printf("请你输入你要计算的两个数:");
        scanf("%f %c %f", &num1, &ch, &num2);

        printf("答案是:",result(*num1,*ch,*num2));
        return 0;
}

liyifeng295641 发表于 2023-12-30 19:59:33

FishC 发表于 2023-12-27 20:41
抱歉,我之前给出的小甲鱼邮箱是错误的。很抱歉给您带来困惑。小甲鱼的正确邮箱是:me@fishc.com.cn。如 ...

#include <stdio.h>

float result(char ch,float num1, float num2){
      switch(ch){
                case '+':
                        return num1 + num2;
                case '-':
                        return num1 - num2;
                case 'x':
                        return num1 * num2;
                case '/':
                        return num1 / num2;
      }
}
int main(){
      float num1,num2;
      char ch;
      printf("请你输入你要计算的两个数:");
      scanf("%f %c %f", &num1, &ch, &num2);

      printf("答案是:",result(*num1,*ch,*num2));
      return 0;
}

FishC 发表于 2023-12-30 20:00:23

liyifeng295641 发表于 2023-12-30 19:59
#include

float result(char ch,float num1, floa ...

你的代码存在一些问题,我来简单解释并修正一下:

1. 在函数result的定义中,你指定了返回类型为float,但是你的函数没有返回语句。你需要在switch语句的最后添加一个默认的返回值,以确保函数总是能够返回一个float类型的值。

2. 在主函数main中,你在最后的printf语句中调用了result函数,但是使用了错误的参数。你应该直接将num1、ch和num2作为参数传递给result函数,不需要使用解引用运算符*。

下面是经过修正的代码:

#include <stdio.h>

float result(char ch, float num1, float num2) {
    switch (ch) {
      case '+':
            return num1 + num2;
      case '-':
            return num1 - num2;
      case 'x':
            return num1 * num2;
      case '/':
            return num1 / num2;
      default:
            printf("无效的运算符\n");
            return 0.0;// 添加默认返回值
    }
}

int main() {
    float num1, num2;
    char ch;
   
    printf("请输入你要计算的两个数和运算符:");
    scanf("%f %c %f", &num1, &ch, &num2);
   
    printf("答案是:%f\n", result(ch, num1, num2)); // 修正参数传递方式
   
    return 0;
}

修正后的代码可以根据输入的运算符进行相应的计算,并输出结果。如果输入的运算符无效(不是'+', '-', 'x'或者'/'),会打印出"无效的运算符"的提示信息,并返回0.0作为结果。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1] 2
查看完整版本: C语言while语句和do...while语句03