aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bigint.cpp42
-rw-r--r--bigint.h1
2 files changed, 37 insertions, 6 deletions
diff --git a/bigint.cpp b/bigint.cpp
index 98846e0..72a882b 100644
--- a/bigint.cpp
+++ b/bigint.cpp
@@ -1,4 +1,5 @@
#include <iomanip>
+#include <sstream>
#include <stdexcept>
#include <cctype>
#include <cassert>
@@ -15,6 +16,10 @@ Bigint Bigint::two(2);
Bigint::Bigint()
:sign(1){}
+Bigint::Bigint(const string &repr){
+ stringstream(repr)>>*this;
+}
+
Bigint::Bigint(slongdigit_t v)
:digits(1,abs(v)),sign(v>=0?1:-1){
static_assert(sizeof(longdigit_t)==2*sizeof(digit_t),
@@ -573,23 +578,48 @@ istream& operator>>(istream &is,Bigint &b){
while(isspace(is.peek()))is.get();
if(!is)return is;
b.digits.resize(0);
- b.sign=1;
- Bigint ten(10);
+ if(is.peek()=='-'){
+ b.sign=-1;
+ is.get();
+ } else b.sign=1;
bool acted=false;
+ if(is.peek()=='0'){
+ is.get();
+ if(is.peek()=='x'){
+ is.get();
+ acted=false;
+ while(true){
+ char c=is.peek();
+ if(!isdigit(c)&&(c<'a'||c>'f')&&(c<'A'||c>'F'))break;
+ acted=true;
+ is.get();
+ if(!is)break;
+ int n;
+ if(c<='9')n=c-'0';
+ else if(c<='F')n=c-'A'+10;
+ else n=c-'a'+10;
+ b<<=4;
+ b+=n;
+ }
+ if(!acted)is.setstate(ios_base::failbit);
+ b.normalise();
+ b.checkconsistent();
+ return is;
+ } else acted=true;
+ }
+ Bigint ten(10);
while(true){
char c=is.peek();
if(!isdigit(c))break;
acted=true;
is.get();
- if(!is){
- b.checkconsistent();
- return is;
- }
+ if(!is)break;
b*=ten;
b+=c-'0';
// cerr<<"b="<<b<<endl;
}
if(!acted)is.setstate(ios_base::failbit);
+ b.normalise();
b.checkconsistent();
return is;
}
diff --git a/bigint.h b/bigint.h
index bd15fd9..4d6c980 100644
--- a/bigint.h
+++ b/bigint.h
@@ -32,6 +32,7 @@ public:
Bigint();
Bigint(const Bigint&)=default;
Bigint(Bigint&&)=default;
+ explicit Bigint(const std::string&);
explicit Bigint(sdigit_t);
explicit Bigint(digit_t);
explicit Bigint(slongdigit_t);