C - 如果长度不同,则将 2 个字符串中的数字加在一起

Posted

技术标签:

【中文标题】C - 如果长度不同,则将 2 个字符串中的数字加在一起【英文标题】:C - Adding the numbers in 2 strings together if a different length 【发布时间】:2013-05-21 01:20:16 【问题描述】:

如果我有两个字符串:

a = "1234"
b = "4321"

我可以像这样将这两个数字相加:

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;

然后反转它(宽度等于strlen(a))。

如果出现以下情况,我怎么能做同样的事情?

a = "12345"
b = "4321"

我需要重新分配内存吗?还是什么?

(顺便说一句 - the problem I'm trying to solve 使用了许多 50 位数字,所以我理解 strtoul 或 strtoull 是不可能的。Here's my code so far。)

【问题讨论】:

您可以在较小的数字前加上 0,使其长度与较大的数字相等。 【参考方案1】:
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);

【讨论】:

【参考方案2】:

如果你坚持使用“小学加法”,找到两个字符串的长度,前进到它们的末端,然后向后移动,直到较短的字符串的长度用完。然后继续只移入较长的字符串,假设较短的字符串的剩余数字为零:

12345
04321

您需要一直移动到较长字符串的开头,并在那里处理进位。请注意,无论如何您都需要分配一个新结果,因为添加两个N-digit 数字可能会由于进位而导致N+1-digit 数字。

【讨论】:

除了这个添加之外,还有更有效的方法吗?无需创建一些新的“数据类型”或结构.. @jaska 不幸的是,C 没有为任意精度数学提供太多结构。不过,您可以为它找到许多预构建的库。 谢谢。我正在努力让普通 C 变得更舒服,不要让自己轻松:)) bis spader【参考方案3】:
#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;

【讨论】:

【参考方案4】:

引用自C - Adding the numbers in 2 strings together if a different length 回答,我写了一个更易读的代码:

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);

测试代码如下:

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;

输出:

579

456912

100020

【讨论】:

【参考方案5】:
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--;
    


【讨论】:

请在您的代码中添加一些注释行:)

以上是关于C - 如果长度不同,则将 2 个字符串中的数字加在一起的主要内容,如果未能解决你的问题,请参考以下文章

C语言中 %d之间加了个数字啥作用?

获取字符长度,中文2个字符,英文数字一个字符

C语言编程 计算一串字符中的数字个数

C语言如何将一个字符串按照规定长度分解为几个字符串

Codeforces Round #371 (Div. 2) C. Sonya and Queries(字典树)

如果与给定的数字匹配,则将数组中的数字相乘