What's the safest and best way to retrieve an unsigned long from a string in C++?
I know of a number of possible methods.
First, converting a signed long taken from atol.
char *myStr; // Initalized to some value somehow.
unsigned long n = ((unsigned)atol(myStr));
The obvious problem with this is, what happens when the value stored in myStr is larger than a signed long can contain? What does atol retrieve?
The next possibility is to use strtoul.
char *myStr; // Initalized to some value somehow.
unsigned long n = strtoul(myStr, 0, 10);
However, this is a little over complicated for my needs. I'd like a simple function, string in, unsigned long base 10 out. Also, the error handling leaves much to be desired.
The final possibility I have found is to use sscanf.
char *myStr; // Initalized to some value somehow.
unsigned long n = 0;
if(sscanf(myStr, "%lu", n) != 1) {
//do some error handling
}
Again, error handling leaves much to be desired, and a little more complicated than I'd like.
The remaining obvious option is to write my own either a wrapper around one of the previous possibilities or some thing which cycles through the string and manually converts each digit until it reaches ULONG_MAX.
My question is, what are the other options that my google-fu has failed to find? Any thing in the C++ std library that will cleanly convert a string to an unsigned long and throw exceptions on failure?
My apologies if this is a dupe, but I couldn't find any questions that exactly matched mine.
You can use strtoul with no problem. The function returns an unsigned long. If convertion can not be performed the function return 0. If the correct long value is out of range the function return ULONG_MAX and the errno global variable is set to ERANGE.
One way to do it:
stringstream(str) >> ulongVariable;
template <class T>
T strToNum(const std::string &inputString,
std::ios_base &(*f)(std::ios_base&) = std::dec)
{
T t;
std::istringstream stringStream(inputString);
if ((stringStream >> f >> t).fail())
{
throw runtime_error("Invalid conversion");
}
return t;
}
// Example usage
unsigned long ulongValue = strToNum<unsigned long>(strValue);
int intValue = strToNum<int>(strValue);
int intValueFromHex = strToNum<int>(strHexValue,std::hex);
unsigned long ulOctValue = strToNum<unsigned long>(strOctVal, std::oct);
If you can use the boost libraries (www.boost.org) look at the conversion library - it's a header only include
#include "boost/lexical_cast.hpp"
then all you need to do is
unsigned long ul = boost::lexical_cast<unsigned long>(str);
Jeffrey Stedfast has a beautiful post about writing int parser routines for Mono (in C).
It generates code that uses uses native types (you need 32 bit to parse 32 bit) and error codes for overflow.
Use "atol" in-built std function
For example std::string input = "1024";
std::atol(input.c_str());
Atol expect parameter to be of type c string, so c_str() does it that for you.
Robust way will be
write a static function and use it
bool str2Ulong(const string& str,unsigned long & arValue)
{
char *tempptr=NULL;
arValue=strtoul(str,tempptr,10);
return ! (arValue==0 && tempptr==str.c_str());
}
Related
In C++, how can I input a number to unsigned char variable? In C, I can accept the input using %hhu format specifier:
unsigned char var_name;
scanf("%hhu", &var_name);
//lets say I inputted 27
printf("%hhu", var_name);
//the output is 27
How can I do that in C++? The code below is my attempt to do this in C++, but it does a wrong thing. How can I write equivalent code in C++?
unsigned char var_name;
std::cin >> var_name;
//Input 27 again
std::cout << var_name;
//The output is just 2, how can I make the '7' appear?
This happens because when reading an unsigned char from std::istream, a character is read. That's just what happens, that's how std::istream works. It also makes a lot of sense, because it's quite common to want to read a single character.
The trivial solution is to use a temp variable:
unsigned char var_name;
unsigned int tmp;
std::cin >> tmp; // input 27
// optionally add checking that tmp is small enough
var_name = tmp; // truncation of unsigned ints is well defined
std::cout << var_name; // should print 27
You are only getting a 2 when printing the variable because of cin.
The maximum size of an unsigned char in C++ is usually 8 bits, which is fine for any actual character, and any digit up to 255. However this number depends on the compiler and the system. The maximum value that can be stored is in the header, as UCHAR_MAX.
Your issue here is that you are using cin, which only ever reads the first 'character' of an input if it is storing that input as a char. There are several ways around this, including taking the input as an integer and then converting to a char, or making your program work with an integer.
Hope this helps :)
When var_name is of type unsigned char, then the line
std::cin >> var_name;
is similar to
std::scanf("%c", &var_name);
i.e. C++ will assume that you want to read a single character and write the character code into var_name.
If you instead want to read a number and write that number into var_name, then you cannot use the data type char or unsigned char when using operator >>, even if the data type is technically able to represent the desired range of values. Instead, you will first have to use a variable with a larger data type, such as unsigned short, for reading the number. Afterwards, you can assign it to another variable of type unsigned char:
unsigned char var_name;
unsigned short temp;
std::cin >> temp;
if ( std::cin )
{
var_name = static_cast<unsigned char>( temp );
std::cout << var_name << '\n';
}
else
{
//TODO: handle error
}
The static_cast is not necessary, but some compilers may emit a warning due to the truncation, which will probably be suppressed by the cast. Also, using the cast makes the code more readable, because it becomes obvious that the value is being truncated.
However, I generally do not recommend that you use operator >> for user input, because it will do strange things, such as
not always read one line of input at a time, and
accept garbage such as "6sdfj23jlj" as valid input for the number 6, although the input should probably be rejected in this case.
If you want to read a number from the user with proper input validation, I recommend that you take a look at my function get_int_from_user in this answer of mine to another question.
Hi I have a string that looks like this:
std::string myString = "123456789";
Is there a way for me to turn that string of a decimal number to a binary number?
Firstly, you want to convert the string representing a number into an actual integer.
As stated by some others: std::stoi "string to int". Depending on the size of the numbers, you may want to use std::stoull. this is the same thing but for long long, a 64 bit integer.
Next you want to convert that number back into string. the easiest thing to use that provides this functionality is std::bitset and its to_string member function. The constructor of bitset requires an unsigned long long, so we'll use std::stoull, the unsigned variant.
This can all be combined into a single line of code:
myString = std::bitset<64>{ std::stoull(myString) }.to_string(); // 64 bits to fit a long long
After this operation, You'll be left with a string that looks like this: 0000000000000000000000000000000000000111010110111100110100010101
You may want to get rid of the zero's up front.
We can use the string's find and erase
myString.erase( 0, myString.find('1') );
This will erase all characters from position 0 until the first 1's position.
If you want to parse string to int, here is how you do it:
std::string strDec = "123456789";
int i = std::stoi(strDec);
If you then want to convert int to string but this time in binary representation, here is a way to do that:
std::string strBin = std::bitset<32>(i).to_string();
Demo
Or, you can use {fmt} library:
#include <fmt/core.h>
int main() {
std::string strDec = "123456789";
std::string strBin = fmt::format("{:032b}", std::stoi(strDec));
}
Demo
I have bitset<8> v8 and its value is something like "11001101", how can I convert it to char? I need a single letter. Like letter "f"=01100110.
P.S. Thanks for help. I needed this to illustrate random errors in bits. For example without error f, and with error something like ♥, and so on with all text in file. In text you can see such errors clearly.
unsigned long i = mybits.to_ulong();
unsigned char c = static_cast<unsigned char>( i ); // simplest -- no checks for 8 bit bitsets
Something along the lines of the above should work. Note that the bit field may contain a value that cannot be represented using a plain char (it is implementation defined whether it is signed or not) -- so you should always check before casting.
char c;
if (i <= CHAR_MAX)
c = static_cast<char>( i );
The provided solution did not work for me. I was using C++14 with g++ 9. However, I was able to get it working by :
char lower = 'a';
bitset<8> upper(lower);
upper.reset(5);
cout << (char)upper.to_ulong() << endl;
This may not be the best way to do it, I am sure, but it worked for me!
I am writing a program that converts a parathensized expression into a mathematical one, and evaluates it. I've got the calculation bit written already.
I am using a stack for the operands, and a queue for the numbers. Adding operands to the stack isn't an issue, but I need to identify whether the input character is an integer, and if so, add it to the queue. Here's some code:
cout << "Enter the numbers and operands for the expression";
string aString;
do
{
cin >> aString
if (aString = int) // function to convert to read if int, convert to int
{
c_str(...);
atoi(...);
istack.push(int);
}
}
That's where I'm stuck now. I know I'm going to have to use c_str and atoi to convert it to an int. Am I taking the wrong approach?
Use the .fail() method of the stream.
If you need the string too, you can read to a string first, then attempt to convert the string to an integer using a stringstream object and check .fail() on the stringstream to see if the conversion could be done.
cin >> aString;
std::stringstream ss;
ss << aString;
int n;
ss >> n;
if (!ss.fail()) {
// int;
} else {
// not int;
}
I'll probably get flamed for this by the C++ purists.
However, sometimes the C++ library is just more work than the C library. I offer this
solution to C developers out there. And C++ developers who don't mind using some of the
features of the C library.
The whole check and conversion can be done in 1 line of C using the sscanf function.
int intval;
cin >> aString
if (sscanf(aString.c_str(), "%d", &intval)){
istack.push(intval);
}
sscanf returns the number of input arguments matched and assigned. So in this case, it's looking for one standard signed int value. If sscanf returns 1 then it succeeded in assigning the value. If it returns 0 then we don't have an int.
If you expect an integer, I would use boost::lexical_cast.
std::string some_string = "345";
int val = boost::lexical_cast<int>(some_string);
If it fails to cast to an integer, it will throw. The performance is pretty reasonable, and it keeps your code very clean.
I am unaware of any non-throwing version. You could use something like this, though I usually try to avoid letting exceptions control program flow.
bool cast_nothrow(const std::string &str, int &val) {
try {
val = boost::lexical_cast<int>(str);
return true;
} catch (boost::bad_lexical_cast &) {
return false;
}
}
Edit:
I would not recommend your integer validation checking for structure like you described. Good functions do one thing and one thing well.
Usually you'd want a more formal grammar parser to handle such things. My honest advice is to embed a scripting language or library in your project. It is non-trivial, so let someone else do the hard work.
If I actually tried to implement what you propose, I would probably do a stack based solution keeping the parenthesis levels at their own stack frame. The simplest thing would just be to hard code the simple operators (parenthesis, add, sub, etc) and assume that the rest of everything is a number.
Eventually you'd want everything broken down into some expression type. It might look something like this:
struct Expression {
virtual ~Expression() {}
virtual float value() const = 0;
};
struct Number : public Expression {
virtual float value() const {return val;}
float val;
};
struct AdditionOper : public Expression {
virtual float value() const {return lhs->value() + rhs->value();}
boost::shared_ptr<Expression> lhs;
boost::shared_ptr<Expression> rhs;
};
I'd start by parsing out the parenthesis, they will determine the order of your expressions. Then I'd split everything based on the numerical operands and start putting them in expressions. Then you're left with cases like 3 + 4 * 6 which would require some some care to get the order of operations right.
Good luck.
You can either run your function that converts a string representation of a number to a double and see if there's an error, or you can look at the contents of the string and see if it matches the pattern of a number and then do the conversion.
You might use boost::lexical_cast<double>() or std::stod() (C++11) where errors are reported with an exception, or istringstream extractors where the error is reported by setting the fail bit, or with C conversion functions that report errors by setting the global (thread local, rather) variable errno.
try {
istack.push_back(std::stod(aString));
} catch(std::invalid_argument &e) {
// aString is not a number
}
or
errno = 0;
char const *s = aString.c_str();
char *end;
double result = strtod(s,&end);
if(EINVAL==errno) {
// the string is not a number
} else {
istack.push_back(result);
}
An implementation of the second option might use a regex to see if the string matches the pattern you use for numbers, and if it does then running your conversion function. Here's an example of a pattern you might expect for floating point values:
std::regex pattern("[+-]?(\d*.\d+|\d+.?)([eE][+-]?\d+)?");
if(std::regex_match(aString,pattern)) {
istack.push_back(std::stod(aString));
} else {
// aString is not a number
}
Also, this probably doesn't matter to you, but most any built in method for converting a string to a number will be locale sensitive one way or another. One way to isolate yourself from this is to use a stringstream you create and imbue with the classic locale.
I guess the C++ (no boost) way would be this :
do
{
std::stringstream ss;
std::string test;
cin >> test;
ss << test;
int num;
if (ss >> num) // function to convert to read if int, convert to int
{
std::cout << "Number : " << num << "\n";
}
}while(true); // don't do this though..
Can you not use ctype.h http://www.cplusplus.com/reference/clibrary/cctype/. I have used this before and did not get into trouble.
Especially if you're doing base-10 input, I find the most blatant thing to do is read the string, then check that it only contains valid characters:
string s;
cin >> s;
if(strrspn(s.c_str(), "0123456789")==s.length()){
//int
} else{
//not int
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to convert a single char into an int
Well, I'm doing a basic program, wich handles some input like:
2+2
So, I need to add 2 + 2.
I did something like:
string mys "2+2";
fir = mys[0];
sec = mys[2];
But now I want to add "fir" to "sec", so I need to convert them to Int.
I tried "int(fir)" but didn't worked.
There are mulitple ways of converting a string to an int.
Solution 1: Using Legacy C functionality
int main()
{
//char hello[5];
//hello = "12345"; --->This wont compile
char hello[] = "12345";
Printf("My number is: %d", atoi(hello));
return 0;
}
Solution 2: Using lexical_cast(Most Appropriate & simplest)
int x = boost::lexical_cast<int>("12345");
Solution 3: Using C++ Streams
std::string hello("123");
std::stringstream str(hello);
int x;
str >> x;
if (!str)
{
// The conversion failed.
}
Alright so first a little backround on why what you attempted didn't work. In your example, fir is declared as a string. When you attempted to do int(fir), which is the same as (int)fir, you attempted a c-style cast from a string to an integer. Essentially you will get garbage because a c-style cast in c++ will run through all of the available casts and take the first one that works. At best your going to get the memory value that represents the character 2, which is dependent upon the character encoding your using (UTF-8, ascii etc...). For instance, if fir contained "2", then you might possibly get 0x32 as your integer value (assuming ascii). You should really never use c-style casts, and the only place where it's really safe to use them are conversions between numeric types.
If your given a string like the one in your example, first you should separate the string into the relevant sequences of characters (tokens) using a function like strtok. In this simple example that would be "2", "+" and "2". Once you've done that you can simple call a function such as atoi on the strings you want converted to integers.
Example:
string str = "2";
int i = atoi(str.c_str()); //value of 2
However, this will get slightly more complicated if you want to be able to handle non-integer numbers as well. In that case, your best bet is to separate on the operand (+ - / * etc), and then do a find on the numeric strings for a decimal point. If you find one you can treat it as a double and use the function atof instead of atoi, and if you don't, just stick with atoi.
Have you tried atoi or boost lexical cast?