这个大数求模程序在VC中单步调试正常,但是运行起来会内存错,搞不懂

下面的程序是用来计算大数求模的,由于大数不能直接用变量储存,所以考虑用字符数组来储存。本来最原始的方法是用比较大的数一次一次减去小的数,最后得到余数,可是发现这样的话,如果较大的书比较小的数大很多,比如“437467856787967”对“5”取模,就会算很久,所以我改进了方法,每次从前面一个大数中取出最前面的几位,然后将它对后者求模,比如上面这个例子中,先取出“43”和“5”求模,得到“3”,然后把“3”和余下的部分连起来,继续这样算,就可以算的很快。

下面这个程序运行起来会出错,导致程序死,但是我单步调试却可以一步一步得到结果,并顺利结束退出,这是为什么呢?
还有一个问题就是,大家可以自己改一下main函数里的参与计算的数值,它有时候是可以算出结果,有时候就会出错,我很无解,还求各路C++高手看看。

相应的函数有注释:

C/C++ code
#include <iostream>
#include <math.h>
#include <string.h>
#include <time.h>

using namespace std;

char* sub(char *numa,char *numb);
char *findend(char *num);
int compare(char *numa,char*numb);
char *mod(char *numa,char *numb);
void reverse(char *s);
char *clearzero(char *num);

char *mod(char *numa,char *numb)  //求模函数
{
    int slong = strlen(numa),
        sshort = strlen(numb),
        contin,i = 0;
    int cp = compare(numa,numb);
    char *result = NULL,*temp = NULL,*mid = NULL,*latter =NULL;
    if(cp == 0)
        return numa;
    else if(cp == 2)
    {
        result = "0";
        return result;
    }
    else
    {
        if(slong - sshort <= 2)    //如果两个数相差位数不多,就可以用减法来算余数
        {
            temp = numa;
            sshort = strlen(numb);
        
            while(contin)
            {
                temp = sub(temp,numb);
                cp = compare(temp,numb);
                if(cp == 1)
                    contin = 1;
                else if(cp == 2)
                {
                    contin = 0;
                    result = "0";
                }
                else
                {
                    contin = 0;
                    result = temp;
                }
            }
        }
        else                       //如果相差太大,减法算会耗费很长时间,就用改进的方法计算
        {
            mid = new char[sshort+1+1];
            latter = new char[slong-sshort];    
            mid[sshort+1] = '\0';
            latter[slong-sshort-1] = '\0';

            for(i=0;i<sshort+1;i++)
            {
                mid[i] = numa[i];
            }
            for(i=0;i<slong-sshort-1;i++)
            {
                latter[i] = numa[sshort+1+i];
            }
            temp = strcat(mod(mid,numb),latter);
            clearzero(temp);
            delete mid;
            delete latter;
            result = mod(temp,numb);
        }
        return result;
    }
}


char *clearzero(char *num)         //清除无效的“0”,比如把“0091”处理成“91”
{
    int length = strlen(num);
    int i = length - 1;
    reverse(num);

    while(num[i] == 48)
    {
        num[i] = '\0';
        i--;
    }
    reverse(num);
    return num;
}

void reverse(char *s)    //颠倒字符串的顺序,因为有的函数是逆序储存字符串结果的,而求在clearzero函数中也要用。
{
        int i,j;
        char t;
        
        for(i=0,j=strlen(s)-1;i<j;i++,j--)
                t=s[i],s[i]=s[j],s[j]=t;
}

char* sub(char *numa,char *numb)//大数相减函数,现在目前没有实现处理负数出现的代码,因为在这个例子中不会出现小数减大数的情况
{
    char *temp;
    int carry = 0,loop;
    int slong,sshort;
    char *pl = NULL,*ps = NULL;

    if(compare(numa,numb) > 0)
    {
        pl = findend(numa);
        ps = findend(numb);
        slong  = strlen(numa);
        sshort = strlen(numb);
        loop = strlen(numa);
    }
    else
    {
        pl = findend(numb);
        ps = findend(numa);
        slong = strlen(numb);
        sshort = strlen(numa);
    }
    temp =  new char[slong+1];
    temp[loop]='\0';
    while(loop > 0)
    {
        if(loop > slong - sshort)
        {
            if(*pl > *ps)
            {
                temp[loop-1] = *pl - *ps + 48 - carry;
                carry = 0;
            }
            else if(*pl == *ps)
            {
                if(carry == 1)
                {
                    temp[loop-1] = *pl + 10 -*ps - carry + 48;
                    carry = 1;
                }
                else
                {
                    temp[loop-1]= 48;
                    carry = 0;
                }
            }
            else
            {
                temp[loop-1] = *pl + 10 -*ps - carry + 48;
                carry = 1;
            }
        }
        else
        {
            if(*pl == 48 && carry ==1)
            {
                temp[loop-1] = 57;
                carry = 1;
            }
            else
            {
                temp[loop-1] = *pl - carry;
                carry = 0;
            }
        }
        pl--;ps--;        
        loop--;
    }
    return clearzero(temp);
}

char *findend(char *num)   //用来返回num字符串的最后一个字符的位置
{
    num += strlen(num)-1;
    return num;
}

int compare(char *numa,char*numb)  //比较numa和numb的大小,如果numa>numb返回1,numa=numb返回2,numa<numb返回0
{
    int slong = strlen(numa);

    int sshort = strlen(numb);
    char *pna = numa;
    char *pnb = numb;

    if (slong > sshort) return 1;
    if (slong == sshort)
    {
        while (*pna)
        {
            if(*pna > *pnb) return 1;
            else if(*pna < *pnb) return 0;
            else if(*pna == *pnb)
            {
                pna++;
                pnb++;
            }
        }
        return 2;
    }
    return 0;
}

 int main ()  //主函数
 {
     char *a = "45321432432144321432154";
     char *b = "21322";
     char *result = a;
     result = mod(a,b);
     cout<<result<<endl;
     return 0;
 }

作者: lovejoyy   发布时间: 2011-06-13

The variable 'contin' is being used without being initialized

作者: nfer_cn   发布时间: 2011-06-13

多谢提醒,不过我把它初始化为1了还是不能正常工作,呵呵

作者: lovejoyy   发布时间: 2011-06-13

比如取:
C/C++ code
    
char *a = "45321432432132154";
char *b = "21322";


就可以算出结果11918

作者: lovejoyy   发布时间: 2011-06-13

引用 3 楼 lovejoyy 的回复:

比如取:
C/C++ code

char *a = "45321432432132154";
char *b = "21322";


就可以算出结果11918

确实DebugOK,但是运行却出错!

作者: nfer_cn   发布时间: 2011-06-13

引用 4 楼 nfer_cn 的回复:

引用 3 楼 lovejoyy 的回复:

比如取:
C/C++ code

char *a = "45321432432132154";
char *b = "21322";


就可以算出结果11918

确实DebugOK,但是运行却出错!


哎,困扰了我两天了,还是不能解决。。心都碎了

作者: lovejoyy   发布时间: 2011-06-13

引用 5 楼 lovejoyy 的回复:

引用 4 楼 nfer_cn 的回复:

引用 3 楼 lovejoyy 的回复:

比如取:
C/C++ code

char *a = "45321432432132154";
char *b = "21322";


就可以算出结果11918

确实DebugOK,但是运行却出错!


哎,困扰了我两天了,还是不能解决。。心都碎了

问题定位了,在sub函数中126行,第22次调用new时出现问题,不过还没想出解决办法!

作者: nfer_cn   发布时间: 2011-06-13

C/C++ code
else                       //如果相差太大,减法算会耗费很长时间,就用改进的方法计算
        {
            mid = new char[sshort+1+1];
            latter = new char[slong-sshort];
            char * temp2 = new char[slong];
            memset(temp2, 0x0, slong);
            mid[sshort+1] = '\0';
            latter[slong-sshort-1] = '\0';

            for(i=0;i<sshort+1;i++)
            {
                mid[i] = numa[i];
            }
            for(i=0;i<slong-sshort-1;i++)
            {
                latter[i] = numa[sshort+1+i];
            }
            //temp = strcat(mod(mid,numb),latter);
            temp = mod(mid, numb);
            memcpy(temp2,temp,strlen(temp));
            strcat(temp2,latter);
            clearzero(temp2);
            delete mid;
            delete latter;

            result = mod(temp2,numb);
            delete temp2;
        }

OK了,替换下你的54行的else,OK了
问题出在内存泄露上

作者: nfer_cn   发布时间: 2011-06-13

引用 6 楼 nfer_cn 的回复:

引用 5 楼 lovejoyy 的回复:

引用 4 楼 nfer_cn 的回复:

引用 3 楼 lovejoyy 的回复:

比如取:
C/C++ code

char *a = "45321432432132154";
char *b = "21322";


就可以算出结果11918

确实DebugOK,但是运行却出错!


哎,困扰了我两天了,还是……

对,我也发现了,那个temp字符串变成了“”,照理说应该不会是空的吧?或者是不是申请了要先memset一下?

作者: lovejoyy   发布时间: 2011-06-13

你原来的特姆坡一直是个野指针!
temp = strcat(mod(mid,numb),latter);
这一行的问题,我刚开始就觉得就不对劲!

作者: nfer_cn   发布时间: 2011-06-13

引用 9 楼 nfer_cn 的回复:

你原来的特姆坡一直是个野指针!
temp = strcat(mod(mid,numb),latter);
这一行的问题,我刚开始就觉得就不对劲!


诶?麻烦说详细点么,还没想通 呵呵

作者: lovejoyy   发布时间: 2011-06-13

给你一个经过检验多次的代码做参考吧:
大数的四则运算及求模

作者: pathuang68   发布时间: 2011-06-13

引用 10 楼 lovejoyy 的回复:

引用 9 楼 nfer_cn 的回复:

你原来的特姆坡一直是个野指针!
temp = strcat(mod(mid,numb),latter);
这一行的问题,我刚开始就觉得就不对劲!


诶?麻烦说详细点么,还没想通 呵呵

说实话,我也不是很清楚,不过感觉你应该清楚的一下几个地方:
1.strcat(mod(mid,numb),latter) mod(mid,numb)返回的指针指向的内存在哪里开辟的?
2.strcat函数中第一个指针是否能保存下两个字符串连接的长度
3.result = mod(temp,numb)同理,result指向的内存是谁管理的?请明确!
建议把mod函数重写下,其他的函数模块化还是很好的

作者: nfer_cn   发布时间: 2011-06-13

引用 12 楼 nfer_cn 的回复:

引用 10 楼 lovejoyy 的回复:

引用 9 楼 nfer_cn 的回复:

你原来的特姆坡一直是个野指针!
temp = strcat(mod(mid,numb),latter);
这一行的问题,我刚开始就觉得就不对劲!


诶?麻烦说详细点么,还没想通 呵呵

说实话,我也不是很清楚,不过感觉你应该清楚的一下几个地方:
1.strcat(mod(mid,nu……


恩,多谢指点!我取完善一下mod函数~

作者: lovejoyy   发布时间: 2011-06-13

引用 13 楼 lovejoyy 的回复:

引用 12 楼 nfer_cn 的回复:

引用 10 楼 lovejoyy 的回复:

引用 9 楼 nfer_cn 的回复:

你原来的特姆坡一直是个野指针!
temp = strcat(mod(mid,numb),latter);
这一行的问题,我刚开始就觉得就不对劲!


诶?麻烦说详细点么,还没想通 呵呵

说实话,我也不是很清楚,不过感觉你应该清楚的一下几个……

互相进步!
个人一点意见:
1、学会使用项目管理工具,如:GIT,SVN之类的
2、一定要养成良好的编程规范
3、多学习开源代码

作者: nfer_cn   发布时间: 2011-06-13

引用 14 楼 nfer_cn 的回复:

引用 13 楼 lovejoyy 的回复:

引用 12 楼 nfer_cn 的回复:

引用 10 楼 lovejoyy 的回复:

引用 9 楼 nfer_cn 的回复:

你原来的特姆坡一直是个野指针!
temp = strcat(mod(mid,numb),latter);
这一行的问题,我刚开始就觉得就不对劲!


诶?麻烦说详细点么,还没想通 呵呵

说……


呵呵 多谢前辈如此耐心!在VC下面的确不太熟练,以后要抓紧!

作者: lovejoyy   发布时间: 2011-06-13