galois
galois

Reputation: 857

C - Adding the numbers in 2 strings together if a different length

If I had two strings:

a = "1234"
b = "4321"

I could add the two numbers together like this:

for(i=0; i<width-1; i++){
    sum = (a[width-2-i]-48) + (b[width-2-i]-48) + carry;
    carry = 0;
    if(sum > 9){
        carry = 1;
        sum-=10;
    }
    answer[i] = sum+48;
}

if(carry) answer[i++] = carry+48;
answer[i]= 0;

And then reverse it (width is equal to strlen(a)).

How could I do the same thing if the following?

a = "12345"
b = "4321"

Would I need to reallocate memory? Or what?

(BTW - the problem I'm trying to solve is using many numbers all with 50 digits, so strtoul or strtoull is out of the question as I understand. Here's my code so far.)

Upvotes: 0

Views: 12360

Answers (5)

Gary Lloyd M. Senoc
Gary Lloyd M. Senoc

Reputation: 11

int num(char x,int len){
    if(len <0)
        return 0;
    return ((x=='1') ? 1 :  (x=='2') ? 2 : (x=='3') ? 3 : (x=='4') ? 4 : (x=='5') ? 5 : (x=='6') ? 6 : (x=='7') ? 7 : (x=='8') ? 8 : 9);
}

int main(){


    int result[100];
    int i=0;
    char num1[] = "123456789123456789";
    char num2[] = "1234567811111111111111111111";
    int carry = 0;
    int l1= strlen(num1)-1;
    int l2 = strlen(num2)-1;
    int result1;


    while(1){
        if(l1 < 0  && l2 <0 && carry == 0)
            break;
        result1 = num(num1[l1],l1) + num(num2[l2],l2);
        l1--;
        l2--;
        if(carry>0){
            result1 +=carry;
            carry = 0;
        }
        carry = result1 / 10;
        result[i] = (result1 % 10);
        i++;
    }

    i--;
    printf("\n");

    while(i>=0){
            printf("%d",result[i]);
            i--;
    }

}

Upvotes: 0

Jayhello
Jayhello

Reputation: 6602

cited from C - Adding the numbers in 2 strings together if a different length answer, I write a more readable code:

void str_reverse(char *beg, char *end){
    if(!beg || !end)return;
    char cTmp;
    while(beg < end){
        cTmp = *beg;
        *beg++ = *end;
        *end-- = cTmp;
    }
}

#define c2d(c) (c - '0')
#define d2c(d) (d + '0')
void str_add(const char* s1, const char* s2, char* s_ret){
    int s1_len = strlen(s1);
    int s2_len = strlen(s2);

    int max_len = s1_len;
    int min_len = s2_len;
    const char *ps_max = s1;
    const char *ps_min = s2;

    if(s2_len > s1_len){
        ps_min = s1;min_len = s1_len;
        ps_max = s2;max_len = s2_len;
    }

    int carry = 0;
    int i, j = 0;
    for (i = max_len - 1; i >= 0; --i) {
        // this wrong-prone
        int idx = (i - max_len + min_len) >=0 ? (i - max_len + min_len) : -1;
        int sum = c2d(ps_max[i]) + (idx >=0  ? c2d(ps_min[idx]) : 0) + carry;

        carry = sum / 10;
        sum = sum % 10;

        s_ret[j++] = d2c(sum);
    }

    if(carry)s_ret[j] = '1';
    str_reverse(s_ret, s_ret + strlen(s_ret) - 1);
}

test code as below:

void test_str_str_add(){
    char s1[] = "123";
    char s2[] = "456";
    char s3[10] = {'\0'};

    str_add(s1, s2, s3);
    std::cout<<s3<<std::endl;

    char s4[] = "456789";
    char s5[10] = {'\0'};
    str_add(s1, s4, s5);
    std::cout<<s5<<std::endl;

    char s7[] = "99999";
    char s8[] = "21";
    char s9[10] = {'\0'};
    str_add(s7, s8, s9);
    std::cout<<s9<<std::endl;
}

output:

579

456912

100020

Upvotes: 0

BLUEPIXY
BLUEPIXY

Reputation: 40145

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

#define c2d(c) (c-'0')
#define d2c(c) (c+'0')

char* add(const char *a, const char *b, char *ans){
    int alen, blen;
    int i, carry=0;
    char *wk;
    char *awk=strdup(a);
    char *bwk=strdup(b);

    alen=strlen(strrev(awk));
    blen=strlen(strrev(bwk));
    if(alen<blen){
        alen ^= blen;blen ^= alen;alen ^= blen;//swap
        wk = awk ; awk = bwk ; bwk = wk;
    }
    ans[alen+1]=ans[alen]='\0';
    for(i=0;i<alen;++i){
        int sum = c2d(awk[i])+(i<blen ? c2d(bwk[i]): 0)+carry;
        ans[i] = d2c(sum % 10);
        carry = sum / 10;
    }
    if(carry){
        ans[i++]='1';
    }
    free(awk);
    free(bwk);
    return strrev(ans);
}

int main(){
    const char *a="12345";
    const char *b="4321";
    char ans[6];

    printf("{%s}+{%s}={%s}\n", a, b, add(a,b, ans));
    return 0;
}

Upvotes: 0

perreal
perreal

Reputation: 97938

int getcharval(const char *s, int idx) {
    if (idx < strlen(s))
        return s[strlen(s) - idx - 1] - 48; 
    return 0;
}

void add() {
    const char *a = "1234";
    const char *b = "13210";
    char answer[256];
    int i, wa=strlen(a), wb=strlen(b), width, sum, carry;
    width = wa > wb ? wa : wb; 
    for(i=0; i<width; i++){
        char ca = getcharval(a, i); 
        char cb = getcharval(b, i); 
        printf("%d %d\n", ca, cb);
        sum = ca + cb + carry;
        carry = 0;
        if(sum > 9){ 
            carry = 1;
            sum-=10;
        }
        answer[i] = sum+48;
    }   
    if(carry) answer[i++] = carry+48;
    answer[i]= 0;
    for (i = 0; i < strlen(answer) / 2; i++) {
        char t = answer[i];
        answer[i] = answer[strlen(answer) - i - 1]; 
        answer[strlen(answer) - i - 1] = t;
    }   

    printf("%s\n", answer);
}

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726489

If you insist on using the "elementary school addition", find the length of both strings, advance to their ends, and then move back until the shorter string's length is exhausted. Then continue moving in only the longer string, assuming that the remaining digits of the shorter string are zeros:

12345
04321

You need to move all the way to the beginning of the longer string, and process the carry there. Note that you need to allocate a new result anyway, because adding two N-digit numbers may result in a N+1-digit number due to the carry.

Upvotes: 1

Related Questions