仅使用C在两个大数字之间添加操作

时间:2018-03-29 10:22:30

标签: c algorithm numbers

我想尝试的是在600位数下添加两个大数字。 所以我在C中制作struct 但是下面的源代码中存在一些错误。

(实践环境是 GCC编译器和Linux。该工具是 VSCode ,带有 BASH终端。)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAX_SIZE 600
#define SWAP(x,y,t) ((t)=(x), (x)=(y), (y)=(t)) //SWAP preprocessor
#define D_C(x) (x==0 ? 0 : x+'0') //Convert Decimal to Character
#define C_D(x) (x==0 ? 0 : x-'0') //Convert Character to Decimal


/*The structure to save BIG NUMBER*/
typedef struct _BIG_DECIMAL{
    unsigned char *data;
    int size;
} BIG_DECIMAL;

/*Make string reverse*/
void reverseString(char* s, size_t size) {
  char temp;
  for (size_t i = 0; i < size / 2; i++) SWAP(s[i], s[(size - 1) - i], temp);
}

/*Create Decimal data in BIG_DECIMAL struct*/
BIG_DECIMAL * createDecimal(unsigned char *str) {
    //local variables in func.
    size_t size_str;    
    BIG_DECIMAL * number = malloc(sizeof(BIG_DECIMAL));

    //save str in buffer
    char buffer[MAX_SIZE] = {'\0',};
    strcpy(buffer, str);

    //temporary value for size measure.
    size_str = strlen(buffer);
    printf("%d", size_str);
    //Save reversed number data.
    reverseString(buffer, size_str);
    strcpy(number->data, buffer);
    //Save size.
    number->size = size_str;

    //Return BIG_DECIMAL struct.
    return number;
}

/*ADDITION BETWEEN TWO BIG NUMBERS. left argument's size value should be big.*/
BIG_DECIMAL * BD_addition(BIG_DECIMAL *dec1, BIG_DECIMAL *dec2) {
    //local variable in this func.
    int carry = 0;
    BIG_DECIMAL *result = malloc(sizeof(BIG_DECIMAL));
    //Adding loop start
    for(int i = 0; i < (result -> size); i++) {
        int digit_plus;    
        //if start
        if(i < dec2->size) {
            //there are digit in both dec so...
            digit_plus = C_D(dec1->data[i]) + C_D(dec2->data[i]) + carry;
            //nested-if start
            if(digit_plus > 10) { //if the carry is occured
                carry = digit_plus / 10; //carry can be (> 1)
                result->data[i] = D_C(digit_plus % 10);
            }
            else { //if the carry is not occcured
                carry = digit_plus / 10; //carry can be (> 1)
                result->data[i] = D_C(digit_plus % 10);
            }
            //nested-if end
        }
        else if((i >= (dec2->size)) && (i < ((result->size)-1))){
            digit_plus = C_D(dec1->data[i]) + carry;
            //nested-if start
            if(digit_plus > 10) { //if the carry is occured
                carry = digit_plus / 10;
                result->data[i] = D_C(digit_plus % 10);
            }
            else { //if the carry is not occcured 
                carry = 0;
                result->data[i] = D_C(digit_plus);
            }
            //nested-if end
        }
        else { //if i == (result->size)-1   (the last index of result->data)
            //nested-if start
            if(carry > 0) result->data[i] = D_C(carry); //if carry occured
            else { //if the carry doesn't occure in the last index of result->data
                result->data[i] = D_C(0); //the last index value of result->data is NULL.
                --(result->size); //result size - 1
            }
            //nested-if end
        }
        //if end
    }
    //Adding loop end

    return result;
}

int main() {
    /*data for operand*/
    BIG_DECIMAL * op1;
    BIG_DECIMAL * op2;
    /*data for result*/
    BIG_DECIMAL * result;

    op1 = createDecimal("123456789");
    op2 = createDecimal("12345678");

    result = BD_addition(op1,op2);
    printf("%s", result->data);

    /*DeAllocation*/
    free(op1);
    free(op2);
    free(result);
    return 0;
}

此代码导致Segmentation fault错误。 我认为它可能首先是字符串访问错误,所以我尝试输入所有char*类型变量,但它不起作用。

2 个答案:

答案 0 :(得分:1)

作为评论中的指针,您可以通过为data分配足够的空间来更正代码,您可以使用strdup

/*Create Decimal data in BIG_DECIMAL struct*/
BIG_DECIMAL * createDecimal(unsigned char *str) {
    //local variables in func.
    size_t size_str;    
    BIG_DECIMAL * number = malloc(sizeof(BIG_DECIMAL));

    //save str in buffer
    char buffer[MAX_SIZE] = {'\0',};
    strcpy(buffer, str);

    //temporary value for size measure.
    size_str = strlen(buffer);

    //Save reversed number data.
    reverseString(buffer, size_str);

    /* here: copy buffer in a new allocated memory stored in number->data. */
    number->data = strdup(buffer);

    //Save size.
    number->size = size_str;

    //Return BIG_DECIMAL struct.
    return number;
}

不要忘记正确释放它们:

/*DeAllocation*/
free(op1->data);
free(op1);
free(op2->data);
free(op2);

您的代码中存在一些错误:BD_addition函数的开头应如下所示:

BIG_DECIMAL * BD_addition(BIG_DECIMAL *dec1, BIG_DECIMAL *dec2) {
    //local variable in this func.
    int carry = 0;
    BIG_DECIMAL *result = malloc(sizeof(BIG_DECIMAL));
    /* compute the size of result */
    result->size = (dec1->size < dec2->size) ? dec1->size : dec2->size;

    /* take in account an eventual carry */
    result->size += 1;

    /* allocate */
    result->data = malloc(result->size+1);

    //Adding loop start
    ....

您的宏D_C似乎无效(0未转换为'0')。

答案 1 :(得分:0)

如果你愿意,这里只有一个malloc。

没有struct,strdup,reverse等
#include <stdlib.h>
#define toI(x) ((x)-'0')
#define toC(x) ((x)+'0')
#define max(a,b) ((a)>(b)) ? (a):(b)

char *add(char *buf1, char *buf2) {
    int size, v1, v2, r, carry=0;
    char *ap1, *ep1, *ap2, *ep2, *ap3, *ep3, *rp, *result;

    for(ep1=ap1=buf1; *ep1; ep1++);
    for(ep2=ap2=buf2; *ep2; ep2++);

    size=max(ep2-ap2, ep1-ap1);
    ap3=ep3=rp=result=malloc(size+10);

    ep3+=size+10;
    rp=ep3-1;
    *rp='\0';
    for(ep1--, ep2--, rp--; ep1>=ap1 || ep2>=ap2; ep1--, ep2--, rp--) {
        v1 = ep1>=ap1 ? toI(*ep1) : 0;
        v2 = ep2>=ap2 ? toI(*ep2) : 0;
        r = v1+v2+carry;
        *rp=toC(r%10);
        carry=r/10;
    }
    if(carry!=0) *rp-- = toC(carry);
    for(rp++;rp<ep3; rp++, ap3++)
        *ap3=*rp;

    return result;
}
int main() {
    char *result = add("123456789", "12345678");
    printf("\n%s\n", result);
    free(result);
}