鱼C论坛

 找回密码
 立即注册
查看: 725|回复: 2

[已解决]数据结构

[复制链接]
发表于 2020-12-7 10:44:54 | 显示全部楼层 |阅读模式

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

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

x
[问题描述]设计一个程序实现两个任意 长的整数的求和运算

[输入形式]按中国对于长整数的表示习惯,每四位一一组, 组间用逗号隔开

[输出形式]每四位一组,组间用逗号隔开

【评分标准】任何整形变量的范围是:-(215-1)~(215-1)。采用恰当的存储结构,如:利用双向循环链表实现长整数的存储,每个结点中仅存十进制数的4位,即不超过9999的非负整数,整个链表视为万位制数。可以利用头结点数据域的符号代表长整数的符号,用其绝对值表示元素结点数目。相加过程中不要破坏两个操作数链表。两操作数的头指针存于指针数组中是简化程序结构的一种方法。不能给长整数的位数规定上限。

【选作内容】修改上述程序,使它在整形量范围是-(2n-1)~(2n-1)的计算机上都能有效地运行。其中,n是由程序读入的参量。
最佳答案
2020-12-7 14:44:37
本帖最后由 xieglt 于 2020-12-7 14:53 编辑

后面才看到要考虑符号。又改了下,一个有符号的版本
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BASE                (10000)
#define        NUM_LEN                (4)
#define        _BASE_SIZE        (1024)
#define ISINIT(p)        ((p->_data != 0) && (p->_flag == 0))

typedef struct tagInteger
{
        int * _data;
        int _size;
        int _len;
        int _signed;
        int _flag;
}INTEGER,*LPINTEGER;

int _InitInteger(LPINTEGER n,int size = 0)
{
        size = ((size == 0) ? _BASE_SIZE : size);
        
        n->_size = 0;
        n->_data = (int *)malloc(size * sizeof(int));
        
        if(n->_data == 0)
        {
                return 0;
        }

        memset(n->_data,0,size * sizeof(int));
        n->_len = 0;
        n->_size = size;
        n->_flag = 0;
        return 1;
}

void _UninitInteger(LPINTEGER n)
{
        if(ISINIT(n))
        {
                free(n->_data);
        }
}

int _ResizeInteger(LPINTEGER n,int _size = 0)
{
        int len = n->_size;
        
        if(!ISINIT(n))
        {
                return _InitInteger(n,_size);
        }
                
        if(_size < _BASE_SIZE)
        {
                n->_size += _BASE_SIZE;
        }
        else
        {
                n->_size += _size;
        }
                
        n->_data = (int *)realloc(n->_data,n->_size * sizeof(int));
                
        if(n->_data == 0)
        {
                        return 0;
        }
        
        memset(n->_data + len,0,(n->_size - len) * sizeof(int));
        return 1;
}

int _String2Integer(LPINTEGER pNum,char * number)
{
        int i = 0;
        int nRet = 0;
        char cByte = 0;
        int value = 0;
        int power = 0;
        int index =0;
        int len = strlen(number);
        int size = len / NUM_LEN + (len % NUM_LEN == 0 ? 0 : 1);
        int flag = 0;

        do 
        {
                if(len == 0)
                {
                        break;
                }

                
                if(number[0]=='-' || number[0]=='+')
                {
                        if(number[0] == '-')
                        {
                                flag = 1;
                        }
                        
                        number ++;
                        len --;
                }
                
                if(!ISINIT(pNum) && _InitInteger(pNum,size) == 0)
                {
                        break;
                }

                if(size > pNum->_size && _ResizeInteger(pNum,size) == 0)
                {
                        break;
                }
                
                for(i=0 ; i<len ; i++)
                {
                        if(number[i]<'0' || number[i]>'9')
                        {
                                break;
                        }
                }
                if(i < len--)
                {
                        break;
                }


                for(i=len ; i>=0 ; i--)
                {
                        if((len - i) % NUM_LEN == 0)
                        {
                                if(len - i != 0)
                                {
                                        pNum->_data[index++] = value;
                                }

                                value = 0;
                                power = 1;
                        }
                        cByte = number[i] - 0x30;
                        value += power * cByte;
                        power *= 10;
                }

                if(value != 0)
                {
                        pNum->_data[index++] = value;
                }
                pNum->_signed = flag;
                pNum->_len = index;
                while(pNum->_data[pNum->_len-1] == 0)
                {
                        pNum->_len--;
                }
                nRet = 1;
        }while(0);

        return nRet;
}

int _Integer2String(LPINTEGER pNum,char * number)
{
        int i = 0;
        int nRet = 0;
        char buffer[16] = {0};
        
        do 
        {
                if(!ISINIT(pNum))
                {
                        break;
                }

                if(number == 0)
                {
                        nRet = pNum->_len * (NUM_LEN + 1) + 1;
                        break;
                }

                number[0] = 0;

                if(pNum->_signed != 0)
                {
                        strcat(number,"-");
                }
                
                for(i=pNum->_len-1 ; i>=0 ; i--)
                {
                        if(i == pNum->_len-1)
                        {
                                sprintf(buffer,"%d",pNum->_data[i]);
                        }
                        else
                        {
                                sprintf(buffer,"%04d",pNum->_data[i]);
                        }
                        strcat(number,buffer);
                        if(i != 0)
                        {
                                strcat(number,",");
                        }
                }

                nRet = strlen(number);
        }while(0);

        return nRet;
}

void _PushBack(LPINTEGER src,int data)
{

        if(src->_len == src->_size)
        {
                if(!_ResizeInteger(src))
                {
                        return;
                }
        }

        src->_data[src->_len++] = data;
}

void _SimpleAdd(LPINTEGER src,LPINTEGER dst)
{
        int sizeofme = src->_len;
        int sizeofyou = dst->_len;
        int len = sizeofme >= sizeofyou ? sizeofme : sizeofyou;
        int i = 0;
        int value = 0;
        int carry = 0;

        for(i=0 ; i<len ; i++)
        {
                value = carry;
                if(i < sizeofme)
                {
                        value += src->_data[i];
                }

                if(i < sizeofyou)
                {
                        value += dst->_data[i];
                }

                carry = value / BASE;
                value %= BASE;

                if(i < sizeofme)
                {
                        src->_data[i] = value;
                }
                else
                {
                        _PushBack(src,value);
                }
        }

        if(carry != 0)
        {
                if(i < sizeofme)
                {
                        src->_data[i] = carry;
                }
                else
                {
                        _PushBack(src,carry);
                }
        }
};

void _SimpleSub(LPINTEGER src,LPINTEGER dst)
{
        int sizeofme = src->_len;
        int sizeofyou = dst->_len;
        int i = 0;
        int value = 0;
        int carry = 0;
        
        for(i=0 ; i<sizeofme ; i++)
        {
                value = src->_data[i];

                if(i < sizeofyou)
                {
                        value -= dst->_data[i];
                }
                
                value -= carry;
                
                if(value < 0)
                {
                        value += BASE;
                        carry = 1;
                }
                else
                {
                        carry = 0;
                }
                src->_data[i] = value;
        }

        while(src->_data[src->_len-1] == 0)
        {
                src->_len--;
        }
}

int _UnsignedCompare(LPINTEGER src,LPINTEGER dst)
{
        int i = 0;

        if(src->_len > dst->_len)
        {
                return 1;
        }
        else if(src->_len < dst->_len)
        {
                return -1;
        }
        
        for(i=src->_len-1 ; i>=0 ; i--)
        {
                if(src->_data[i] > dst->_data[i])
                {
                        return 1;
                }
                else if(src->_data[i] < dst->_data[i])
                {
                        return -1;
                }
        }

        return 0;
}

void _CopyInteger(LPINTEGER dst,LPINTEGER src)
{
        if(!ISINIT(dst))
        {
                if(!_InitInteger(dst,src->_size))
                {
                        return;
                }
        }
        else if(dst->_size < src->_size)
        {
                if(!_ResizeInteger(dst,src->_size))
                {
                        return;
                }
        }

        memcpy(dst->_data,src->_data,src->_size);
        dst->_len = src->_len;
        dst->_signed = src->_signed;
}

void _UnsignedSub(LPINTEGER src,LPINTEGER dst)
{
        INTEGER n;
        int _signed = src->_signed;

        if(_UnsignedCompare(src,dst) == -1)
        {

                _CopyInteger(&n,dst);
                _SimpleSub(&n,src);
                _CopyInteger(src,&n);
                _UninitInteger(&n);
                src->_signed = !_signed;
        }
        else
        {
                _SimpleSub(src,dst);
        }
}

void _AddInteger(LPINTEGER src,LPINTEGER dst)
{
        int _signed = src->_signed - dst->_signed;
        if(_signed == 0)
        {
                _SimpleAdd(src,dst);
        }
        else
        {
                _UnsignedSub(src,dst);
        }
}

void _SubInteger(LPINTEGER src,LPINTEGER dst)
{
        int _signed = src->_signed - dst->_signed;
        if(_signed != 0)
        {
                _SimpleAdd(src,dst);
        }
        else
        {
                _UnsignedSub(src,dst);
        }
}

int main(int argc, char* argv[])
{
        INTEGER n,m;
        char buffer[128];
        _InitInteger(&n);
        _InitInteger(&m);
        _String2Integer(&n,"-1234567890987654321012345678909876543210123");
        _String2Integer(&m,"99998888777776666655555444433332222111100001234567890");
        
        _AddInteger(&n,&m);
        _Integer2String(&n,buffer);
        _UninitInteger(&n);
        _UninitInteger(&m);
        printf("%s",buffer);
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-12-7 14:08:59 | 显示全部楼层
用的数组实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BASE                (10000)
#define        NUM_LEN                (4)
#define        _BASE_SIZE        (1024)
#define ISINIT(p)        ((p->_data != 0) && (p->_flag == 0))

typedef struct tagInteger
{
        int * _data;
        int _size;
        int _len;
        int _flag;
}INTEGER,*LPINTEGER;

int _InitInteger(LPINTEGER n,int size = 0)
{
        size = ((size == 0) ? _BASE_SIZE : size);
        
        n->_size = 0;
        n->_data = (int *)malloc(size * sizeof(int));
        
        if(n->_data == 0)
        {
                return 0;
        }

        memset(n->_data,0,size * sizeof(int));
        n->_len = 0;
        n->_size = size;
        n->_flag = 0;
        return 1;
}

void _UninitInteger(LPINTEGER n)
{
        if(ISINIT(n))
        {
                free(n->_data);
        }
}

int _ResizeInteger(LPINTEGER n,int _size = 0)
{
        int len = n->_size;
        
        if(!ISINIT(n))
        {
                return _InitInteger(n,_size);
        }
                
        if(_size < _BASE_SIZE)
        {
                n->_size += _BASE_SIZE;
        }
        else
        {
                n->_size += _size;
        }
                
        n->_data = (int *)realloc(n->_data,n->_size * sizeof(int));
                
        if(n->_data == 0)
        {
                        return 0;
        }
        
        memset(n->_data + len,0,(n->_size - len) * sizeof(int));
        return 1;
}

int _String2Integer(LPINTEGER pNum,char * number)
{
        int i = 0;
        int nRet = 0;
        char cByte = 0;
        int value = 0;
        int power = 0;
        int index =0;
        int nLen = strlen(number);
        int size = nLen / NUM_LEN + (nLen % NUM_LEN == 0 ? 0 : 1);

        do 
        {
                if(nLen == 0)
                {
                        break;
                }
                
                if(!ISINIT(pNum) && _InitInteger(pNum,size) == 0)
                {
                        break;
                }

                if(size > pNum->_size && _ResizeInteger(pNum,size) == 0)
                {
                        break;
                }
                
                for(i=0 ; i<nLen ; i++)
                {
                        if(number[i]<'0' || number[i]>'9')
                        {
                                break;
                        }
                }
                if(i < nLen--)
                {
                        break;
                }


                for(i=nLen ; i>=0 ; i--)
                {
                        if((nLen - i) % NUM_LEN == 0)
                        {
                                if(nLen - i != 0)
                                {
                                        pNum->_data[index++] = value;
                                }

                                value = 0;
                                power = 1;
                        }
                        cByte = number[i] - 0x30;
                        value += power * cByte;
                        power *= 10;
                }

                if(value != 0)
                {
                        pNum->_data[index++] = value;
                }

                pNum->_len = index;                
                nRet = 1;
        }while(0);

        return nRet;
}

int _Integer2String(LPINTEGER pNum,char * number)
{
        int i = 0;
        int nRet = 0;
        char buffer[16] = {0};
        
        do 
        {
                if(!ISINIT(pNum))
                {
                        break;
                }

                if(number == 0)
                {
                        nRet = pNum->_len * NUM_LEN + 1;
                        break;
                }

                number[0] = 0;
                
                for(i=pNum->_len-1 ; i>=0 ; i--)
                {
                        if(i == pNum->_len-1)
                        {
                                sprintf(buffer,"%d",pNum->_data[i]);
                        }
                        else
                        {
                                sprintf(buffer,"%04d",pNum->_data[i]);
                        }
                        strcat(number,buffer);
                        if(i != 0)
                        {
                                strcat(number,",");
                        }
                }

                nRet = strlen(number);
        }while(0);

        return nRet;
}

void _PushBack(LPINTEGER src,int data)
{

        if(src->_len == src->_size)
        {
                if(!_ResizeInteger(src))
                {
                        return;
                }
        }

        src->_data[src->_len++] = data;
}

void _IntegerAdd(LPINTEGER src,LPINTEGER dst)
{
        int sizeofme = src->_len;
        int sizeofyou = dst->_len;
        int len = sizeofme >= sizeofyou ? sizeofme : sizeofyou;
        int i = 0;
        int value = 0;
        int carry = 0;

        for(i=0 ; i<len ; i++)
        {
                value = carry;
                if(i < sizeofme)
                {
                        value += src->_data[i];
                }

                if(i < sizeofyou)
                {
                        value += dst->_data[i];
                }

                carry = value / BASE;
                value %= BASE;

                if(i < sizeofme)
                {
                        src->_data[i] = value;
                }
                else
                {
                        _PushBack(src,value);
                }
        }

        if(carry != 0)
        {
                if(i < sizeofme)
                {
                        src->_data[i] = carry;
                }
                else
                {
                        _PushBack(src,carry);
                }
        }

};


int main(int argc, char* argv[])
{
        INTEGER n,m;
        char buffer[128];
        _InitInteger(&n);
        _InitInteger(&m);
        _String2Integer(&n,"1234567890987654321012345678909876543210123");
        _String2Integer(&m,"9999888877777666665555544443333222211110000");
        _IntegerAdd(&n,&m);
        _Integer2String(&n,buffer);
        _UninitInteger(&n);
        _UninitInteger(&m);
        printf("%s",buffer);
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-12-7 14:44:37 | 显示全部楼层    本楼为最佳答案   
本帖最后由 xieglt 于 2020-12-7 14:53 编辑

后面才看到要考虑符号。又改了下,一个有符号的版本
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BASE                (10000)
#define        NUM_LEN                (4)
#define        _BASE_SIZE        (1024)
#define ISINIT(p)        ((p->_data != 0) && (p->_flag == 0))

typedef struct tagInteger
{
        int * _data;
        int _size;
        int _len;
        int _signed;
        int _flag;
}INTEGER,*LPINTEGER;

int _InitInteger(LPINTEGER n,int size = 0)
{
        size = ((size == 0) ? _BASE_SIZE : size);
        
        n->_size = 0;
        n->_data = (int *)malloc(size * sizeof(int));
        
        if(n->_data == 0)
        {
                return 0;
        }

        memset(n->_data,0,size * sizeof(int));
        n->_len = 0;
        n->_size = size;
        n->_flag = 0;
        return 1;
}

void _UninitInteger(LPINTEGER n)
{
        if(ISINIT(n))
        {
                free(n->_data);
        }
}

int _ResizeInteger(LPINTEGER n,int _size = 0)
{
        int len = n->_size;
        
        if(!ISINIT(n))
        {
                return _InitInteger(n,_size);
        }
                
        if(_size < _BASE_SIZE)
        {
                n->_size += _BASE_SIZE;
        }
        else
        {
                n->_size += _size;
        }
                
        n->_data = (int *)realloc(n->_data,n->_size * sizeof(int));
                
        if(n->_data == 0)
        {
                        return 0;
        }
        
        memset(n->_data + len,0,(n->_size - len) * sizeof(int));
        return 1;
}

int _String2Integer(LPINTEGER pNum,char * number)
{
        int i = 0;
        int nRet = 0;
        char cByte = 0;
        int value = 0;
        int power = 0;
        int index =0;
        int len = strlen(number);
        int size = len / NUM_LEN + (len % NUM_LEN == 0 ? 0 : 1);
        int flag = 0;

        do 
        {
                if(len == 0)
                {
                        break;
                }

                
                if(number[0]=='-' || number[0]=='+')
                {
                        if(number[0] == '-')
                        {
                                flag = 1;
                        }
                        
                        number ++;
                        len --;
                }
                
                if(!ISINIT(pNum) && _InitInteger(pNum,size) == 0)
                {
                        break;
                }

                if(size > pNum->_size && _ResizeInteger(pNum,size) == 0)
                {
                        break;
                }
                
                for(i=0 ; i<len ; i++)
                {
                        if(number[i]<'0' || number[i]>'9')
                        {
                                break;
                        }
                }
                if(i < len--)
                {
                        break;
                }


                for(i=len ; i>=0 ; i--)
                {
                        if((len - i) % NUM_LEN == 0)
                        {
                                if(len - i != 0)
                                {
                                        pNum->_data[index++] = value;
                                }

                                value = 0;
                                power = 1;
                        }
                        cByte = number[i] - 0x30;
                        value += power * cByte;
                        power *= 10;
                }

                if(value != 0)
                {
                        pNum->_data[index++] = value;
                }
                pNum->_signed = flag;
                pNum->_len = index;
                while(pNum->_data[pNum->_len-1] == 0)
                {
                        pNum->_len--;
                }
                nRet = 1;
        }while(0);

        return nRet;
}

int _Integer2String(LPINTEGER pNum,char * number)
{
        int i = 0;
        int nRet = 0;
        char buffer[16] = {0};
        
        do 
        {
                if(!ISINIT(pNum))
                {
                        break;
                }

                if(number == 0)
                {
                        nRet = pNum->_len * (NUM_LEN + 1) + 1;
                        break;
                }

                number[0] = 0;

                if(pNum->_signed != 0)
                {
                        strcat(number,"-");
                }
                
                for(i=pNum->_len-1 ; i>=0 ; i--)
                {
                        if(i == pNum->_len-1)
                        {
                                sprintf(buffer,"%d",pNum->_data[i]);
                        }
                        else
                        {
                                sprintf(buffer,"%04d",pNum->_data[i]);
                        }
                        strcat(number,buffer);
                        if(i != 0)
                        {
                                strcat(number,",");
                        }
                }

                nRet = strlen(number);
        }while(0);

        return nRet;
}

void _PushBack(LPINTEGER src,int data)
{

        if(src->_len == src->_size)
        {
                if(!_ResizeInteger(src))
                {
                        return;
                }
        }

        src->_data[src->_len++] = data;
}

void _SimpleAdd(LPINTEGER src,LPINTEGER dst)
{
        int sizeofme = src->_len;
        int sizeofyou = dst->_len;
        int len = sizeofme >= sizeofyou ? sizeofme : sizeofyou;
        int i = 0;
        int value = 0;
        int carry = 0;

        for(i=0 ; i<len ; i++)
        {
                value = carry;
                if(i < sizeofme)
                {
                        value += src->_data[i];
                }

                if(i < sizeofyou)
                {
                        value += dst->_data[i];
                }

                carry = value / BASE;
                value %= BASE;

                if(i < sizeofme)
                {
                        src->_data[i] = value;
                }
                else
                {
                        _PushBack(src,value);
                }
        }

        if(carry != 0)
        {
                if(i < sizeofme)
                {
                        src->_data[i] = carry;
                }
                else
                {
                        _PushBack(src,carry);
                }
        }
};

void _SimpleSub(LPINTEGER src,LPINTEGER dst)
{
        int sizeofme = src->_len;
        int sizeofyou = dst->_len;
        int i = 0;
        int value = 0;
        int carry = 0;
        
        for(i=0 ; i<sizeofme ; i++)
        {
                value = src->_data[i];

                if(i < sizeofyou)
                {
                        value -= dst->_data[i];
                }
                
                value -= carry;
                
                if(value < 0)
                {
                        value += BASE;
                        carry = 1;
                }
                else
                {
                        carry = 0;
                }
                src->_data[i] = value;
        }

        while(src->_data[src->_len-1] == 0)
        {
                src->_len--;
        }
}

int _UnsignedCompare(LPINTEGER src,LPINTEGER dst)
{
        int i = 0;

        if(src->_len > dst->_len)
        {
                return 1;
        }
        else if(src->_len < dst->_len)
        {
                return -1;
        }
        
        for(i=src->_len-1 ; i>=0 ; i--)
        {
                if(src->_data[i] > dst->_data[i])
                {
                        return 1;
                }
                else if(src->_data[i] < dst->_data[i])
                {
                        return -1;
                }
        }

        return 0;
}

void _CopyInteger(LPINTEGER dst,LPINTEGER src)
{
        if(!ISINIT(dst))
        {
                if(!_InitInteger(dst,src->_size))
                {
                        return;
                }
        }
        else if(dst->_size < src->_size)
        {
                if(!_ResizeInteger(dst,src->_size))
                {
                        return;
                }
        }

        memcpy(dst->_data,src->_data,src->_size);
        dst->_len = src->_len;
        dst->_signed = src->_signed;
}

void _UnsignedSub(LPINTEGER src,LPINTEGER dst)
{
        INTEGER n;
        int _signed = src->_signed;

        if(_UnsignedCompare(src,dst) == -1)
        {

                _CopyInteger(&n,dst);
                _SimpleSub(&n,src);
                _CopyInteger(src,&n);
                _UninitInteger(&n);
                src->_signed = !_signed;
        }
        else
        {
                _SimpleSub(src,dst);
        }
}

void _AddInteger(LPINTEGER src,LPINTEGER dst)
{
        int _signed = src->_signed - dst->_signed;
        if(_signed == 0)
        {
                _SimpleAdd(src,dst);
        }
        else
        {
                _UnsignedSub(src,dst);
        }
}

void _SubInteger(LPINTEGER src,LPINTEGER dst)
{
        int _signed = src->_signed - dst->_signed;
        if(_signed != 0)
        {
                _SimpleAdd(src,dst);
        }
        else
        {
                _UnsignedSub(src,dst);
        }
}

int main(int argc, char* argv[])
{
        INTEGER n,m;
        char buffer[128];
        _InitInteger(&n);
        _InitInteger(&m);
        _String2Integer(&n,"-1234567890987654321012345678909876543210123");
        _String2Integer(&m,"99998888777776666655555444433332222111100001234567890");
        
        _AddInteger(&n,&m);
        _Integer2String(&n,buffer);
        _UninitInteger(&n);
        _UninitInteger(&m);
        printf("%s",buffer);
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-12 12:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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