【问题标题】:Infiny calculator无限计算器
【发布时间】:2014-10-16 13:51:52
【问题描述】:

我正在尝试制作一个无穷大计算器(数字大于和小于 int 大小),只使用字符串。 我正在做加法,但是当我需要将十个字符报告给下一个字符时遇到问题:比如 9 + 7 = 16 我将在当前字符中放入 6,在结果字符串的下一个字符中放入 1。 这是我的代码:

 char    *add_inf(char *nb1, char *nb2, char *rslt)
{
  if (*nb1 && *nb2)
    {
      *rslt = (*nb1 - '0' + *nb2 - '0' > 9 ? (*nb1 - '0' + *nb2 - '0') % 10 : *nb1 - '0' + *nb2 - '0') + *rslt - '0' + '0';
      if (*nb1 - '0' + *nb2 - '0' > 9)
        {
          rslt++;
          *rslt = '1'; //Here i put the next char to '1'
          add_inf(nb1 + 1, nb2 + 1, rslt);
        }
      add_inf(nb1 + 1, nb2 + 1, rslt + 1);
    }
  return (rslt);
}

对不起 - '0' 和 + '0' 的混乱,我应该在计算之前创建一个子函数并添加它。 当输入为 nb1 = "11111111" 和 nb2 = "58856557" 时,输出是正确的:

69967668

但是当我输入 nb1 = "11111114" 和 nb2 = "588856557" 时,输出是:

699676611

代替将 1 添加到下一个字符并具有:

69967671

它只是将“1”字符添加到我的结果字符串中。 想法?

【问题讨论】:

  • 一个问题:你如何让你的函数添加499999(甚至99990)?
  • 我已将我的代码减少到最低限度以便于理解。如果这是您的问题,我正在管理添加两个不同长度的字符串
  • 那么,只需在之前的字符串中添加一个虚拟的0。因此,不是添加"4""99999",而是添加"04""099999"。这解决了额外的领先 1 的问题

标签: c string


【解决方案1】:

1。我将向您展示三行等效的代码:

*rslt = (*nb1 - '0' + *nb2 - '0' > 9 ? (*nb1 - '0' + *nb2 - '0') % 10 : *nb1 - '0' + *nb2 - '0') + *rslt - '0' + '0';

*nb1 - '0' + *nb2 - '0' <= 9 时,条件的真假双方将有相同的输出。正因为如此,我们可以把这糟糕的行代码(它需要实际的时间来解析),并将其重写为更清晰:

*rslt = ((*nb1 - '0' + *nb2 - '0') % 10) + *rslt - '0' + '0';

我们还可以使用 += 运算符来清理它。

*rslt += (*nb1 - '0' + *nb2 - '0') % 10;

2。您的用户输入

不清楚你如何调用这个函数。我假设rslt'0' 的字符串,它至少比其他两个字符串一个字节。

3。溢出

您没有正确检查溢出。我们来看一个简单的案例:"54" + "65"。在第一个循环中,您将首先正确存储1 作为结果。您将携带1 到下一次迭代。

但是,在下一次迭代中,您不会使用进位位来测试您是否溢出。在这里,你的代码会说lhs + rhs == 9,所以你很好。但实际上是lhs + rhs + carry == 10

4。克拉斯·林德贝克所说的一切。

In this answer

5。返回值

大概,您总是希望返回值指向完整的rslt 字符串。你的代码不会那样做。当您溢出时,您增加rslt 的值。因此,如果前 2 个字符导致溢出,则您的返回值实际上是指向完整 rslt 字符串的第二个字符的指针。

6。因此...

因此,如果我们牢记所有这些,我们可以生成一些看起来像这样的代码。

char *add_inf(char *nb1, char *nb2, char *rslt) {
    if (*nb1 && *nb2) {
        int sum = (*nb1 - '0' + *nb2 - '0' + *rslt - '0');

        *(rslt + 0) = (sum % 10) + '0';
        if (sum / 10)
            *(rslt + 1) = (sum / 10) + '0';

        add_inf(nb1 + 1, nb2 + 1, rslt + 1);
    }

    return rslt;
}

int main() {
    char nb1[]    = "11111114";
    char nb2[]    = "58856557";
    char output[] = "000000000";

    add_inf(nb1, nb2, output);
    printf("%s\n", output);
}

得到的答案和你得到的一样破碎!这是怎么回事?

好吧,您的代码假设最低有效位在左边,最高有效位在右边。所以在你的字符串中,如果你想添加数字 100 和 200,你实际上会做inf_add("001", "002");

如果这不是你想要的,那么你需要以 reverse order 迭代字符串!

7。逆序的代码是什么样的?

嗯,递归做起来有点烦人,所以我打算用一个循环。

char *add_inf(char *nb1, char *nb2, char *rslt) {
    int len = strlen(nb1);
    int carry = 0;

    for (int i=len - 1; i >= 0; --i) {
        int sum = (nb1[i] - '0' + nb2[i] - '0' + carry);

        rslt[i] = (sum % 10) + '0';
        carry   = (sum / 10);
    }

    return rslt;
}

int main() {
    char nb1[]    = "11111114";
    char nb2[]    = "58856557";
    char output[] = "00000000";

    add_inf(nb1, nb2, output);
    printf("%s\n", output);
}

这会产生,正如您可能想要的那样:

69967671

请注意,在这段代码中,我们从字符串的末尾迭代字符串,到字符串的开头。

此外,在return 之前,我们可以测试carry 以查看它是否为非零。如果它不为零,我们可以断言或通知用户添加溢出。

【讨论】:

    【解决方案2】:

    你好像少了一个“else”:

     char    *add_inf(char *nb1, char *nb2, char *rslt)
    {
      if (*nb1 && *nb2)
        {
          *rslt = (*nb1 - '0' + *nb2 - '0' > 9 ? (*nb1 - '0' + *nb2 - '0') % 10 : *nb1 - '0' + *nb2 - '0') + *rslt - '0' + '0';
          if (*nb1 - '0' + *nb2 - '0' > 9)
            {
              rslt++;
              *rslt = '1'; //Here i put the next char to '1'
              add_inf(nb1 + 1, nb2 + 1, rslt);
            }
          else  // sum is less than 10
              add_inf(nb1 + 1, nb2 + 1, rslt + 1);
        }
      return (rslt);
    }
    

    我不明白顺序 - 只有当您进行加法时字符串以相反的顺序存储时,代码才应该起作用。

    【讨论】:

    • 嗯,你可能适合这个订单,需要试试!但我觉得我不需要 else 因为我回调 add_inf if *nb1 + *nb2 > 9
    • 避免“数组索引越界”也很好(例如,可能通过检查和调整数组大小)。
    • @Robin 因为在第一个add_inf 之后没有return,所以一旦从递归返回,代码将再次调用add_inf。 else 是防止这种情况发生的必要条件。
    猜你喜欢
    • 2015-01-06
    • 2015-10-02
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 2020-09-09
    • 2012-02-04
    • 2020-01-20
    相关资源
    最近更新 更多