2015-04-12 58 views
-4

我写了一个非常大的数字加法函数,当它被调用时,程序崩溃。我假设它与携带有关。这里是代码:大数加法函数崩溃程序

char * bigadd(char a[], char b[]){ 

int i, temp; 
char useadd[MAX]; 
char usea = strrev(a); 
char useb = strrev(b); 
char ret[strlen(useadd)]; 
char *pa, *pb, *padd; 

padd = &useadd; 
pa = &usea; 
pb = &useb; 

while(*pa != '\0' && *pb != '\0'){ 

    if(atoi(*pa) + atoi(*pb) + temp > 9){ 

     if(temp + atoi(*pa) + atoi(*pb) < 20){ 
      temp = 1; 
      *padd = atoi(*pa) + atoi(*pb) - 10; 
     } 
     else{ 
      temp = 2; 
      *padd = atoi(*pa) + atoi(*pb) - 20; 
     } 
    } 
    else{ 
     *padd = atoi(*pa) + atoi(*pb); 
     temp = 0; 
    } 
    ++padd; 
    ++pa; 
    ++pb; 

} 

i = 0; 
while(useadd[i] != '\0'){ 
    ret[i] = useadd[i]; 
    ++i; 
} 
return strrev(ret); 
} 

感谢您的所有帮助。如果这最终成为一个愚蠢的错误,我很抱歉。

+1

'strrev()'返回一个指针,所以'字符* USEA = strrev(a)中;',请注意加入'',具有相同'useb'。 –

+1

'strlen(useadd)' - 使用未初始化的字符串,无论如何它应该是'char ret [1 + strlen(useadd)];'。对一个非常长的数字字符串使用'atoi()'是不行的。 –

+0

...并且最终返回一个指向'ret'的指针也不起作用,因为'ret'是堆栈中的一个本地变量,只要函数退出就会被销毁。 –

回答

0

你的程序有这么多问题!

char * bigadd(char a[], char b[]){ 
    int i, temp; 
    char useadd[MAX]; // MAX might not be large enough 
    char usea = strrev(a); // should not modify argument a 
          // strrev() is not standard C undefined on my system 
          // if defined, it returns char*, not char 
    char useb = strrev(b); // see above 
    char ret[strlen(useadd)]; // useadd is uninitialized -> undefined behaviour 
    char *pa, *pb, *padd; 

    padd = &useadd; // & is incorrect, useadd is an array 
    pa = &usea;  // same as above 
    pb = &useb;  // idem 
        // forgot to initialize temp to 0 
    while(*pa != '\0' && *pb != '\0'){ 
     if(atoi(*pa) + atoi(*pb) + temp > 9){ // atoi converts a string, not a char 
     if(temp + atoi(*pa) + atoi(*pb) < 20){ // same... sum cannot exceed 19 
      temp = 1; 
      *padd = atoi(*pa) + atoi(*pb) - 10; // atoi... 
     } 
     else{ // never reached 
      temp = 2; 
      *padd = atoi(*pa) + atoi(*pb) - 20; // atoi... 
     } 
     } 
     else{ 
     *padd = atoi(*pa) + atoi(*pb); // same atoi problem 
     temp = 0; 
     } 
     ++padd; 
     ++pa; 
     ++pb; 
    } 
    // if a and b have a different size, loop fails to copy digits and propagate carry 
    // if temp is not 0, you forget to add the leading '1' 
    // trailing '\0' is not set 

    i = 0; 
    while(useadd[i] != '\0'){ // undefined behaviour, '\0' not set. 
     ret[i] = useadd[i]; 
     ++i; 
    } 
    // forgot to set the final '\0' 
    // why not use strcpy? 
    return strrev(ret); // strrev not defined. 
         // if defined, returning ret, address of local array 
} 

下面是一个完整重写:

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

char *bigadd(const char a[], const char b[]) { 
    int ia = strlen(a); 
    int ib = strlen(b); 
    int size = 2 + (ia > ib ? ia : ib), ic = size - 1, temp = 0; 
    char *res = malloc(size); 

    if (res) { 
     res[--ic] = '\0'; 
     while (ia + ib) { 
      if (ia > 0) temp += a[--ia] - '0'; 
      if (ib > 0) temp += b[--ib] - '0'; 
      res[--ic] = '0' + temp % 10; 
      temp /= 10; 
     } 
     if (temp) { 
      memmove(res + 1, res, size - 1); 
      *res = '1'; 
     } 
    } 
    return res; 
} 

int main(int argc, char *argv[]) { 
    for (int i = 1; i + 1 < argc; i += 2) { 
     char *res = bigadd(argv[i], argv[i+1]); 
     printf("%s + %s = %s\n", argv[i], argv[i+1], res); 
     free(res); 
    } 
}