鱼C论坛

 找回密码
 立即注册
查看: 2603|回复: 5

[已解决]s1e29动动手0.疑问和题目没有太大关系,只是不明白哪里用了溢出

[复制链接]
发表于 2022-11-11 21:38:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
s1e29动动手0,题目如下:
      你应该听说过 itoa 函数(函数文档 -> 传送门),它的作用是将一个整数转换成字符串形式存储。现在要求我们自己来实现一个类似功能的函数 myitoa(int num, char *str),该函数的第一个参数是待转换的整型变量,第二参数传入一个字符指针,用于存放转换后的字符串。
给出主程序段:
……
int main(void)
{
        char str[10];

        printf("%s\n", myitoa(520, str));
        printf("%s\n", myitoa(-1234, str));

        return 0;
}
要求的结果:
165251rn3c3dcp5pec6nyp.png
我的代码:
#include<stdio.h>

char *myitoa(int a,char *array)
{

        int i=0,j,flag=0,m; //结果位数i计算
        char ch_array[10]; //中间数组。

        
        if(a<<0)  //判断正负值。如果是负数,将符号‘-’存入数组array第一个位置
        {
                array[0]='-';
                i++;
                a=-a;
                
        }
        m=0;
        if(a>=10)    //每次除10,提取余数存入中间数组ch_array
        {
                ch_array[m]=a%10;
                m++;        
        }

        for(j=m;j<0;j--)  //数组存储值反转存储到指定的数组里
        {
                array[i]=ch_array[j];
                i++;
        }

}

int main(void)
{
        char str[10];
        
        printf("%s\n",myitoa(520,str));
        printf("%s\n",myitoa(-1234,str));

        return 0;
}
悲惨的运行结果:
屏幕截图 2022-11-11 212723.jpg

仔细分析了代码的各个部分,实在搞不明白哪里出了问题,造成这个“段错误(核心已转存)”。上网查找段错误的原因,是指发生了越界,也就是访问了不应该访问的内存,这个内存要么不存在,要么不允许使用。还有一个可能文件损坏。
那么首先,我尝试编译了好多遍了,应该排除文件损坏的原因。整个代码没有指定内存位置,应该不会被这么多次调用到不允许访问的内存,那么就是越界了。整个代码过程,根据题目要求定义了一个10元素的数组,我又定义了一个10元素组成的中间数组char ch_array[10].外加使用了4个整形变量,都是用了几个数字,根据题目,数组最大用到5个元素,那么变量值最大用到4也就结束了,不可能超出范围呀。还求哪位有耐心帮忙找找这个“段错误”错在了哪里。谢谢。
最佳答案
2022-11-12 08:36:22
先说编码问题,其实您的编译器本应该协助您解决这些问题的。看看我使用的编译器是怎么评价您的代码的:
test.c:10:13: warning: converting the result of '<<' to a boolean; did you mean '(a << 0) != 0'? [-Wint-in-bool-context]
        if(a<<0)  //判断正负值。如果是负数,将符号‘-’存入数组array第一个位置
            ^
test.c:6:19: warning: unused variable 'flag' [-Wunused-variable]
        int i=0,j,flag=0,m; //结果位数i计算
                  ^
test.c:30:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
3 warnings generated.
理解和解决了这些问题,就理解和解决了您目前出现的段错误。
当然,您的代码除此之外还有逻辑上的问题,还需要后续的修改才能得到正确的结果,您可以先尝试,遇到无法解决的问题欢迎继续提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-11-11 22:27:08 | 显示全部楼层
jackz007 发表于 2022-11-11 22:05
下面是我修改的版本

谢谢Jack。上次就看出来您的for循环使用的炉火纯青,在下佩服。根据你的提示,我修改了判断正负的if语句(第10行),修改了取尾数语句(第18行),在第21行插入了a=a/10;语句。虽然不明白你的第13行,计算出10进制尾数后,存入的时候要与0相加,也按照您的方式进行了修改。试运行结果还是同样的结果,编译通过,运行时出现“段错误”提示,不能出现正确结果。

我想要的不只是一个正确的答案,想要的是解决我现在遇到的问题。十分感谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-12 08:36:22 | 显示全部楼层    本楼为最佳答案   
先说编码问题,其实您的编译器本应该协助您解决这些问题的。看看我使用的编译器是怎么评价您的代码的:
test.c:10:13: warning: converting the result of '<<' to a boolean; did you mean '(a << 0) != 0'? [-Wint-in-bool-context]
        if(a<<0)  //判断正负值。如果是负数,将符号‘-’存入数组array第一个位置
            ^
test.c:6:19: warning: unused variable 'flag' [-Wunused-variable]
        int i=0,j,flag=0,m; //结果位数i计算
                  ^
test.c:30:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
3 warnings generated.
理解和解决了这些问题,就理解和解决了您目前出现的段错误。
当然,您的代码除此之外还有逻辑上的问题,还需要后续的修改才能得到正确的结果,您可以先尝试,遇到无法解决的问题欢迎继续提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-13 19:28:04 | 显示全部楼层
dolly_yos2 发表于 2022-11-12 08:36
先说编码问题,其实您的编译器本应该协助您解决这些问题的。看看我使用的编译器是怎么评价您的代码的:
理 ...

谢谢您的答复,根据你的编译器提示,我找到了溢出的位置,也对逻辑进行了修正,已经完成了题目。好奇问一下,您用的是什么编译器,可以告诉我么?你这个编译器的提示太丰富了,我能够使用不?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-14 10:11:20 | 显示全部楼层
顶级太阳 发表于 2022-11-13 19:28
谢谢您的答复,根据你的编译器提示,我找到了溢出的位置,也对逻辑进行了修正,已经完成了题目。好奇问一 ...

得到之前回复里的输出的编译器和版本是
clang version 14.0.6
当然, gcc 也可以得到类似的结果(这里我改了一下源代码文件名):
test2.c: In function ‘myitoa’:
test2.c:10:13: warning: ‘<<’ in boolean context, did you mean ‘<’? [-Wint-in-bool-context]
   10 |         if(a<<0)  //判断正负值。如果是负数,将符号‘-’存入数组array第一个位置
      |            ~^~~
test2.c:6:19: warning: unused variable ‘flag’ [-Wunused-variable]
    6 |         int i=0,j,flag=0,m; //结果位数i计算
      |                   ^~~~
test2.c:30:1: warning: control reaches end of non-void function [-Wreturn-type]
   30 | }
      | ^
版本是
gcc (GCC) 12.2.0
您可以试着给您的编译命令加上额外的调试选项,我一般常用的是(在此处使用的也是) -Wall -Wextra -fsanitize=address ,即改为
gcc -Wall -Wextra -fsanitize=address test.c
相关选项的含义可以在这里查找对应您使用的版本的文档: https://gcc.gnu.org/onlinedocs/
如最新版的选项总结在这里: https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Option-Summary.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-14 11:40:11 | 显示全部楼层
dolly_yos2 发表于 2022-11-14 10:11
得到之前回复里的输出的编译器和版本是
当然, gcc 也可以得到类似的结果(这里我改了一下源代码文件名 ...

十分感谢。刚刚自己开始学习,完全靠摸索,很多东西还都不懂。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-20 17:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表