添加用户定义的类型C ++

时间:2014-08-10 09:46:47

标签: c++ string class addition

我正在编写自己的类(称为“Longer”),这样它可以保存一个没有任何上限的数字,而不像int。我正在使用std :: string。 我在执行添加时遇到问题。

  1. 如果我只是添加两个字符串,我无法得到正确的结果。
  2. 我想过将string转换为int然后执行加法, 但长字符串无法转换为int。
  3. 如何定义自己添加两个字符串的方式以便获得所需的结果?这是代码:

    Longer.h

    #pragma once
    #include <string>
    
    class Longer
    {
    public:
       Longer(std::string number);
       Longer add(Longer num2);
       void print();
    private:
       std::string number;
    };
    

    Longer.cpp

    #include "Longer.h"
    #include <iostream>
    #include <string>
    
    Longer::Longer(std::string num): number(num)
    {
    }
    
    Longer Longer::add(Longer num2){
      return Longer(number+num2.number);
    }
    
    void Longer::print(){
    std::cout<<number<<"\n";
    }
    

    的main.cpp

    #include <iostream>
    #include "Longer.h"
    
    int main(){
    
    Longer num1("123456789101112");
    Longer num2("121110987654321");
    
    
    Longer num3 = num1.add(num2);
    num3.print();
    
    }
    

4 个答案:

答案 0 :(得分:4)

我不知道补充并不像你想的那样有效。 std::string并不打算用作任意长号的容器,这就是原因。

您必须定义自己的方式来添加&#34;两个字符串,应该包括向后迭代两个字符串(从结尾)并比较单个字符,将它们解释为数字。

答案 1 :(得分:0)

  

没有任何上限,不像int

小心这些事情。任何解决方案总会有某些上限,至少在你的机器内存耗尽时。强大的应用程序应始终进行某种错误检查。

  

如果我只是添加两个字符串,我就无法获得正确的结果。

嗯,那很明显,不是吗? String concatentation对数学语义一无所知。

  

我想过将string转换为int然后执行添加,   但是长字符串不能转换为int。

完全。将字符串内部转换为内置类型会破坏解决方案的整个目的。

  

我如何定义自己添加两个字符串的方式,以便我得到   期望的结果?

目标显然是支持大于内置类型提供的数字。

首先,您确定您的应用程序是否需要处理如此庞大的数字?即使标准int通常也应该足够,更不用说long long(自C ++ 11以来的标准,但在此之前几乎可以使用)。

或许您真正需要的是检测无效的用户输入,例如&#34; 10000000000000000000000000&#34;

字符串流为您提供此错误检测。以下是您可以使用的完整示例,包括std::numeric_limits的示例用法:

#include <iostream>
#include <stdexcept>
#include <exception>
#include <limits>

int ReadInt()
{
    int result;
    std::cin >> result;
    if (!std::cin)
    {
        throw std::runtime_error("Illegal number");
    }
    return result;
}

int main()
{
    try
    {
        std::cout << "Enter number (max: " << std::numeric_limits<int>::max() << ") > ";
        int input = ReadInt();
        std::cout << "You entered the following number: " << input << "\n";
    }
    catch (std::exception const &exc)
    {
        std::cerr << exc.what() << "\n";
    }
}

以下是我的计算机上的三个示例运行。第一个是&#34;正常&#34;数字很​​小,第二个只是可能的最大值,第三个恰好是最大可能的整数:

Enter number (max: 2147483647) > 1000
You entered the following number: 1000

Enter number (max: 2147483647) > 2147483648
Illegal number

Enter number (max: 2147483647) > 2147483647
You entered the following number: 2147483647

现在,如果真的必须在内部支持大整数,那么就不要重新发明轮子。使用 Boost.Multiprecision

http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/index.html

由于该特定库的文档可能有点难以接受,这里有一个非常简单的例子可以帮助您入门:

#include <iostream>
#include <stdexcept>
#include <exception>
#include <boost/multiprecision/cpp_int.hpp>

int main()
{
    try
    {
        boost::multiprecision::int128_t number("100000000000000000000000000000000");

        number *= 2;

        std::cout << number << "\n";
    }
    catch (std::exception const &exc)
    {
        std::cerr << exc.what() << "\n";
    }
}

这实际上会打印200000000000000000000000000000000

答案 2 :(得分:0)

#include <iostream>
using namespace std;

class Longer {
public:
    Longer(std::string number): number(number) {}
    void print() { cout << number << endl; }
    Longer add(Longer num2) {
        char over = '0'; string it;
        for(int i = number.size() - 1,
          j = num2.number.size() - 1;
          i >= 0 || j >= 0; i--, j--) {
            char one = i >= 0 ? number[i] : '0';
            char two = j >= 0 ? num2.number[j] : '0';
            char dig = one-'0' + two-'0' + over;
            over = '0'; if(dig > '9') {
                dig -= 10; over = '1'; }
            it.insert(0, 1, dig);
        }
        if(over != '0') it.insert(0, 1, over);
        return Longer(it);
    }
private:
   std::string number;
};

int main() {
    Longer num1("123456789101112"); num1.print();
    Longer num2("121110987654321"); num2.print();
    Longer num3 = num1.add(num2);   num3.print();
}

输出:

123456789101112
121110987654321
244567776755433

但如果那不是作业,请看boost::multiprecision::cpp_int

答案 3 :(得分:0)

这是一个随时可用的解决方案

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <iterator>

class Longer
{
public:
    Longer() : value( 1, '0' ) {}

    Longer (std::string s ) 
        : value( s.rbegin(), s.rend() )
    {}

    Longer( const char *s ) 
        : value( std::reverse_iterator<const char *>( s + std::strlen( s ) ),
                 std::reverse_iterator<const char *>( s ) )
    {}             

    const Longer add( const Longer &number ) const;

    void print( std::ostream &os = std::cout ) const
    {
        os << std::string( value.rbegin(), value.rend() );
    }

private:
    std::string value;
};

const Longer Longer::add( const Longer &number ) const
{
    std::pair<std::string::size_type, std::string::size_type> sizes = 
        std::minmax( this->value.size(), number.value.size() );

    std::string result;
    result.reserve( sizes.second + 1 );

    int overflow = 0;

    auto out = std::transform( this->value.begin(), 
                               std::next( this->value.begin(), sizes.first ),
                               number.value.begin(), 
                               std::back_inserter( result ),
                               [&] ( char c1, char c2 ) ->char
                               {
                                   char c = ( c1 - '0' ) + ( c2 -'0' ) + overflow;
                                   overflow = c / 10;
                                   return c % 10 + '0';
                               } );

    std::string::const_iterator first, last;

    if ( this->value.size() < number.value.size() )
    {
        first = std::next( number.value.begin(), sizes.first );
        last  = number.value.end();
    }
    else
    {
        first = std::next( this->value.begin(), sizes.first );
        last  = this->value.end();
    }

    std::transform(first, last, out,
                   [&]( char c )
                   {
                       return ( c = c - '0' + overflow ), 
                              ( overflow = c / 10 ),
                              ( c % 10 + '0' );  
                   } );

    if ( overflow ) result.push_back( overflow + '0' );

    Longer n;
    n.value = result;

    return n;
}



int main() 
{
    Longer n1( "12345678912345678" );

    n1.print();
    std::cout << std::endl;

    Longer n2( "1123" );

    n2.print();
    std::cout << std::endl;

    Longer n3 = n2.add( "877" );

    n3.print();
    std::cout << std::endl;

    Longer n4( "9999999999" );

    n4.print();
    std::cout << std::endl;

    Longer n5 = n4.add( "1" );

    n5.print();
    std::cout << std::endl;

    return 0;
}

输出

12345678912345678
1123
2000
9999999999
10000000000

考虑到在类中以相反的顺序存储字符串更方便。