【问题标题】:Return the result of sum of character arrays返回字符数组总和的结果
【发布时间】:2010-09-21 06:24:22
【问题描述】:

最近在一次采访中,有人问我一个问题,要编写一个函数,该函数将两个字符数组(整数)作为输入并返回输出字符数组。

函数签名:

char* find_sum(char* a, char* b)

如何解决这个问题?

示例场景:

find_sum("12345","32142") = "44487"

注意:

位数可以很多(1-100)。

【问题讨论】:

  • 你不能将它们转换为整数,将它们相加并将结果转换回字符串吗?
  • 每个输入被视为单个数字还是单个数字的数组(例如,“19”+“19”应该给出“218”还是“38”)?
  • 如何解决这个问题?通过提问......如果数组的长度不同怎么办?溢出(“99”和“33”)呢?谁负责释放内存?它可以使用长度有限的静态数组吗?...
  • 现在这对面试官来说是一个相当不错的采访.. :)
  • 请注意,在最坏的情况下,返回的 char 与最长 char + 1 的长度相同,即 find_sum("123..n", "123..m") where n> m 的长度为 (n+1)。这将允许您分配答案所需的确切长度。

标签: c++ c arrays pointers


【解决方案1】:

您可以使用 char 数组方法添加大量数字。但是您需要在每次使用后删除 char* 或使用一些智能指针。

 char* find_sum(char* a, char* b) {
    int lenA = strlen(a), lenB = strlen(b);
    int max = lenA > lenB ? lenA : lenB; // Get the max for allocation
    char* res = (char*)malloc (max+2);
    memset(res, '0', max +1);      // set the result to all zeros
    res[max+1] = '\0';
    int i=lenA - 1, j = lenB - 1, k = max;
    for (; i >= 0 || j >=0; --i, --j, --k) {
            int sum = 0;
            if (i >= 0 && j>=0)
                    sum = a[i] - '0' + b[j] - '0' + res[k] - '0' ;  // add using carry
            else if (j >= 0)
                    sum =  b[j] - '0' + res[k] - '0' ;     // add the carry with remaining
            else if (i >= 0)
                    sum =  a[i] - '0' + res[k] - '0' ;
            res[k] = sum % 10 + '0';
            res[k-1] = sum / 10 + '0';
    }
    return res;
 }

 int main() {
    printf (" sum = %s ", find_sum("12345432409240242342342342234234234", "9934563424242424242423442424234"));
    return 0;
 }

注意:函数的前提是输入的字符数组只能包含数字。

【讨论】:

  • 我认为你应该打电话给find_sum,而不是add
  • 您需要为溢出分配 (max + 2):9 + 3 = 12res[max+1] = '\0'; 也会尝试写入不属于该对象的内存。
【解决方案2】:

最明显的答案是在内部使用atoisprintf 之类的东西将数字转换为整数,求和并将响应作为char* 返回但是这里重要的不是什么面试官在问,但是为什么。

根据我的经验,面试官可能不希望你写一个涵盖所有角度的解决方案的嗡嗡声。他们最可能想要的是最常见的方法是什么,以及这种功能的可能限制是什么。即:

  1. 如果输入的数字不是整数会怎样? (例如 13.245、2.3E+7)

  2. 如果您的“数字”根本不是数字会怎样?

  3. 如果输入的整数非常大,会发生什么? (即~2^31)

  4. 如何检测错误以及如何报告。

  5. 如何为结果字符串分配内存?

  6. 内存分配对调用代码意味着什么?

  7. 函数的效率是多少?如何提高效率?

通过这种方式,面试官想探究您在批评解决问题的方法方面的经验。自然,有很多方法可以解决这个问题。一些方法有副作用,但在某些情况下,这些副作用(即整数溢出)可能不是很重要。

编码通常是综合解决方案与可以快速生成(因此成本更低)之间的权衡这些问题让面试官了解您对质量的理解 - 也就是说,您是否可以设计适合的东西出于目的,功能强大,但不会花费太长时间来组合 - 以及您必须识别/解决常见错误的经验。

【讨论】:

    【解决方案3】:

    你没有提到任何关于不使用任何外部命令的事情。

    我们可以在具有bc 命令的机器上轻松完成此操作。您可以添加任意位数:

    $ echo "99999999999999999999999999999999+1" | bc
    100000000000000000000000000000000
    $ 
    

    我们在 C 程序中将其称为 bc。我们需要构建正确的命令行为

    echo "n1+n2" | bc
    

    然后使用 popen 读取其结果。下面是执行此操作的函数。该代码缺少许多错误检查。

    char* find_sum(char* a, char* b) {
    
            int l1 = strlen(a),l2 = strlen(b);
            int cmdLen = l1 + l2 + 30; // 30 to accomodate echo,bc and stuff.
    
            char *cmd = malloc(cmdLen);    
            snprintf(cmd,cmdLen,"echo \"%s+%s\"|bc",a,b);
    
            FILE *fp = popen(cmd, "r");
    
            int max = (l1 > l2) ? l1:l2;
            max += 2; // one for additional digit, one for null.
            char *result = malloc(max);
    
            fgets(result, max, fp);
            return result;
    }
    

    Working link

    【讨论】:

      【解决方案4】:

      答案可能是你要问返回的是什么?这是一个应该由用户释放的内存分配字符串,还是一个在下次调用函数时被覆盖的静态内存位置?

      char* find_sum(char* a, char* b) {
          static char buf[MAX_STRING];
          ...
          return buf;
      }
      

      char* find_sum(char* a, char* b) {
          char *buf = malloc(MAX_STRING*sizeof(char));
          ...
          return buf;
      }
      

      给出这个答案向面试官展示了你对 C 的了解不仅仅是制作算法。 (作为一个侧面节点:它还说明了为什么像 java 这样的语言在这些情况下大放异彩,因为垃圾收集负责释放缓冲区)。

      【讨论】:

      • 我也会让调用者负责发送目标缓冲区:char *school_sum(char *dst, size_t len, const char *a, const char *b);
      • @prng,是的,这也是我的解决方案,但严格来说我们会更改分配。
      【解决方案5】:

      只要记住你在二年级时是如何在纸上做加法的。

      【讨论】:

        【解决方案6】:
        #include <stdio.h>
        #include <string.h>
        
        char *sum(char *a,char *b);
        
        int main()
        {
                char a[] = "100";
                char b[] = "300";
                char *c;
                c = sum(a,b);
                printf("%s",c);
        }
        
        char *sum(char *a,char *b)
        {
                int x,y,z,z2,zLen;
                char *result;
                x = atoi(a);
                y = atoi(b);
                z = x + y;
                z2 = z;
                /* Determine the length of the string now! */
                for(zLen = 1; z > 0 || z < 0; zLen++)
                        z/=10;
                result = (char *)malloc(zLen*sizeof(char)+1);
                sprintf(result,"%d\0",z2);
                return result;
        }
        

        快速而肮脏的实施。请注意,我没有释放内存,这不是“理想的”。提到这里没有发生错误检查,也没有释放内存,这在实际情况下远非理想,将为您带来额外的布朗尼积分。

        Online Version of Code

        【讨论】:

        • +1,也许不是完美的答案,但它展示了如何做到这一点。我想关于内存分配和错误检查的问题取决于这个面试问题的“复杂程度”。
        • 你不会得到一个错误的结果,因为当你确定字符串的长度时,你做的 z/=10 等于 z=z/10,还是我错了?所以你的结果应该总是 0?
        【解决方案7】:

        一些答案​​提到了atoiitoa 函数的使用。

        atoi 返回int。您的数字可能不适合整数数据类型。

        您可以尝试使用atol(返回long int)或atoll(返回long long int)来缓解问题(虽然不是完全)。

        另外,itoa 不是标准库函数,因此可能并非在所有系统上都可用。

        【讨论】:

          【解决方案8】:

          这是另一种方法。不,我不喜欢 find_sum 的原型。我非常喜欢它

          char *find_sum(char *dst, size_t len, const char *a, const char *b);
          

          让调用者负责管理资源。

          ab 是由 1 个或多个数字组成的字符串(并且只有数字);结果应该由调用者释放。使用无效输入调用 find_sum 会导致 UB :-)

          char *find_sum(char *a, char *b) {
            char *res;
            int alen, blen, rlen;
            int carry;
          
            alen = strlen(a);
            blen = strlen(b);
            rlen = 1 + ((alen > blen) ? alen : blen);
            res = malloc(1 + rlen);
            if (res) {
              int oldlen = rlen;
              res[rlen] = 0;
              carry = 0;
              while (rlen) {
                int tmp;
                if (alen && blen) tmp = a[--alen] - '0' + b[--blen] - '0';
                else if (alen) tmp = a[--alen] - '0';
                else if (blen) tmp = b[--blen] - '0';
                else tmp = 0;
                tmp += carry;
                res[--rlen] = '0' + tmp % 10;
                carry = tmp / 10;
              }
              if (res[0] == '0') memmove(res, res+1, oldlen);
            }
            return res;
          }
          

          在 ideone (http://ideone.com/O2jrx) 上有该函数的工作版本。

          【讨论】:

            【解决方案9】:

            itoa(atoi(a) + atoi(b), t, 10); 如果你想偷懒,这里 t 是 char[MAX_NUMBER_OF_DIGITS]

            真正的问题与其他用户提到的输出数组有关。

            【讨论】:

            • +1:这应该是你的初始答案 - 跟随哪个面试官希望你做@allajunaki 和@codaddict 正在做的事情:)
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-22
            • 2021-12-16
            • 2023-04-01
            • 2017-05-26
            • 2015-05-18
            • 2021-10-09
            相关资源
            最近更新 更多