Lexical cast Partial conversion - Is it possible? - c++

lexical_cast throws an exception in the following case. Is there a way to use lexical_cast and convert the string to integer.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
int main()
{
std::string src = "124is";
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
I understand, I can use atoi instead of boost::lexical_cast.

If I'm understanding your requirements correctly it seems as though removing the non-numeric elements from the string first before the lexical_cast will solve your problem. The approach I outline here makes use of the isdigit function which will return true if the given char is a digit from 0 to 9.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
#include <algorithm>
#include <cctype> //for isdigit
struct is_not_digit{
bool operator()(char a) { return !isdigit(a); }
};
int main()
{
std::string src = "124is";
src.erase(std::remove_if(src.begin(),src.end(),is_not_digit()),src.end());
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}

The boost/lexical_cast uses stringstream to convert from string to other types,so you must make sure the string can be converted completely! or, it will throw the bad_lexical_cast exception,This is an example:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#define ERROR_LEXICAL_CAST 1
int main()
{
using boost::lexical_cast;
int a = 0;
double b = 0.0;
std::string s = "";
int e = 0;
try
{
// ----- string --> int
a = lexical_cast<int>("123");//good
b = lexical_cast<double>("123.12");//good
// -----double to string good
s = lexical_cast<std::string>("123456.7");
// ----- bad
e = lexical_cast<int>("abc");
}
catch(boost::bad_lexical_cast& e)
{
// bad lexical cast: source type value could not be interpreted as target
std::cout << e.what() << std::endl;
return ERROR_LEXICAL_CAST;
}
std::cout << a << std::endl; // cout:123
std::cout << b << std::endl; //cout:123.12
std::cout << s << std::endl; //cout:123456.7
return 0;
}

Related

Build incremental std::string

I try to build an std::string in the form of "start:Pdc1;Pdc2;Pdc3;"
With following code I can build the repeated "Pdc" and the incremental string "123" but I'm unable to combine the two strings.
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iterator>
#include <numeric>
int main()
{
std::ostringstream ss;
std::string hdr("start:");
std::fill_n(std::ostream_iterator<std::string>(ss), 3, "Pdc;");
hdr.append(ss.str());
std::string v("abc");
std::iota(v.begin(), v.end(), '1');
std::cout << hdr << std::endl;
std::cout << v << std::endl;
std::cout << "Expected output: start:Pdc1;Pdc2;Pdc3;" << std::endl;
return 0;
}
How can I build this string? Preferable without a while or for loop.
The expected output is: start:Pdc1;Pdc2;Pdc3;
std::strings can be concatenated via their operator+ (or +=) and integers can be converted via std::to_string:
std::string res("start:");
for (int i=0;i<3;++i){
res += "Pdc" + std::to_string(i+1) + ";";
}
std::cout << res << "\n";
If you like you can use an algorithm instead of the handwritten loop, but it will still be a loop (your code has 2 loops, but only 1 is needed).
Code to generate your expected string, though with a small for loop.
#include <iostream>
#include <string>
#include <sstream>
std::string cmd(const std::size_t N)
{
std::ostringstream os;
os << "start:";
for(std::size_t n = 1; n <= N; ++n) os << "Pdc" << n << ";";
return os.str();
}
int main()
{
std::cout << cmd(3ul);
return 0;
}

Defining a string in an if statement

Im trying to make a number that is positive (already converted into a string) look like "+number" instead of "number" but i can't define it in an if
#include <iostream>
#include <string>
int main()
{
std::string x3s;
int number = 145;
if (number >= 0)
{
x3s = "+" + number;
}
std::cout << x3s << std::endl;
}
Firstly, there is an I/O manipulator std::showpos.
#include <iostream>
int main()
{
int number = 145;
std::cout << std::showpos << number << std::endl;
}
Secondly, you are using the verb "define" incorrectly.
You can use x3s = std::string("+") + std::to_string(number);

getting a sub string of a std::wstring

How can I get a substring of a std::wstring which includes some non-ASCII characters?
The following code does not output anything:
(The text is an Arabic word contains 4 characters where each character has two bytes, plus the word "Hello")
#include <iostream>
#include <string>
using namespace std;
int main()
{
wstring s = L"سلام hello";
wcout << s.substr(0,3) << endl;
wcout << s.substr(4,5) << endl;
return 0;
}
This should work: live on Coliru
#include <iostream>
#include <string>
#include <boost/regex/pending/unicode_iterator.hpp>
using namespace std;
template <typename C>
std::string to_utf8(C const& in)
{
std::string result;
auto out = std::back_inserter(result);
auto utf8out = boost::utf8_output_iterator<decltype(out)>(out);
std::copy(begin(in), end(in), utf8out);
return result;
}
int main()
{
wstring s = L"سلام hello";
auto first = s.substr(0,3);
auto second = s.substr(4,5);
cout << to_utf8(first) << endl;
cout << to_utf8(second) << endl;
}
Prints
سلا
hell
Frankly though, I think your substring calls are making weird assumptions. Let me suggest a fix for that in a minute:

How to check std::string if its indeed an integer?

The following code converts an std::string to int and the problem lies with the fact that it cannot discern from a true integer or just a random string. Is there a systematic method for dealing with such a problem?
#include <cstring>
#include <iostream>
#include <sstream>
int main()
{
std::string str = "H";
int int_value;
std::istringstream ss(str);
ss >> int_value;
std::cout<<int_value<<std::endl;
return 0;
}
EDIT: This is the solution that I liked because it is very minimal and elegant! It doesn't work for negative numbers but I only needed positive ones anyways.
#include <cstring>
#include <iostream>
#include <sstream>
int main()
{
std::string str = "2147483647";
int int_value;
std::istringstream ss(str);
if (ss >> int_value)
std::cout << "Hooray!" << std::endl;
std::cout<<int_value<<std::endl;
str = "-2147483648";
std::istringstream negative_ss(str);
if (ss >> int_value)
std::cout << "Hooray!" << std::endl;
std::cout<<int_value<<std::endl;
return 0;
}
You may try to use Boost lexical_cast, it will throw an exception if the cast failed.
int number;
try
{
number = boost::lexical_cast<int>(str);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << str << "isn't an integer number" << std::endl;
}
EDIT
Accorinding to #chris, You may also try to use std::stoi since C++11. It will throw std::invalid_argument exception if no conversion could be performed. You may find more information here: std::stoi
WhozCraig's approach is much nicer and I wanted to expand on it using the approach that the C++ FAQ uses which is as follows:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline int convertToInt(std::string const& s,
bool failIfLeftoverChars = true)
{
std::istringstream i(s);
int x;
char c;
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
throw BadConversion("convertToInt(\"" + s + "\")");
return x;
}
int main()
{
std::cout << convertToInt( "100" ) << std::endl ;
std::cout << convertToInt( "-100" ) << std::endl ;
std::cout << convertToInt( " -100" ) << std::endl ;
std::cout << convertToInt( " -100 ", false ) << std::endl ;
// The next two will fail
std::cout << convertToInt( " -100 ", true ) << std::endl ;
std::cout << convertToInt( "H" ) << std::endl ;
}
This is robust and will know if the conversion fails, you also can optionally choose to fail on left over characters.
/* isdigit example */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main ()
{
char str[]="1776ad";
int year;
if (isdigit(str[0]))
{
year = atoi (str);
printf ("The year that followed %d was %d.\n",year,year+1);
}
return 0;
}

convert string to integer in c++

Hello
I know it was asked many times but I hadn't found answer to my specific question.
I want to convert only string that contains only decimal numbers:
For example 256 is OK but 256a is not.
Could it be done without checking the string?
Thanks
The simplest way that makes error checking optional that I can think of is this:
char *endptr;
int x = strtol(str, &endptr, 0);
int error = (*endptr != '\0');
In C++ way, use stringstream:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
stringstream sstr;
int a = -1;
sstr << 256 << 'a';
sstr >> a;
if (sstr.failbit)
{
cout << "Either no character was extracted, or the character can't represent a proper value." << endl;
}
if (sstr.badbit)
{
cout << "Error on stream.\n";
}
cout << "Extracted number " << a << endl;
return 0;
}
An other way using c++ style : We check the number of digits to know if the string was valid or not :
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
int main(int argc,char* argv[]) {
std::string a("256");
std::istringstream buffer(a);
int number;
buffer >> number; // OK conversion is done !
// Let's now check if the string was valid !
// Quick way to compute number of digits
size_t num_of_digits = (size_t)floor( log10( abs( number ) ) ) + 1;
if (num_of_digits!=a.length()) {
std::cout << "Not a valid string !" << std::endl;
}
else {
std::cout << "Valid conversion to " << number << std::endl;
}
}