只是为了好玩,我正试着用C语言写一段代码,它像人类一样加2个数字.However the code breaks if they are of same length.还有其他方法可以将2个非常大的数字相加,但是他们使用诸如倒数、位操作符或使用长整型这样的技巧来相加;这不是我想要的.

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

int main()
{
    int *ptr, *ptr2, *ptr3;
    int size, size2, size3, carry = 0;
    
    printf("Enter size of 1st element: ");
    scanf("%d", &size);
    ptr = (int *)calloc(size, sizeof(int));
    if (ptr == NULL)
        printf("Memory not allocated.\n");
    else {
        for (int j = 0; j < size; ++j) {
            scanf("%d", &ptr[j]);
        }
    }

    printf("\nEnter size of 2nd element: ");
    scanf("%d", &size2);
    ptr2 = (int *)calloc(size2, sizeof(int));
    if (ptr2 == NULL)
        printf("Memory not allocated.\n");
    else {
        for (int j = 0; j < size2; ++j) {
            scanf("%d", &ptr2[j]);
        }
    }
    printf("\n");

    // Addition starts here

    if (size > size2)
        size3 = size + 1;
    else
        size3 = size2 + 1;
    ptr3 = (int *)calloc(size3, sizeof(int));
    for (int j = 0; j < size3; ++j) {
        ptr3[j]=0;
    }

    if (size > size2) {     //1st number higher digits
        for (int k = 1; k <= size2; ++k) {
            ptr3[k - 1] = (carry + ptr[size - k] + ptr2[size2 - k]);
            carry = ptr3[k - 1] / 10;
            ptr3[k - 1] = ptr3[k - 1] % 10;
        }
        for (int k = size2 + 1; k <= size; ++k) {
            if (k == size2)
                ptr3[k - 1] = ptr[size - k] + carry;
            else
                ptr3[k - 1] = ptr[size - k];
        }
    } else if (size2 > size)  { //2nd number higher digits
        for (int k = 1; k <= size; ++k) {
            ptr3[k - 1] = (carry + ptr2[size2 - k] + ptr[size - k]);
            carry = ptr3[k - 1] / 10;
            ptr3[k - 1] = ptr3[k - 1] % 10;
        }
        for (int k = size + 1; k <= size2; ++k) {
            if (k == size)
                ptr3[k - 1] = ptr2[size2 - k] + carry;
            else
                ptr3[k - 1] = ptr2[size2 - k];
        }       
    } else {                //equal digits
        for (int k = size; k > -1; --k) {
            ptr3[k] = (carry + ptr2[k] + ptr[k]);
            printf("%d + %d = %d\n", ptr2[k], ptr[k], ptr3[k]);
            carry = ptr3[k] / 10;
            ptr3[k] = ptr3[k] % 10;
        }
    }

    //  DISPLAY     
    for (int j = 0; j < size; ++j) {
        printf("%d", ptr[j]);
    }
    printf("+");
    for (int j = 0; j < size2; ++j) {
        printf("%d", ptr2[j]);
    }
    printf(" = ");
    for (int j = size3; j > -1; --j) {
        if (ptr3[j] >= 0)
            printf("%d", ptr3[j]);
    }
    return 0;
}

推荐答案

您的代码中存在多个问题:

  • 当您检测到内存分配失败时,应该退出程序,以避免在访问分配失败的数组时出现未定义的行为.

  • 将数字作为单独的数字读取是很麻烦的:您应该使用scanf("%1d", &ptr[i])来读取单个数字,即使它们是连续键入的.

  • 您不判断结果数组的分配失败.

  • 初始化由ptr3指向的数组是没有用的,因为calloc()已经将所有字节设置为0,这保证了作为int访问的所有元素都是0.

  • 在前两个加法循环中,您应该将相加数字存储在条目中的ptr3[size3 - k]位.

  • 在这些情况下,第二个循环是不正确的:您应该编写

      for (int k = size2 + 1; k <= size; ++k) {
          ptr3[size3 - k] = ptr[size - k] + carry;
          carry = ptr3[size3 - k] / 10;
          ptr3[size - k] = ptr3[size - k] % 10;
      }
    

    或者使用carry存储中间结果:

      for (int k = size2 + 1; k <= size; ++k) {
          carry = carry + ptr[size - k];
          ptr3[size - k] = carry % 10;
          carry = carry / 10;
      }
    
  • 您应该将最高有效数字存储为ptr3[0] = carry

  • size == size2的情况下,您使用一种不同的方法进行向下循环,但边界不正确,并且在第一次迭代时访问超出数组末尾的元素.此外,您应该将数字存储在结果数组中的下一个索引处,以便为可能的非零前导数字腾出空间:

       for (int k = size; --k > 0;) {
          ptr3[k + 1] = carry + ptr[k] + ptr2[k];
          carry = ptr3[k + 1] / 10;
          ptr3[k + 1] = ptr3[k + 1] % 10;
       }
       ptr3[0] = carry;
    

    或者使用carry存储中间结果:

       for (int k = size; --k > 0;) {
          carry = carry + ptr[k] + ptr2[k];
          ptr3[k + 1] = carry % 10;
          carry = carry / 10;
       }
       ptr3[0] = carry;
    
  • 然而,注意,不需要第三种情况,其中size == size2可以通过第一或第二种情况或组合方法来处理,将两个长度中较小的一个上的数字相加,并通过剩余的数字传播进位.

  • 在最后一次循环中,您只输出结果的非零数字:这是不正确的,您应该只跳过前导零.

以下是一个经过修改的版本,其中采用了综合方法:

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

int main(void)
{
    int *ptr1, *ptr2, *ptr3;
    int size1, size2, size3, minsize, carry;
    
    printf("Enter size of 1st number: ");
    if (scanf("%d", &size1) != 1 || size1 <= 0)
       return 1;
    ptr1 = (int *)calloc(size1, sizeof(int));
    if (ptr1 == NULL) {
        printf("Memory not allocated.\n");
        return 1;
    }
    for (int j = 0; j < size1; ++j) {
        if (scanf("%1d", &ptr1[j]) != 1)
            return 1;
    }

    printf("\nEnter size of 2nd number: ");
    if (scanf("%d", &size2) != 1 || size2 <= 0)
        return 1;
    ptr2 = (int *)calloc(size2, sizeof(int));
    if (ptr2 == NULL) {
        printf("Memory not allocated.\n");
        return 1;
    }
    for (int j = 0; j < size2; ++j) {
        if (scanf("%1d", &ptr2[j]) != 1)
            return 1;
    }
    printf("\n");

    // Addition starts here

    if (size1 > size2) {
        minsize = size2;
        size3 = size1 + 1;
    } else {
        minsize = size1;
        size3 = size2 + 1;
    }
    ptr3 = (int *)calloc(size3, sizeof(int));
    if (ptr3 == NULL) {
        printf("Memory not allocated.\n");
        return 1;
    }

    // handle digits up to the smaller number size
    carry = 0;
    for (int k = 0; k < minsize; ++k) {
        carry = carry + ptr1[size1 - k - 1] + ptr2[size2 - k - 1];
        ptr3[size3 - k - 1] = carry % 10;
        carry = carry / 10;
    }
    // handle remaining digits of the first number if it is larger
    for (int k = minsize; k < size1; ++k) {
        carry = carry + ptr1[size1 - k - 1];
        ptr3[size3 - k - 1] = carry % 10;
        carry = carry / 10;
    }
    // handle remaining digits of the second number if it is larger
    for (int k = minsize; k < size2; ++k) {
        carry = carry + ptr2[size2 - k - 1];
        ptr3[size3 - k - 1] = carry % 10;
        carry = carry / 10;
    }
    // store the most significant digit of the result (0 or 1)
    ptr3[0] = carry;

    //  DISPLAY     
    for (int j = 0; j < size1; ++j) {
        printf("%d", ptr1[j]);
    }
    printf("+");
    for (int j = 0; j < size2; ++j) {
        printf("%d", ptr2[j]);
    }
    printf(" = ");
    for (int j = (ptr3[0] == 0); j < size3; ++j) {
        printf("%d", ptr3[j]);
    }
    printf("\n");
    return 0;
}

你可能还想读这个问题:Calculating a very large integer和我的答案,它提供了additional个洞察力(双关语).

C++相关问答推荐

字符串令牌化xpath表达式

为什么写入系统调用打印的字符数不正确?

va_copy的使用是未定义的行为吗?

__VA_OPT__(,)是否可以检测后面没有任何内容的尾随逗号?

测量ARM MCU中断延迟的问题

在列表中插入Int指针(C)

如何使解释器存储变量

GTK3按钮信号错误

有什么方法可以将字符串与我们 Select 的子字符串分开吗?喜欢:SIN(LOG(10))

tick.q中的Kdb+键控表语法

为什么用非常数指针变量改变常量静态变量时会出现分段错误?

覆盖读取函数,但当文件描述符为3或4时,我有问题

我正在try 将QSORT算法实现为C++中的泛型函数

unions 的原子成员是个好主意吗?

用C++初始化局部数组变量

Malloc和对齐

程序打印一些随机空行

C 错误:对 int 数组使用 typedef 时出现不兼容的指针类型问题

使用邻接表创建图

在带中断的循环缓冲区中使用 易失性