This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
converting string to int in C++
I have tried include stdlib.h but it doesn't work.
in c++98 you can do
std::string str("1234");
int i;
std::stringstream ss(str);
ss >> i;
in c++11 you should do:
std::string str("1234");
int i=std::stoi(str);
A more C++-way of doing this:
#include <sstream>
#include <string>
// Converts a string to anything.
template<typename T>
T to(const std::string& s)
{
std::stringstream ss(s);
T ret;
ss >> ret;
return ret;
}
// And with a default value for not-convertible strings:
template<typename T>
T to(const std::string& s, T default_)
{
std::stringstream ss(s);
ss >> default_;
return default_;
}
Use it as follows:
int i = to<int>("123");
assert(i == 123);
int j = to<int>("Not an integer", 123);
assert(j == 123);
And extend it to support arbitrary types of yours:
struct Vec3 {float x, y, z;};
template<class T>
T& operator>>(T& f, Vec3& v) {
f >> v.x >> v.y >> v.z;
return f;
}
// Somewhere else:
Vec3 v = to<Vec3>("1.0 2.0 3.0");
Related
I would like to create an std::array from a std::string.
For this, I would like to overload the operator>>.
I have the following test case:
std::istream& operator>>(std::istream& is, const std::array<double, 3>& a)
{
char p1, p2;
is >> p1;
// if fail warn the user
for (unsigned int i = 1; i < a.size(); ++i)
{
// something to ignore/ check if numeric
}
is >> p2;
// if fail warn the user
return is;
}
int main()
{
std::string a = "[1 2 3]";
std::array<double, 3> arr;
std::istringstream iss (a);
iss >> arr;
return 0;
}
I would like for the operator to check if the characters [and ] are in the correct place and to construct the array with the elements inside.
How can I do checks if the extraction was successfull? How can I check the string between the parenthesis is numeric and if so construct my array from it?
Kind regards
I'd add a helper class that checks for a certain character in the stream and removes it if it's there. If it's not, sets the failbit.
Example:
#include <cctype>
#include <istream>
template <char Ch, bool SkipWhitespace = false>
struct eater {
friend std::istream& operator>>(std::istream& is, eater) {
if /*constexpr*/ (SkipWhitespace) { // constexpr since C++17
is >> std::ws;
}
if (is.peek() == Ch) // if the expected char is there, remove it
is.ignore();
else // else set the failbit
is.setstate(std::ios::failbit);
return is;
}
};
And it could then be used like this:
std::istream& operator>>(std::istream& is, std::array<double, 3>& a) {
// use the `eater` class template with `[` and `]` as template parameters:
return is >> eater<'['>{} >> a[0] >> a[1] >> a[2] >> eater<']'>{};
}
int main() {
std::string a = "[1 2 3]";
std::array<double, 3> arr;
std::istringstream iss (a);
// iss.exceptions(std::ios::failbit); // if you want exceptions on failure
if(iss >> arr) {
std::cout << "success\n";
} else {
std::cout << "fail\n";
}
}
Demo where , is used as separator in the input.
As an old c99 person, I was often stubled upon the curly brakets initialization. In the `initializer_list`, I have to use {r, i} for a complex number. On the other hand, I have to use (r, i) for `complex` in the istream field. Here, I cut a part of my class that is able to run and give examples under codeblock 20.03 with MinGW 8.1.0.
#ifndef __tMatrix_class__
#define __tMatrix_class__
#include <iostream>
#include <initializer_list>
#include <iomanip>
#include <complex>
#include <sstream>
template <typename T> class tMatrix
{
public:
T *ptr;
int col, row, size;
inline T* begin() const {return ptr;}
inline T* end() const {return this->ptr + this->size;}
inline T operator()(const int i, const int j) const { return ptr[i*col+j]; } // r-value
inline T&operator()(const int i, const int j) { return ptr[i*col+j]; } //l-value
inline tMatrix(): col{0}, row{0}, size{0}, ptr{0} {;}
tMatrix(const int i, const int j): col(j), row(i), size(i*j) {
ptr = new T [this->size] ; }
tMatrix(const std::initializer_list< std::initializer_list<T> > s):tMatrix<T>(s.size(), s.begin()->size())
{
int j = 0;
for (const auto& i : s) { std::copy (i.begin(), i.end(), ptr + j*col); ++j ; }
}
tMatrix(const tMatrix<T>&a) : tMatrix<T>(a.row, a.col)
{
std::copy(a.begin(), a.end(), this->ptr);
}
tMatrix<T>& operator=(tMatrix<T>&&a)
{
this->col = a.col;
this->row = a.row;
delete [] this->ptr;
this->ptr = a.ptr;
a.ptr = nullptr;
return *this;
}
tMatrix<T>& operator=(const tMatrix<T>&a)
{
if (col==a.cpl && row==a.row) std::copy(a.begin(), a.end(), this->ptr);
else { tMatrix<T>&&v(a); *this = std::move(v);}
return *this;
}
tMatrix<T>& operator=(const std::initializer_list<std::initializer_list<T> > a)
{
tMatrix<T> &&v = a;
*this = std::move(v);
return *this;
}
~tMatrix() {delete [] this->ptr;}
void operator<<(const char*s)
{
std::stringstream ss;
ss.str(s);
for (int i=0; i<this->size; i++){
if (ss.good()) ss >> this->ptr[i];
else return;
}
}
}; //end of class tMatrix
template <typename X> std::ostream& operator<<(std::ostream&p, const tMatrix<X>&a)
{
p << std::fixed;
for (int i=0; i<a.row; i++) {
for (int j=0; j <a.col; j++) p << std::setw(12) << a(i, j);
p << std::endl;
}
return p;
}
using CMPLX = std::complex<double>;
using iMatrix = tMatrix<int>;
using rMatrix = tMatrix<double>;
using cMatrix = tMatrix< CMPLX >;
#endif
int main()
{
cMatrix cx(2,2);
cx = { { {1,2},{3,4} }, { {5,6}, {7,8} } };
std::cout << cx << std::endl;
cx << "(1,2) (3,4)";
std::cout << cx << std::endl;
return 0;
}
The above code renders correct format of complex number, and prints
$ ./ttt_mtx_init_fin_tmp.exe
(1.000000,2.000000)(3.000000,4.000000)
(5.000000,6.000000)(7.000000,8.000000)
(1.000000,2.000000)(3.000000,4.000000)
(5.000000,6.000000)(7.000000,8.000000)
But if I use the `()` in the initializer_list and `{}` in the istream filed, the results are all wrong. If I chagned the relavant part of main() to :
cx = { { (1,2),(3,4) }, { (5,6), (7,8) } };
std::cout << cx << std::endl;
cx << "{1,2} {3,4}";
std::cout << cx << std::endl;
Which renders all wrong values (compared with above):
$ ./ttt_mtx_init_fin_tmp.exe
(2.000000,0.000000)(4.000000,0.000000)
(6.000000,0.000000)(8.000000,0.000000)
(2.000000,0.000000)(4.000000,0.000000)
(6.000000,0.000000)(8.000000,0.000000)
I found it is rather confusion. So, my questions: is there a way to make these two expressions a same form? Many thanks for any helps.
I do not know any way to make std::istream::operator>> use { and } for std::complex, but if you are fine with using a helper, then you can replace the () in the input with {} and forward the input to the original operator>>:
#include <iostream>
#include <complex>
#include <sstream>
#include <algorithm>
template <typename T>
struct complex_reader {
std::complex<T>& target;
};
template <typename T>
complex_reader<typename T::value_type> get_complex_reader(T& t){ return {t};}
template <typename T>
std::istream& operator>>(std::istream& in,complex_reader<T> cr){
std::string input;
std::getline(in,input,'}'); // read till `}`
std::replace(input.begin(),input.end(),'{','(');
input += ')';
std::stringstream ss{input};
ss >> cr.target; // call the original >>
return in;
}
int main()
{
std::stringstream ss{"{2,2}"};
std::complex<double> x;
ss >> get_complex_reader(x);
std::cout << x;
}
Output:
(2,2)
However, you would have to write a similar helper to get consistent output (you may not provide an operator<< for std::complex<T> directly). Also note that the above implementation is a little simplistic. It reads from the stream until it encounters a }. For invalid input this may result in undesired effects and more sophisticated input validation is required.
Note that the operator>> takes the complex_helper by value to allow passing temporaries. Thats fine, because the member is a (non-const) reference.
This is not an answer, but a reasoning of my choice. After a series of cross conversions with `largest_prime_is_463035818`, I figured out what is my best choice for now (many thanks to his time and patience). A bottom line is becoming clear to me that I will not alter the input format of istream that is too much changed for pratical purpose, since file input is the major method to fetch data for a large matrix.
Under this constrain, I try to make the appearance of initializer_list as friendly as possible. I did some experiments, and found that the complex_literals expression is acceptable by initializer_list. And it looks ok to me.
using namespace std::complex_literals;
int main()
{
cMatrix cx(3,2);
cx = { { 1+2.2j , 4j}, { 5.3+6.5j , 8.3j}, {8.3, 5.6+4j} };
std::cout << cx << std::endl;
cx << " (1,2) (3,4) (5,6) (7,8) (2.3, 3.4) (2,7.8) ";
std::cout << cx << std::endl;
return 0;
}
And it works.
$ ./a.exe
(1.000000,2.200000) (0.000000,4.000000)
(5.300000,6.500000) (0.000000,8.300000)
(8.300000,0.000000) (5.600000,4.000000)
(1.000000,2.000000) (3.000000,4.000000)
(5.000000,6.000000) (7.000000,8.000000)
(2.300000,3.400000) (2.000000,7.800000)
Thank you for your patience, and please let me know if there are better ways.
See my code below:(you can compile the code with: g++-4.7 demo.cpp -std=c++11 -lmsgpack)
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <msgpack.hpp>
using namespace std;
template<class T>
void pack(T &t, string &str)
{
using namespace msgpack;
sbuffer buff;
pack(buff, t);
ostringstream is;
is << buff.size() << buff.data();
str = string(is.str());
}
template<class T>
T unpack(string &str)
{
using namespace msgpack;
unpacked result;
istringstream ss(str);
int len;
string buff;
ss >> len >> buff;
unpack(&result, buff.c_str(), len);
auto obj = result.get();
return obj.as<T>();
}
int main(int argc, char *argv[]) {
vector<float> t = {1., 2., 3., 4., 5.};
string s;
pack(t, s);
auto r = unpack<vector<float> >(s);
for(auto & v : r)
std::cout << v << std::endl;
// vector<int> is right
/*
vector<int> t = {1, 2, 3, 4, 5};
string s;
pack(t, s);
auto r = unpack<vector<int> >(s);
for(auto & v : r)
std::cout << v << std::endl;
*/
return 0;
}
There is a strange bug that 'vector', 'vector', 'int', 'double' can work in the above encapsulation, while 'vector', 'vector' can not.
runtime error shows below:
terminate called after throwing an instance of 'msgpack::type_error'
what(): std::bad_cast
but in the below encapsulation, any type can work well:
template<class T>
void pack(T &t, msgpack::sbuffer sbuf) {
pack(&sbuf, t);
}
template<class T>
T unpack(const msgpack::sbuffer & sbuf) {
msgpack::unpacked msg;
msgpack::unpack(&msg, sbuf.data(), sbuf.size());
auto obj = msg.get();
return obj.as<t>();
}
What's is the problem in my first code?
Thanks!
msgpack binary output can include null bytes, like it happens in your case. is […] << buff.data(); will only output first 4 bytes in your case.
To fix the error replace is << buff.size() << buff.data(); with is << buff.size() << string(buff.data(), buff.size());.
I have a family of classes that contain only variables of the following types: std::string, int, double. I should be able to serialize/deserialize objects of these classes to/from C string (null terminated). I don't want to use some 3rdparty serializer and do not want to write full-featured serializer by myself. I will serialize/deserialize only once in my code.
So, how to write very very tiny and yet elegant serializer and do it pretty fast?
UPDATE
I've written and tested my own. Maybe it will be useful for someone. If you notice some bugs or have some suggestions how to make it better, let me know. Here it is:
typedef std::ostringstream ostr;
typedef std::istringstream istr;
const char delimiter = '\n';
const int doublePrecision = 15;
void Save(ostr& os, int x) { os << x << delimiter; }
void Save(ostr& os, double x)
{
os.precision(doublePrecision);
os << x << delimiter;
}
void Save(ostr& os, const std::string& x) { os << x << delimiter; }
void Load(istr& is, int& x)
{
is >> x;
is.rdbuf()->sbumpc(); // get rid of delimiter
}
void Load(istr& is, double& x)
{
is >> x;
is.rdbuf()->sbumpc(); // get rid of delimiter
}
void Load(istr& is, std::string& x) { getline(is, x, delimiter); }
Test:
std::string a = "Test string 1 2 and 2.33";
std::string b = "45";
double c = 45.7;
int d = 58;
double e = 1.0/2048;
std::ostringstream os;
Save(os, a);
Save(os, b);
Save(os, c);
Save(os, d);
Save(os, e);
std::string serialized = os.str();
std::string aa;
std::string bb;
double cc = 0.0;
int dd = 0;
double ee = 0.0;
std::istringstream is(serialized);
Load(is, aa);
Load(is, bb);
Load(is, cc);
Load(is, dd);
Load(is, ee);
ASSERT(a == aa);
ASSERT(b == bb);
ASSERT(c == cc);
ASSERT(d == dd);
ASSERT(e == ee);
There are 2 ways of serializing string data to a stream, you either do it C-style and use a null to terminate it or (more portably and easier to read) first output a byte that says how long the string is then write the string.
Now if you want to differentiate a string from a non-string (number in this case), you can prepend every "packet" (item) with a byte code, say 0x00 for int, 0x01 for double, 0x02 for string, and branch a switch off depending on what the code is. This way you can even write the int/double as a byte, so you won't lose precision and you'll also end up with a smaller/easier to read file.
void save(std::ostringstream& out, const std::string& x)
{
out << x;
}
void read(std::istringstream& in, std::string& x)
{
in.str(x);
}
from here.
I know you don't want to use a 3rdParty serializer, but if you would reconsider: use Boost.Serialization.
(even if this is not the answer for you, it might be for someone else stumbling on this question)
Very simple example
class some_data
{
public:
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & my_string;
ar & my_double;
}
private:
std::string my_string;
double my_double;
};
and then to save:
my_data dataObject;
std::ofstream ofs("filename");
boost::archive::text_oarchive oa(ofs);
oa << dataObject;
or to load:
my_data dataObject;
std::ifstream ifs("filename");
boost::archive::text_iarchive ia(ifs);
ia >> dataObject;
See the sun xdr format. It's binary and efficient.
I have a tiny custom class to do this, as an example:
Marshall& Marshall::enc(const string& str) {
size_t size = str.size();
size_t pad = (4 - (size%4))%4;
size_t size_on_buff = size + pad;
space_for(sizeof(uint32_t) + size + pad);
check_size_t_overflow(size);
enc(static_cast<uint32_t>(size));
// xdr mandates padding
//space_for(size_on_buff);
memcpy(&(*buff)[pos],str.data(), size);
memset(&(*buff)[pos+size],0,pad);
pos+=size_on_buff;
return *this;
}
Marshall& Marshall::dec(string& str) {
str.clear();
size_t size;
dec(size);
size_t pad = (4 - (size%4))%4;
size_t size_on_buff = size + pad;
ck_space_avl(size + pad);
//str.resize(size);
str.assign((char*)&(*buff)[pos],size);
pos+=size_on_buff;
return *this;
}
I have a std::string which could be a string or could be a value (such as 0).
What is the best or easiest way to convert the std::string to int with the ability to fail? I want a C++ version of C#'s Int32.TryParse.
Use boost::lexical_cast. If the cast cannot be done, it will throw an exception.
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
int main(void)
{
std::string s;
std::cin >> s;
try
{
int i = boost::lexical_cast<int>(s);
/* ... */
}
catch(...)
{
/* ... */
}
}
Without boost:
#include <iostream>
#include <sstream>
#include <string>
int main(void)
{
std::string s;
std::cin >> s;
try
{
std::stringstream ss(s);
int i;
if ((ss >> i).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
/* ... */
}
catch(...)
{
/* ... */
}
}
Faking boost:
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
T lexical_cast(const std::string& s)
{
std::stringstream ss(s);
T result;
if ((ss >> result).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
return result;
}
int main(void)
{
std::string s;
std::cin >> s;
try
{
int i = lexical_cast<int>(s);
/* ... */
}
catch(...)
{
/* ... */
}
}
If you want no-throw versions of these functions, you'll have to catch the appropriate exceptions (I don't think boost::lexical_cast provides a no-throw version), something like this:
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
T lexical_cast(const std::string& s)
{
std::stringstream ss(s);
T result;
if ((ss >> result).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
return result;
}
template <typename T>
bool lexical_cast(const std::string& s, T& t)
{
try
{
// code-reuse! you could wrap
// boost::lexical_cast up like
// this as well
t = lexical_cast<T>(s);
return true;
}
catch (const std::bad_cast& e)
{
return false;
}
}
int main(void)
{
std::string s;
std::cin >> s;
int i;
if (!lexical_cast(s, i))
{
std::cout << "Bad cast." << std::endl;
}
}
The other answers that use streams will succeed even if the string contains invalid characters after a valid number e.g. "123abc". I'm not familiar with boost, so can't comment on its behavior.
If you want to know if the string contains a number and only a number, you have to use strtol:
#include <iostream>
#include <string>
int main(void)
{
std::string s;
std::cin >> s;
char *end;
long i = strtol( s.c_str(), &end, 10 );
if ( *end == '\0' )
{
// Success
}
else
{
// Failure
}
}
strtol returns a pointer to the character that ended the parse, so you can easily check if the entire string was parsed.
Note that strtol returns a long not an int, but depending on your compiler these are probably the same. There is no strtoi function in the standard library, only atoi, which doesn't return the parse ending character.
Exceptions should not be used for boolean tests
The accepted answer is really a terrible answer for question as asked, as it violates the precept "use exceptions for exceptional cases".
Exceptions are an excellent tool for handling exceptional cases -- cases where something has genuinely gone wrong. They are poor tools for existing use-cases. Partly because throwing and catching an exception is expensive, and partly because it is misleading code -- when a developer sees an exception they should reasonably be able to assume something is going wrong there. Good discussions of this basic principle abound, but I like "The Pragmatic Programmer"'s, or this isn't bad: http://www.lohmy.de/2013/03/06/writing-use-cases-exception-or-alternate-flow/
Use boost::lexical_cast if you always expect a number
boost::lexical_cast is an optimal solution when it really is an exception for it to be receiving a non-number.
Use boost::try_lexical_convert if non-numbers are part of your use case
If you are going through a string and want to do one thing if it's a number, and another if it's a number, don't use an exception for the boolean test. That's just bad programming.
In fact, boost offers try_lexical_convert, which is used in the implementation of lexical_cast (taken from the documentation here:
http://www.boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/synopsis.html#boost_lexical_cast.synopsis.lexical_cast).
template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
Target result;
if (!conversion::try_lexical_convert(arg, result))
throw bad_lexical_cast();
return result;
}
Another way using standard streams :
#include <sstream>
#include <iostream>
#include <string>
int main()
{
std::stringstream convertor;
std::string numberString = "Not a number!";
int number;
convertor << numberString;
convertor >> number;
if(convertor.fail())
{
// numberString is not a number!
std::cout << "Not a Number!";
}
}
Before boost's lexical_cast was available, I used to do the following:
namespace detail {
template< typename Target, typename Source >
struct stream_caster {
static Target stream_cast(const Source& s)
{
std::stringstream ss;
if( (ss << s).fail() ) {
throw std::bad_cast("could not stream from source");
}
Target t;
if( (ss >> t).fail() || !(ss >> ws).eof()) {
throw std::bad_cast("could not stream to target");
}
return t;
}
};
template< typename T >
struct stream_caster<T,T> {
static const T& stream_cast(const T& s)
{
return s;
}
};
template< typename Source >
struct stream_caster<std::string,Source> {
static std::string stream_cast(const Source& s)
{
std::ostringstream oss;
if( (oss << s).fail() ) {
throw std::bad_cast("could not stream from source");
}
return oss.str();
}
};
template< typename Target >
struct stream_caster<Target,std::string> {
static Target stream_cast(const std::string& s)
{
std::stringstream ss(s);
Target t;
if( (ss >> t).fail() || !(ss >> ws).eof()) {
throw std::bad_cast("could not stream to target");
}
return t;
}
};
template<>
struct stream_caster<std::string,std::string> {
static const std::string& stream_cast(const std::string& s)
{
return s;
}
};
}
template< typename Target, typename Source >
inline Target stream_cast(const Source& s)
{
return detail::stream_caster<Target,Source>::stream_cast(s);
}