【问题标题】:Why the simple multiplication would result in some garbled characters?为什么简单的乘法会导致一些乱码?
【发布时间】:2021-09-12 09:33:48
【问题描述】:

我尝试设计一个程序来实现两个大整数之间的乘法(使用 C++)。但是在我完成之后,我发现如果我通过命令参数输入两个整数,结果有时会很奇怪,有时会正确。请帮我找出原因并告诉我如何解决它。谢谢(实现两个大整数相乘功能的主要函数是mul())。

#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std;

void mul(char *c1, char *c2, int len1, int len2);

void printArr(char *c1, char *c2, int len1, int len2);

int main(int argc, char **argv)
{
    if (argv[1] != NULL)
    {
        char cArr1[500], cArr2[500];
        for (int i = 0; i < strlen(argv[1]); i++)
        {
            cArr1[i] = argv[1][i];
        }
        for (int i = 0; i < strlen(argv[2]); i++)
        {
            cArr2[i] = argv[2][i];
        }
        int len1 = strlen(cArr1);
        int len2 = strlen(cArr2);
        printArr(cArr1, cArr2, len1, len2);
        (len1 > len2) ? mul(cArr1, cArr2, len1, len2) : mul(cArr2, cArr1, len2, len1);
        exit(100);
    }
    while (true)
    {
        cout << "Please input two integers" << endl;
        char cArr1[500], cArr2[500];
        cin >> cArr1;
        if (cArr1[0] == 'q' && cArr1[1] == 'u' && cArr1[2] == 'i' && cArr1[3] == 't')
        {
            exit(1000);
        }
        cin >> cArr2;
        int parity = 0;
        int len1 = strlen(cArr1);
        int len2 = strlen(cArr2);
        printArr(cArr1, cArr2, len1, len2);
        if (cArr1[0] == '-')
        {
            for (int i = 1; i < len1; i++)
            {
                cArr1[i - 1] = cArr1[i];
            }
            parity++;
            len1--;
        }
        if (cArr2[0] == '-')
        {
            for (int i = 1; i < len2; i++)
            {
                cArr2[i - 1] = cArr2[i];
            }
            parity++;
            len2--;
        }
        bool isDigit = true;
        for (int i = 0; i < len1; i++)
        {
            if (!isdigit(cArr1[i]))
            {
                isDigit = false;
            }
        }
        for (int i = 0; i < len2; i++)
        {
            if (!isdigit(cArr2[i]))
            {
                isDigit = false;
            }
        }
        if (!isDigit)
        {
            cout << "\rInvalid input. Try again" << endl;
            continue;
        }
        if (parity % 2 != 0)
        {
            cout << "-";
        }
        (len1 > len2) ? mul(cArr1, cArr2, len1, len2) : mul(cArr2, cArr1, len2, len1);
    }
}

void mul(char *bigger, char *smaller, int bigLen, int smallLen)
{
    int *bigNum = new int[bigLen];
    int *smallNum = new int[smallLen];
    for (int i = 0; i < bigLen; i++)
    {
        bigNum[i] = bigger[bigLen - i - 1] - '0';
    }
    for (int i = 0; i < smallLen; i++)
    {
        smallNum[i] = smaller[smallLen - i - 1] - '0';
    }
    int res[30];
    for (int i = 0; i < 30; i++)
    {
        res[i] = 0;
    }
    for (int i = 0; i < smallLen; i++)
    {
        for (int j = 0; j < bigLen; j++)
        {
            res[i + j] += bigNum[j] * smallNum[i];
        }
    }
    for (int i = 0; i < bigLen + smallLen; i++)
    {
        int digit = res[i] % 10;
        int carry = res[i] / 10;
        res[i] = digit;
        res[i + 1] += carry;
    }
    bool null = false;
    for (int i = bigLen + smallLen - 1; i >= 0; i--)
    {
        if (res[i] != 0 && res[i + 1] == 0)
        {
            null = true;
        }
        if (null)
        {
            cout << res[i];
        }
    }
    cout << endl;
}

void printArr(char *c1, char *c2, int len1, int len2)
{
    for (int i = 0; i < len1; i++)
    {
        cout << c1[i];
    }
    cout << " * ";
    for (int i = 0; i < len2; i++)
    {
        cout << c2[i];
    }
    cout << " = ";
}

【问题讨论】:

  • 请包括示例输入和示例输出。 int res[30]; 看起来很容易溢出
  • 你为什么不使用 std::stringstd::vector ?它们具有边界检查的元素访问权限,这有助于消除最常见的错误
  • 一个可能的问题是:当你将argv[1]和argv[2]复制到cArr1和cArr2时,它不包括终端'\0',那么len1和len2的计算不会总是正确取决于内存内容的状态。
  • 很明显,您使用的是 C 习语,但使用的是 C++。您应该尝试忘记您的 C 背景,第一步是使用标准库容器:std::array 和/或 std::vector
  • 示例:输入“23”和“4”bu 命令行参数,有时会打印“23 * 4 = 92”,有时会打印“23�o� * 4 = 4-4-14 -56 英寸

标签: c++ calculator


【解决方案1】:

只需将您的 char 数组初始化为空数组:

char cArr1[500] = {};
char cArr2[500] = {};

然后,为了清楚起见,将参数的长度分配给两个整数,将它们强制转换,因为编译器可能会警告您 size_tint 之间的不兼容。

int lenArg1 = 0;
int lenArg2 = 0;

lenArg1 = (int)strlen ( argv[1] );
lenArg2 = (int)strlen ( argv[2] );

然后,打印长度 len1len2 仅用于调试目的:

int len1 = strlen ( cArr1 );
int len2 = strlen ( cArr2 );

cout << "len1 >> " + to_string(len1) <<endl;
cout << "len2 >> " + to_string(len2) <<endl;

事实上,正如@Kevin SUN 所提到的,您的参数读取步骤可能缺少空字符,但是,在运行一些测试之后,它似乎只需初始化 char 数组就可以正常工作。

另外,如 cmets 中所述,您需要增加为 res 数组保留的大小,我将其增加到 500

使用g++ -Wall main.cpp -o calc.exe 编译并运行:calc 10 100

如果没有初始化,您会遇到以下问题:

初始化后,输出正常:

【讨论】:

  • 能否请您告诉我为什么用数组初始化解决了这个问题?
  • 如果您注意到,如果不初始化 char 数组,则第一个数组的长度是错误的(输入为:calc 10 100)。我相信,初始化既保留内存又删除了这些内存位置中包含的垃圾。请记住,系统必须解析空字符以指示字符串的结尾。实际上,只有当输入的第一个数字的长度大于 1 个字符时才会出现原始代码的问题(试试看)。如果我的回答有帮助,请将其标记为解决方案;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多