我正在编写自己的类(称为“Longer”),这样它可以保存一个没有任何上限的数字,而不像int。我正在使用std :: string。 我在执行添加时遇到问题。
如何定义自己添加两个字符串的方式以便获得所需的结果?这是代码:
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();
}
答案 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
考虑到在类中以相反的顺序存储字符串更方便。