C++ Handle overflow/underflow when extracting string to scalars - c++

when extracting data from string to scalars (char, short, int...), how could I easily know if the value I want to get exceeds the type limit?
unsigned char function(void)
{
std::string str = "259";
std::ostringstream os(str);
unsigned char scalar; // could also be short, int, float or double
if (str > /* limit of char */)
{
/* throw exception */
}
os >> scalar;
return scalar;
}

Consider the new C++11 conversion functions like std::stoi. They should throw a std::out_of_range exception in such a case. Unfortunately, this won't handle the char case directly, but you could first convert to an int, then check the range manually.

Related

convert string to size_t

Is there a way to convert std::string to size_t?
The problem is that size_t is platform dependable type (while it is the result of the sizeof). So, I can not guarantee that converting string to unsigned long or unsigned int will do it correctly.
EDIT:
A simple case is:
std::cout<< "Enter the index:";
std::string input;
std::cin >> input;
size_t index=string_to_size_t(input);
//Work with index to do something
you can use std::stringstream
std::string string = "12345";
std::stringstream sstream(string);
size_t result;
sstream >> result;
std::cout << result << std::endl;
You may want to use sscanf with the %zu specifier, which is for std::size_t.
sscanf(input.c_str(), "%zu", &index);
Have a look here.
Literally, I doubt that there is an overloaded operator >> of std::basic_istringstream for std::size_t. See here.
Let us assume for a minute that size_t is a typedef to an existing integer, i.e. the same width as either unsigned int, unsigned long, or unsigned long long.
AFAIR it could be a separate (larger still) type as far as the standard wording is concerned, but I consider that to be highly unlikely.
Working with that assumption that size_t is not larger than unsigned long long, either stoull or strtoull with subsequent cast to size_t should work.
From the same assumption (size_t defined in terms of either unsigned long or unsigned long long), there would be an operator>> overload for that type.
You can use %zd as the format specifier in a scanf-type approach.
Or use a std::stringstream which will have an overloaded >> to size_t.
#include <sstream>
std::istringstream iss("a");
size_t size;
iss >> size;
By using iss.fail(), you check failure.
Instead of ("a"), use value you want to convert.
/**
* #brief Convert const char* to size_t
* #note When there is an error it returns the maximum of size_t
* #param *number: const char*
* #retval size_t
*/
size_t to_size_t(const char *number) {
size_t sizeT;
std::istringstream iss(number);
iss >> sizeT;
if (iss.fail()) {
return std::numeric_limits<size_t>::max();
} else {
return sizeT;
}
}

How to convert a large integer from a string to a uint64_t?

I have a large integer stored as a string. I need to convert it into an integer (uint64_t). I tried stoi(), but it is crashing after throwing an instance of std::out_of_range.
The string has maximum of 64-bit integer value, max value of 18,446,744,073,709,551,615 (maximum for an unsigned long int).
How do I do this, other than (of course) manually?
As long as the string contains a number that is less than std::numeric_limits<uint64_t>::max(), then std::stoull() will do what you're expecting.
(The std::stoull() function is new in C++11.)
You can use stringstream to do this. This is supported in C++98 (the std::stoull() function was added in C++11).
#include <stdint.h>
#include <iostream>
#include <sstream>
using namespace std;
uint64_t string_to_uint64(string str) {
stringstream stream(str);
uint64_t result;
stream >> result;
return result;
}
int main() {
string str = "1234567891234567";
uint64_t val = string_to_uint64(str);
cout << val;
return 0;
}
One approach could be to use stringstreams:
unsigned long long val;
std::istringstream stream(inputstring);
stream >> val;
According to this reference there's at least an overload for operator>> for unsigned long long, which could be the same as uint64_t.
Otherwise you'll probably have to do it manually, e.g. split the string into handleable pieces, and join the results by multiplication with the right base.
To be sure I'd go with this for now:
unit64_t to_uint64(std::string const & in) {
static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "ull not large enough");
unsigned long long val = 0;
std::istringstream stream(in);
stream >> val;
return val;
}

C++ iterator value to variable

I am using an iterator in a C++ code to retrieve records read using sqlite3 statements. I am able to display the contents pointed to by the iterator to screen using cout. How would i assign the value to a simple float or array variable.
typedef vector<vector<string> > Records;
vector< vector<string> >::iterator iter_ii;
vector<string>::iterator iter_jj;
Records records = select_stmt("SELECT density FROM Ftable where PROG=2.0");
for(iter_ii=records.begin(); iter_ii!=records.end(); iter_ii++)
{
for(iter_jj=(*iter_ii).begin(); iter_jj!=(*iter_ii).end(); iter_jj++)
{
cout << *iter_jj << endl; //This works fine and data gets displayed!
//How do i store the data pointed to by *iter_jj in a simple float variable or array?
}
}
C++ is type-safe, so you need to explicitly convert the string to the desired target type.
For float for example you could use atof:
float f = atof(iter_jj->c_str());
A more convenient alternative is Boost's lexical_cast, which works with the same syntax for all types that support extraction from an std::istream:
float f = boost::lexical_cast<float>(*iter_jj);
Note that both of these can fail in different ways if the contents of the string cannot be converted to a float in any meaningful way.
Your real problem is how to convert a string to a float. Here is one solution.
float value;
stringstream ss(*iter_jj);
if (! (ss >> value))
{
ERROR failed to convert value
}
If you have C++11 compatible compiler:
float x = stof(*iter_jj);
(Obviously x could be a variable outside of the loop).
If you don't have C++11:
stringstream ss(*iter_jj);
float x;
ss >> x;
Well since you are working with:
std::vector<std::vector<std::string> > records;
the actual question here is: how to retrieve the specific type of data from std::string object.
The good approach would be constructing and using std::istringstream object for this purpose:
float f;
std::istringstream is(*iter_jj);
if (is >> f)
{
// handle successful retrieval...
}
just don't forget to #include <sstream> :)
As for converting * to string, in c++11, you can convert integer/floats to string by calling static method to_string:string str = std::string::to_string(integer/* or float*/);
in c++98, you can write your own to_string:
#include <cstdio>
#include <cstring>
#include <cstdarg>
#include <string>
void format_aux(char* ptr, int size, const char* format, ...) {
va_list args;
va_start(args, format);
vsnprintf(ptr, size, format, args);
va_end(args);
}
#undef TO_STRING__GEN
#define TO_STRING__GEN(type, arg, size) \
std::string \
to_string(type val) { \
const int sz = size; \
char buf[sz]; \
format_aux(buf, sz, arg, val); \
return std::string(buf); \
}
TO_STRING__GEN(int, "%d", 4*sizeof(int))
TO_STRING__GEN(unsigned int, "%u", 4*sizeof(unsigned int))
TO_STRING__GEN(long, "%ld", 4*sizeof(long))
TO_STRING__GEN(unsigned long, "%lu", 4*sizeof(unsigned long))
TO_STRING__GEN(float, "%f", (std::numeric_limits<float>::max_exponent10 + 20))
TO_STRING__GEN(double, "%f", (std::numeric_limits<float>::max_exponent10 + 20))
#undef TO_STRING__GEN
*iter_jj is going to give you a std::string. In order to store that as a float, it will need to be a floating point number in string form (e.g. "1.23456") and you will need to call one of the strtof family of functions (http://en.cppreference.com/w/cpp/string/byte/strtof)

basic_string of unsigned char Value Type

So, string comes with the value type of char. I want a string of value type unsigned char. Why i want such a thing is because i am currently writing a program which converts large input of hexadecimal to decimal, and i am using strings to calculate the result. But the range of char, which is -128 to 127 is too small, unsigned char with range 0 to 255 would work perfectly instead. Consider this code:
#include<iostream>
using namespace std;
int main()
{
typedef basic_string<unsigned char> u_string;
u_string x= "Hello!";
return 0;
}
But when i try to compile, it shows 2 errors, one is _invalid conversion from const char* to unsigned const char*_ and the other is initializing argument 1 of std::basic_string<_CharT, _Traits, _Alloc>::basic_string...(it goes on)
EDIT:
"Why does the problem "converts large input of hexadecimal to decimal" require initializing a u_string with a string literal?"
While calculating, each time i shift to the left of the hexadecimal number, i multiply by 16. At most the result is going to be 16x9=144, which surpasses the limit of 127, and it makes it negative value.
Also, i have to initialize it like this:
x="0"; x[0] -='0';
Because i want it to be 0 in value. if the variable is null, then i can't perform operations on it, if it is 0, then i can.
So, what should i do?
String literals are const char and you are assigning them to a const unsigned char.
Two solution you have:
First, Copy string from standard strings to your element by element.
Second, Write your own user-literal for your string class:
inline constexpr const unsigned char * operator"" _us(const char *s,unsigned int)
{
return (const unsigned char *) s;
}
// OR
u_string operator"" _us(const char *s, unsigned int len)
{
return u_string(s, s+len);
}
u_string x = "Hello!"_us;
An alternative solution would be to make your compiler treat char as unsigned. There are compiler flags for this:
MSVC: /J
GCC, Clang, ICC: -funsigned-char

Decimal string to char

Is there a way to convert numeric string to a char containing that value? For example, the string "128" should convert to a char holding the value 128.
Yes... atoi from C.
char mychar = (char)atoi("128");
A more C++ oriented approach would be...
template<class T>
T fromString(const std::string& s)
{
std::istringstream stream (s);
T t;
stream >> t;
return t;
}
char mychar = (char)fromString<int>(mycppstring);
There's the C-style atoi, but it converts to an int. You 'll have to cast to char yourself.
For a C++ style solution (which is also safer) you can do
string input("128");
stringstream ss(str);
int num;
if((ss >> num).fail()) {
// invalid format or other error
}
char result = (char)num;
It depends. If char is signed and 8 bits, you cannot convert "128" to a char in base 10. The maximum positive value of a signed 8-bit value is 127.
This is a really pedantic answer, but you should probably know this at some point.
You can use atoi. That will get you the integer 128. You can just cast that to a char and you're done.
char c = (char) atoi("128");