【问题标题】:Adding long numbers using strings in C在 C 中使用字符串添加长数字
【发布时间】:2020-05-27 01:03:01
【问题描述】:

我正在尝试制作一个使用字符串添加非常大整数的程序。但是,对于与小于 7 的数字相加的整数,输出是无意义的,并且所有其他总和都比正确输出小 7。任何人都可以辨别出可能导致这种情况的原因吗? 7 似乎是凭空而来的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX 10000

int main(void) {
  char str1[MAX],str2[MAX],strnew[MAX],str[MAX];
  int i,l,count,len1,len2,len,zers,nex,excess=0;

  printf("Enter first number:");
  fgets(str1,MAX,stdin);
  printf("Enter second number:");
  fgets(str2,MAX,stdin);

  len1=strlen(str1);
  len2=strlen(str2);

  if(len1<=len2){
    len=len2;
  }
  else{
    len=len1;
  }

  if(len1<=len2){
    zers=len2-len1;
    for(i=0;i<len;i++){
      if(i<zers){
        strnew[i]='0';
      }
      else{
        strnew[i]=str1[i-zers];
      }
    }
    strnew[len]='\0';
  }

  if(len2<len1){
    zers=len1-len2;
    for(i=0;i<len;i++){
      if(i<zers){
        strnew[i]='0';
      }
      else{
        strnew[i]=str2[i-zers];
      }
    }
    strnew[len]='\0';
  }

  for(i=len;i>0;i--){
    if(len1>len2){
      str[i]=(strnew[i-1]-'0'+str1[i-1]-'0'+excess)%10+'0';
      excess=(strnew[i-1]-'0'+str1[i-1]-'0'+excess-(strnew[i-1]-'0'+str1[i-1]-'0'+excess)%10)/10;

    }
    if(len2>=len1){
      str[i]=(strnew[i-1]-'0'+str2[i-1]-'0'+excess)%10+'0';
      excess=(strnew[i-1]-'0'+str2[i-1]-'0'+excess-(strnew[i-1]-'0'+str2[i-1]-'0'+excess)%10)/10;
    }
  }
  str[len]='\0';
  str[0]=excess+'0';
  printf("%s",str);


}

【问题讨论】:

  • 您的代码难以理解。一个原因是格式化,另一个是你的算法看起来太复杂了。我建议您简化它,然后尝试通过阅读代码来遵循它,看看您是否可以毫不费力地理解它在做什么。
  • 并且避免将变量命名为strnew,因为它看起来像str___ 函数,并且在c 中有很多。相反,使用 sumresult 之类的东西看起来更合乎逻辑

标签: c string


【解决方案1】:

你的第一个问题在这里:

fgets(str1,MAX,stdin);

如果您在此处输入27,您的字符串缓冲区将包含"27\n"带有换行符。

由于您不想对该换行符执行任何操作,因此您应该相应地设置长度:

len1 = strlen(str1) - 1;

其次,您可以通过尽可能早地使字符串长度相同来节省大量if 语句:

if (len1 < len2) {
    strcpy(str, str1);
    memset(str1, '0', len2 - len1);
    strcpy(&(str1[len2 - len1]), str);
    len1 = len2;
} else if (len1 > len2) {
    strcpy(str, str2);
    memset(str2, '0', len1 - len2);
    strcpy(&(str2[len1 - len2]), str);
    len2 = len1;
}

完成后,您不再需要担心哪个更长,并且您的代码可以简单得多。

那么这只是(就像您所做的那样)从右边开始,添加每个数字并存储结果的问题。您只需要确保为最后的进位留出空间(按您原来的说法是多余的)。

您的代码已经这样做了,但正如建议的那样,由于预先完成了使数字长度相同的工作,因此可以大大简化它。

最终的完整代码如下,额外检查以确保输入全部为数字,进行调整以消除最终进位为零,并且变量更少:

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

#define MAX 10000

int main(void) {
    char str1[MAX], str2[MAX], str[MAX];

    printf("Enter first number  : ");
    fgets(str1, MAX, stdin);

    printf("Enter second number : ");
    fgets(str2, MAX, stdin);

    int len1 = strlen(str1) - 1;
    int len2 = strlen(str2) - 1;

    // Get both to same length quickly. We'll only use
    // len1 after that.

    if (len1 < len2) {
        strcpy(str, str1);
        memset(str1, '0', len2 - len1);
        strcpy(&(str1[len2 - len1]), str);
        len1 = len2;
    } else if (len1 > len2) {
        strcpy(str, str2);
        memset(str2, '0', len1 - len2);
        strcpy(&(str2[len1 - len2]), str);
    }

    // Now just start at right and do it digit by digit,
    // leaving room for final carry.

    int carry = 0;
    str[len1 + 1] = '\0';

    for (int i = len1; i > 0; --i) {
        // Catch any input problems.

        if (! ( isdigit(str1[i-1]) && isdigit(str2[i-1]))) {
            printf("*** ERROR: Non-digit character in number\n");
            return -1;
        }

        // Work out digit and new carry.

        int newDigit = str1[i-1] - '0' + str2[i-1] - '0' + carry;
        carry = newDigit / 10;
        newDigit = newDigit % 10;

        str[i] = newDigit + '0';
    }

    // Insert final carry if non-zero, otherwise safely move
    // all digits left (overlapping memory needs memmove).

    if (carry != 0) {
        str[0] = carry + '0';
    } else {
        memmove(str, &(str[1]), len1 + 1);
    }

    // Output the result.

    printf("The sum is %s\n", str);
    return 0;
}

【讨论】:

  • 之后,他们需要将str[len+1] = '\0'; 更改为`str[len] = '\0';`,因为他们将每个数字在循环中向右移动一个,以便为额外的数字腾出空间一开始。
猜你喜欢
  • 2020-11-15
  • 2020-04-15
  • 2022-11-02
  • 2023-01-19
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 2017-06-25
相关资源
最近更新 更多