C++ String to Double parsing with exceptions? - c++

In java, if I wanted to create some application which could receive both doubles and strings as appropriate input, I would probably do the following:
String input = getInput();//
try {
double foo = Double.valueOf(input);
//Do stuff with foo here
} catch (NumberFormatException e) {
//Do other validation with input
}
How would you go about doing that in c++? atof() returns 0.0 for invalid input, but how would you differentiate that from a valid double of "0.0"? As an aside, I can only include <iostream>, <string>, <cstdlib>, and <cassert> in this project. I'm assuming I need to use cin in some way, but how can you grab the original input after cin fails to parse some string as a double?
Edit: I could probably use the following, but as I said before, I'm not allowed to import <sstream> on this assignment for some reason
string input;
getline(cin, input);
double x;
istringstream foo(input);
foo >> x
if(cin){
//do manipulations with x
}
else{
//since it's not a number, check if input is a valid command etc..
}

Exceptions should be reserved for exceptional situations. While you certainly can abuse them like this, it's a lousy idea -- clearly you're pretty much expecting things other than doubles, so treating it as an exception doesn't make any real sense.
The only real question is the exact circumstance under which you want the input treated as a string. Just for example, if the input string was something like "1.23e2 non-numeric data", do you want to just use the "1.23e2" as a number, or do you want to treat the whole thing as a string?
Either way, you'd want to us strtod for the conversion -- the difference is only how you react to what it returns. In particular, strtod takes two parameters instead of just one like atof does. The second parameter is a pointer to pointer to char. Assuming you pass a non-NULL pointer, strtod will set it to point at the last character in the input string that it successfully converted. If it's pointing to the beginning of the input string, nothing was converted. If it's pointing to the end, everything was converted. If it's somewhere in between, part of the string converted, and part didn't.
For the moment, I'm going to assume that you want a double value holding whatever number could be converted at the beginning of the string, and whatever couldn't be converted treated as a string:
#include <stdlib.h>
#include <stdio.h>
int main() {
char input[] = "12.34 non-numeric data";
char *string;
double value = strtod(input, &string);
printf("Number: %f\tstring: %s\n", value, string);
return 0;
}

C++ streams associate the good, bad and fail state flags. These are stored in ios_base::goodbit, ios_base::badbit and ios_base::failbit respectively, but are commonly accessed through ios::good(), ios::bad() and ios::fail(). There's also ios_base::eofbit and ios::eof() but let's ignore that for the moment.
If parsing fails then the bad bit raises. Also, stream objects are convertible to a boolean-compatible type. If a stream is in a good state, then the statement
if( stream )
evaluates stream as true. Otherwise, it evaluates it as false. With this at hand, grabbing a value from standard input boils down to this:
#include <iostream>
// ...
double d = 0;
if ( std::cin >> d ) {
// input is a double. handle that here.
} else {
// input isn't a double. handle that here.
}

try "strtod" in stdlib.h

The C++ standard library seems to avoid exceptions for a lot of things that people might expect them, and this may not be the answer that you want to hear but parsing doubles isn't exactly rocket science so maybe it'd be ok to do it "by hand"?
One note if you do this, you'll probably want to collect it into an integer and then convert to a double and divide by 10^number_of_digits_after_decimal_point.

You could have a look at boost::lexical_cast, which would allow you to write pretty much the equivalent of the Java code:
string input;
getline(cin, input);
try {
double x = boost::lexical_cast<double>(input);
//Do manipulations with x
} catch (boost::bad_lexical_cast &) {
//Do other validation with input
}

Related

Distinguishing between integers and doubles in a file

I'm quite new to reading and writing to files. But basically, I have an assignment where part of it requires me to determine whether a line from a file is an integer or double.
This is the part of the assignment I need help on:
Open the text file and read it's contents one line at a time. Determine if the line read from the file is a double or an integer. You are to place the integers in a vector called iNumbers and the doubles in a vector called dNumbers. The vector iNumbers should hold pointers to the Integer class and dNumbers should hold pointers to the Double class. When you add a value to one of the vectors you should use new and call the constructor that takes a string. For example:
iNumbers.push_back(new Integer("12.23"));
Sample of the file:
12
20
80.5
99.345
70
From what I understand, I think I write code that will read the lines in the file and if they have a "." then those will be doubles, but I am not sure as how to start with that.
Any help as to how I should get started would be very appreciated and thanks in advance.
Beware, in C++ (and not only C++), 1e4 is also double (with value of 10000).
If this is not allowed in the task (and finding . in the number is sufficent), then I would create std::ifstream for the file, read from it using std::getline into a std::string s, then in the string I would s.find('.') and if it is to be found (the result of find != s.npos, pass it into dNumbers as new Double(s), if such constructor exists for your class.
To be pedantic, in the general case the best way to figure out whether or not a string is an integer is to try to convert it to an integer without any error or leftover characters.
Here is a very simple method to do just that (for any type):
template <typename T>
T string_to( const std::string& s )
{
T value;
std::istringstream ss( s );
ss >> value >> std::ws;
if (!ss.eof()) throw std::invalid_argument("T string_to()");
return value;
}
You can now test for any standard integer vs double:
int n;
double d;
try {
n = string_to <int> ("12.3");
// it's an int
}
catch (...) {
try {
n = string_to <double> ("12.3");
// it's a double
}
catch (...) {
// it is neither integer nor double
}
}
If desired, you can specialize the int types to handle things like "0xF3" by unsetting the basefield: ss.unsetf(std::ios::basefield);.
Hope this helps.
Here is a straightforward way you could accomplish this task:
read from the stream using std::getline to a std::string
use std::stof and std::stoi with this string as the parameter to determine the type - if they throw std::invalid_argument or std::out_of_range, conversion could not be done
push_back to one of the arrays, depending on which type was
Glad to see that we are in the same class...
There is more to the assignment that you left out. We have our double.cpp and our integer.cpp files that include constructors that take a string as a parameter if you did your program correctly, that is. So the iNumbers.push_back(new Integer("12.23")); is basically saying "iNumbers" - the name of the vector, ".push_back" - the function that puts the string value onto the stack, "new Integer" - allocating memory for the type Integer, and "12.23" - the actually double value that was used as an example in the form of a string taken from the .txt file.
What you need to do is look through his lecture slides that include the content about I/O files and you should be fine. We even did an example in class.
As far as your basic question about integer and double types, its very simple and I have no idea how you got through the past assignments without knowing the difference, an integer does not have a decimal point and a double does. Now there may be a more complicated definition for an integer and a double type but for Stevenson's class this is the only thing you should think about. Forget what you learned in your math class about integers. The definition is not the same for this class.
Best of luck...
See you in class
-C

C++ int function. How do I detect false when zero is a valid return value?

I have a function that parses some input from std::cin and returns an integer value on success. I need to detect, based on the return value, if something went wrong when parsing input. Zero is a valid return. What can I use to differentiate between valid zero and "bad input"?
If I need to post code as an example, just let me know. Thanks!
[EDIT]
int parseInput(){
int calculatedValue = 0;
bool parseOk = true;
/* Parse cin for valid input.*/
if (parseOk) {
/* Perform calculation. Can be zero */
}
return calculatedValue; // Any integer is valid
}
This would be the perfect job for std::optional. Your best alternative, with regards to notify at return value, is to implement a similar class.
Alternatively, you should really use an exception. Exceptions are made exactly to notify the user of your function that something went wrong.
You can use an boolean flag for checking if something went wrong, it is common practice (for instance, Qt library uses it) to do something like:
int getIntegerStuffFromInput(bool & ok);
or
bool getIntegerStuffFromInput(int & value);
When you read numbers from std::cin, the most important thing is not to read directly into an int. Instead, you use std::getline to read a whole line of input into an std::string. This way you can detect wrong input much more easily.
Once the line has been entered, you convert the resulting std::string to an int.
std::string input_line;
std::getline(std::cin, input_line);
// input_line now contains a whole line of input
In C++11, you just use std::stoi for the conversion:
int const input = std::stoi(input_line);
This function will throw an exception if the string cannot be converted to an integer number.
In pre-C++11, you use std::istringstream:
std::istringstream is(input_line);
int input = 0;
is >> input;
The following code then checks if the line could be correctly converted to an integer number or not:
if (!is)
{
// error
}
"What can I use to differentiate between valid zero and "bad input"?"
You have basically three choices
If you need to handle all integers as a valid return value:
Throw an exception, that can be handled outside from your function call
Have a dedicated output parameter passed by reference, and return bool from your function, false indicates bad input.
If negative integers aren't a valid return value:
Just return a negative value and test for result < 0.

Scanf function with strings

I need to read input from user. The input value may be string type or int type.
If the value is int then the program insert the value into my object.
Else if the value is string then it should check the value of that string, if it's "end" then the program ends.
Halda h; //my object
string t;
int tint;
bool end=false;
while(end!=true)
{
if(scanf("%d",&tint)==1)
{
h.insert(tint);
}
else if(scanf("%s",t)==1)
{
if(t=="end")
end=true;
else if(t=="next")
if(h.empty()==false)
printf("%d\n",h.pop());
else
printf("-1\n");
}
}
The problem is that scanning string doesn't seem to work properly.
I've tried to change it to: if(cin>>t) and it worked well.
I need to get it work with scanf.
The specifier %s in the scanf() format expects a char*, not a std::string.
From C11 Standard (C++ Standard refers to it about the C standard library):
Except in the case of a % specifier, the input item (or, in the case of a %n directive, the
count of input characters) is converted to a type appropriate to the conversion specifier. If
the input item is not a matching sequence, the execution of the directive fails: this
condition is a matching failure. Unless assignment suppression was indicated by a *, the
result of the conversion is placed in the object pointed to by the first argument following
the format argument that has not already received a conversion result. If this object
does not have an appropriate type, or if the result of the conversion cannot be represented
in the object, the behavior is undefined.
Anyway, here there's is no real reason to prefer the C way, use C++ facilities. And when you use the C library, use safe functions that only reads characters up to a given limit (just like fgets, or scanf with a width specifier), otherwise you could have overflow, that leads again to undefined behavior, and some errors if you're luck.
That's a really bad way to check for end-of-input. Either use an integer or use a string.
If you choose string, make provisions to convert from string to int.
My logic would be to first check if it can be converted to integer. if it can be, then continue with the logic. If it can't be(such as if it's a float or double or some other string) then ignore and move on. If it can be, then insert it into Halda's object.
Sidenote: Do not use scanf() and printf() when you're working with C++.
Assuming string refers to std::sring this program doesn't have defined behavior. You can't really use std::string with sscanf() You could set up a buffer inside the std::string and read into that but the string wouldn't change its size. You are probably better off using streams with std::string (well, in my opinion you are always better off using streams).

string input, how to tell if it is int?

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
}

how to declare variable before you know what data type it is?

I'm new to c++ coming from a python background.
If I want input from a user and then I want to check what data type the input is (e.g. integer or float), how is it possible for me to declare the variable that I want to assign the user's input to?
Short answer: You can't.
Long answer: You can't. C++ is a statically typed language, meaning that you have to define the type at compile time. Python is dynamically typed, so the type of an object can change from line to line.
If you want to get some input from the user though, you can just use a string though.
For example, if you want to get integer input from the user:
int n;
std::cin >> n;
Float input:
float x;
std::cin >> x;
And so forth. Do note in those two cases, if the user inputs something other than an integer or float, you'll have to check the flags of std::cin to see if there was an error.
But you need to tell the user "Input integer now" or "Input float now". You can't just accept some arbitrary type. Instead, design your code so you have alternative code paths for either integer or floating point input. Or force one or the other, and print an error when they give the wrong type of input.
Don't write your code like you're in Python. Idiomatic Python code is not idiomatic C++ code, and the way you accomplish things will not look the same.
In C++ the way to get arbitrary input would look like:
std::string input;
std::cin >> input;
if (IsInteger(input))
{
// do stuff with integer
}
else if (IsFloat(input))
{
// do stuff with float
}
else
{
std::cout << "Bad Input!" << std::endl;
}
Edit: As MSalters pointed out in a comment, You can actually use boost::lexical_cast<T>(expr) to cast a string representation to some type T (Where T is usually something like int, float, double, etc). Do note, you'll probably still have to do some checking to see if expr is actually an integer, float, or otherwise.
When you get input from the user, it will arrive as a string. For example:
std::string inp;
std::cin >> inp;
Then, you take the contents of inp (which is whatever the user typed), and look inside it to see what characters it contains. At that point you could make decisions based on whether it contains (a) all digits, (b) digits and a decimal point, or (c) something else entirely.
Much better to collect a string from the user and then parse it.
This question is the place to look for an answer:
How to parse an int from a string
C++ is a statically typed language. All the variable types must be known at compilation time.
Python is dynamically typed language and on the contrary, c/c++ are statically typed languages. It is not possible to find the the type and declare at run time.