存储在字符串对象中的HugeInteger对象的数字

时间:2015-05-16 23:52:51

标签: c++ string

我正在研究一个巨大的整数问题,我必须创建一个HugeInteger类,其中数字将存储在字符串对象中,而不是固定(静态)大小的无符号短裤数组。我坚持如何实现这一点。当我运行程序时,我为我的HugeInteger对象输入值,但之后没有任何内容显示。会感激一些帮助。提前致谢。

以下是我到目前为止的源代码。

HugeInteger.h

#include <iostream>
#include <array>
#include <string>

class HugeInteger
{
    // need to offer friendship to these 2 functions
    friend std::istream & operator >> (std::istream & src, HugeInteger & value);
    friend std::ostream & operator << (std::ostream & dest, const HugeInteger & value);

public:
    //ctor that converts a "long long" into a HugeInteger
    HugeInteger(long long value = 0LL); //0LL is constant literal value 0
    //   of type long long
    //ctor that converts a string into a HugeInteger
    HugeInteger( char *str);
    //Convert a string into a HugeInteger
    void input( char *str);

private:
    bool negative;  // will be true if number is negative
    std::string hugeInt; // each digit is stored in a string object
};

//overloads the << and >> operators for the HugeInteger class
std::istream & operator >> (std::istream & src, HugeInteger & value);
std::ostream & operator << (std::ostream & dest, const HugeInteger & value);

HugeInteger.cpp

#include "HugeInteger.h"

#include <iostream>
using namespace std;

// ctor converts a long long into a HugeInteger
HugeInteger::HugeInteger(long long value)
{
    // set all MaxDigit digits to zero to start
    this->negative = false;
    if (value < 0LL){ // 0LL is constant literal 0 of type long long
        this->negative = true;
        value = -value; // make the value positive                  
    }

    unsigned int i = 0;
    for (; i < hugeInt.size(); i++)
    {
        this->hugeInt[i] = '0';
    }
    this->hugeInt[i] = '\0';

    // convert individual digits of input value into a HugeInteger
    for (unsigned int j = hugeInt.size() - 1; j >= 0 && value != 0LL; j--)
    {
        short result = value % 10;
        char c = (char)result;
        this->hugeInt[j] = c;
        value /= 10;
    }

    // test to make sure that HugeInteger was able to contain value

    if (value != 0LL){
        *this = 0LL; // set to -0, to signal overflow
        this->negative = true; //   Possibly should increase value assigned
    }                          //   to MaxDigit to fix this problem.
}

// converts string into a HugeInteger object
HugeInteger::HugeInteger(char *str)
{
    this->input(str); //See HugeInteger::input() method below
}

void HugeInteger::input( char *str)
{
    // assume positive for now
    this->negative = false;

    // init. to all zeros first
    unsigned int i = 0;

    cin.getline(str, sizeof str);
    cin.sync();
    cin.clear();

    while (i < strlen(str) - 1)
    {
        if (isdigit(str[i]))
        {
            this->hugeInt[i] = str[i];
            i++;
        }
    }

istream & operator>>(istream & input, HugeInteger & value)
{
    char inputString[1002];
    input >> inputString;
    value.input(inputString);
    return input;
}

ostream & operator << (ostream & output, const HugeInteger & value)
{
    // find first non-zero digit
    unsigned int i = 0;
    while (i < value.hugeInt.size()){
        if (value.hugeInt[i] != '0'){
            break;
        }
        ++i;
    }

    // if all zeros, just output a single 0
    if (i == 40)
    {
        cout << '0';
        return output;
    }

    // check if we need to ouput a negative sign
    if (value.negative){
        cout << '-';
    }

    // output remaining digits
    for (; i < value.hugeInt.size(); i++)
    {
        cout << value.hugeInt[i];
    }

    return output;
}

MainProg.cpp

#include "HugeInteger.h" // include definiton of class HugeInteger

using namespace std;

    int main()
    {
        HugeInteger A, B, C, D;

        // input value for A & B
        cout << "****** Test << & >> operators ******\n\n";
        cout << "Input values for A and B: ";
        cin >> A >> B;
        cout << "\nA = " << A << "\nB = " << B;
    system("pause");

        return 0;
    } // end main

2 个答案:

答案 0 :(得分:1)

您的代码存在一些问题,但最明显的是您的输入功能。

首先,为什么HugeInteger::input需要知道如何检索输入?不需要cin或任何I / O - 它的工作就是单独使用char *指针,然后循环创建hugeInt字符串。

因此,应删除以下行:

cin.getline(str, sizeof str);
cin.sync();
cin.clear();

下一个问题是实际循环。它有几个问题。

首先,无论字符是否为数字,您都应该递增i。否则,如果字符不是数字,您将最终处于无限循环中。

其次,当您构建hugeInt字符串时,您应该将字符连接到字符串上。当前代码导致未定义的行为,因为您正在访问hugeInt[i],而hugeInt是一个空字符串,因此没有i条目。

所以那里的变化就是这样:

while (i < strlen(str) - 1)
{
    if (isdigit(str[i]))
        this->hugeInt += str[i];
    i++;
}

现在,更好的实现方法是让input获取std::string,而不是char *。现在,总函数将被重写:

void HugeInteger::input(const std::string& str)
{
    // assume positive for now
    this->negative = false;

    // init. to all zeros first
    unsigned int i = 0;

    this->hugeInt.clear();
    while (i < str.size())
    {
        if (isdigit(str[i]))
            this->hugeInt += str[i];
        i++;
    }
}

最后一个问题是您的operator >>。没有必要将自己限制为1002个字符。只需输入std::string

istream & operator>>(istream & input, HugeInteger & value)
{
    string inputString;
    input >> inputString;
    value.input(inputString);
    return input;
}

完成这些更改后,示例正确运行:http://ideone.com/F47TEV

编辑:

使用STL算法函数提取数字并附加到字符串的另一种方法如下:

void HugeInteger::input(std::string str)
{
    // assume positive for now
    this->negative = false;
    str.erase(std::remove_if(str.begin(), str.end(), [](char ch) 
                { return !isdigit(ch);}), str.end());
    hugeInt = str;
}

std::remove_if是稳定的,因此数字的相对顺序不会改变。另请注意,我们传递值,因为这为编译器(如果它的C ++ 11)提供了一个很好的机会来优化传递的副本(而不是在函数内部创建自己的副本)。

答案 1 :(得分:0)

  

您当前的代码导致未定义的行为,因为您正在访问hugeInt [i],而hugeInt是一个空字符串,因此没有i条目。

添加到此,行

for (; i < hugeInt.size(); i++)

 for (unsigned int j = hugeInt.size() - 1; j >= 0 && value != 0LL; j--)

永远不会执行,因为hugeInt.size()将为0并且永远不会满足for循环条件

相关问题