c++ How to extract numbers from a string that has backslash? - c++

I am trying to extract numbers from a string.
I would like to save each number to a separate double variable.
I currently tried using a simple stringstream like this.
std::string line = "100.2456426246\200.2624362436\300.136213477347";
std::stringstream stream(line);
stream.precision(20);
double a,b,c;
stream >> a >> b >> c;
Not only is the precision wrong(only prints out 6 digits), it only extracts the first number a(100.245), and b and c is null. I suspect it is due to backslash, but I'm not exactly sure.
What is the best way to read the string which contains backslash between each number and store the whole number with correct precision?

You could use getline with a delimiter to split a string into a vector of elements and atof to extract floats along these lines
vector<string> elems;
stringstream stream(line);
string item;
while (getline(stream, item, "\\")) {
elems.push_back(item);
}
vector<float> val(elems.size());
...
val[i]=atof(elems[i].c_str())
Precision here is more of a matter of presentation, which you can customize with the help of setprecision. For example,
#include <iomanip>
...
cerr << setprecision(6) << val[i] << endl;
will output the truncation to six significant digits.
Another matter is making sure that all digits up to the last one are stored. To make sure that all digits are stored, simply the size of your defined float must be sufficiently large to contain your data, and atof may need to be replaced by an appropriate parser if float should be replaced by double or something else.

Related

Input validation for integer

I am having trouble with some basic input validation. I have done a lot of searching but cant seem to find the answer that works with my code. I am trying to validate integer input. I am able to test whether a char was entered or not but I need another parameter to test if the number is actually an int and not a double or float.
do
{
cout << "\nHow many numbers would you like to enter?" << endl;
cin >> size;
if (size < 1 || cin.fail())
{
cout << "\nInvalid input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}while(size < 1 || cin.fail());
Too late. By the time operator>> does its job, the horse has left the barn already. You have to figure it out before you actually parse the value.
If you tell operator>> to extract a value into an integer, operator>> will, first, skip any spaces, parse an optional negative sign, then as many digits as it sees. And that's what you will get.
If the last digit is followed by a ".", operator>> doesn't care. It stops, because you told it to parse an integer, and calls it a day.
Similarly, if you tell operator>> to extract a value into one of the floating point types (float, double, long double), operator>> will parse anything that looks like a floating point number, and put it into the floating point type instance. Since an integer looks like a perfectly valid floating point number, either an integer or a floating point number will parse equally, and stored.
You have no indication of what was actually parsed, except the value itself.
So, there are two ways of doing this. One way is to always parse the value into a floating point number, then check if the parsed number is a whole number, or contains any fractional part, then proceed accordingly.
Or, you could parse this yourself. Use get() to parse one character at a time. Ignore any leading whitespace, then collect everything that follows: an optional minus sign, zero or more digits, an optional period followed by zero or more digits, and an optional "e" followed by an exponent.
If you collected a period or an "e", as part of this process, you know that you just parsed a floating point number, otherwise it's going to be an integer. Then, take everything that's been collected, and then parse it, with std::istringstream's assistance, into your selected value.
(Technically, "e" does not necessarily indicate a floating point value; for example 1e3 will happily live inside an int, it's up to you to decide how you wish to handle this case).
I think you could read the input first then do the validation afterward.
If you can use a c11 compiler and the application only wants positive number and do not care symbols e.g "+", "-", you could try something like the following code:
#include <regex>
...
std::regex integers(R"(\d+)");
enum{INPUT_SIZE=256};
char input[INPUT_SIZE];
do
{
memset(input, 0, INPUT_SIZE);
cin >> input;
if(std::regex_match(input, input+strlen(input), integers))
{
cout << input << " is an integer\n";
}
else
{
cout << "input is not an integer";
}
}while(1);

Using stringstream precision to format floats but discarding zero-padding

I'm trying to set precision (i.e. number of decimal places) of floats and long doubles to 10, but i don't want them zero padded. I.e.,
123456.789123456789 should give 123456.7891234568, but
123456 should not give 123456.0000000000, but rather 123456
So far i've narrowed it down to:
long double myNumber;
string myString;
ostringstream myStream;
myStream.setf(ios::fixed,ios::floatfield);
myStream.precision(10);
myStream << myNumber;
myString = myStream.str();
I've also tried fiddling with setfill(' ') and std::ws but can't really get the hang of it.
Any suggestions?
Don't use ios::fixed for ios::floatfield. That's what causes the padding. Simply use setprecision.

How can I parse double from a string?

I have the following code but it only converts strings to double. if the string contains a letter, it causes an error
while (cin >> s){
const char *c_ptr=s.c_str();
d = atof(c_ptr);
v.push_back(d);
}
I want to input a string like "a1.2 3 4b" and have the vector populated with "1.2 3 4"
What about this:
1) replace all chars in the string that aren't digits or decimal points by spaces
2) read doubles in a loop
since you got rid of the letters before parsing the doubles, they should no longer cause issues.

converting string to int

hello i have a problem i am trying to convert a string like "12314234" to int
so i will get the first number in the string.
from the example of string that is shown above i want to get '1' in int.
i tried :
string line = "12314234";
int command = line.at(0);
but it puts inside command the ascii value of 1 and not the number 1.
thanks in advance.
int command = line.at(0) - '0';
The numerical values of digit characters are required to be next to each other. So this works everywhere and always. No matter what character-set your compiler uses.
To convert a numerical character ('0' – '9') to its corresponding value, just substract the ASCII code of '0' from the result.
int command = line.at(0) - '0';
The standard function to convert an ascii to a integral value is strtol (string to long) from stdlib (#include <cstdlib>). For information, see http://en.wikipedia.org/wiki/Strtol and then the link off that page entitled Using strtol correctly and portably. With strtol you can convert one numeric character, or a sequence of numeric characters, and they can be multiple bases (dec, hex, etc).
i am trying to convert a string like "12314234" to int
Boost has a library for this:
int i = boost::lexical_cast<int>(str);
Sorry to join this party late but what is wrong with:
int value;
std::string number = "12345";
std::istringstream iss(number);
iss >> value;
If you are passing hexadecimal around (and who isn't these days) then you can do:
int value;
std::string number = "0xff";
std::istringstream iss(number);
iss >> std::hex >> value;
It's C++ and has none of this hackish subtraction of ASCii stuff.
The boost::lexical_cast<>() way is nice and clean if you are using boost. If you can't guarantee the string being passed will be a number then you should catch the thrown error.

How to convert a string representing decimal number in exponential form to float in Qt?

I have some decimal numbers in a text file represented in exponential form Eg: 144.2e-3. I want to store the values in float. In qt it returns "0" when i directly use the "number.toFloat()" method. Please help.
toFloat() should work. Check that your string contains only the number. If the string contains something else too, for example "144.2e-3 a", then the toFloat() returns 0. Note that also other numbers in the string will cause the conversion to fail, for example QString("144.2e-3 100").toFloat() will return 0.
Additional whitespace in the number string doesn't matter, but other characters do.
value = 3.91e+01;
double doubleValue;
stringstream valuestream(value);
valuestream >> doubleValue;
Using a stringstream you can convert exponential number to the datatype we require.
Use QString::toDouble.
Example:
bool ok;
float f = static_cast< float>( QString( "1234.56e-02" ).toDouble( &ok));