Appending long double literal suffix to user inputs in c++ - c++

I have a class that has a long double vector:
MyClass{
vector<long double> myvec;
public:
MyClass(){ //Constructor }
// Some memeber functions that operate on the vector
};
I have overloaded the input operator an I'm taking input from a user that are then pushed into the vector. The problem that I'm having is if the user inputs a number that is out of range of double, the code should append append the long double suffix to the input with out the user having too. This is what I have tried so far:
long double input;
...
input = (long double)(input + "L");
myvec.push_back(input);
I thought of using scanf, but I'm not sure how safe that is to use when overloading the input operator.

Use std::stold to convert input text to long double. There is no need for a suffix; stold will do it right. The suffix is needed in source code to tell the compiler what type the text represents. When you're reading from an external source the compiler isn't involved, so you have to sort out the type yourself.

Suffixes are only for literal values, e.g. auto x = 12345.0L. You use them to prevent implicit conversions since the default type of a floating point literal is double.
You can't use them on a named variable.
The question is how you get your input?

Related

Is there a function similar to stoi that would work for a template class?

I've created a class for complex numbers for an assignment last week and our next assignment is to modify this class to be a template class. Part of the assignment was overloading the extraction operator, and originally when only dealing with int, I took the whole input line as a string and made substrings for the real and imaginary parts, then I used stoi to convert the parts to ints which I could store (This is what my professor suggested doing). However, now that this is is a template class stoi no longer works if the type being used is double, float, etc. Is there a function that works similarly but across different types? Or possibly another solution altogether that may work better?
I tried using if statements to detect what type is being used and then using stoi, stod, etc. accordingly however, this seems less than ideal because it only works for the types I explicitly define, and I'm sure this isn't what they're looking for.
template <class T>
istream& operator>>(istream& in,MyComplex<T> &num){
string inString;
getline(in, inString);
T test = 3.33;
if(test != 3.33){
//convert using stoi
}
else if(test == 3.33){
//convert using stod
}
//etc.
}
I left out what's inside the brackets because it's very long and doesn't change the fact that I can only define for a finite amount of data types. Thank you in advance for any help!
I would recommend using the input stream directly. It seems like your input format is 2.3 + 5i, so you can use the following code:
double a,b;
char c;
in >> a >> c >> b; // c eats the +; let's the i in the in
in >> c; // eats the i
Note that then we also can use c two times in the same line, I just wanted space for my comments so I put it on the next.
A more general note to your code:
The "right" way to check what type T is (or maybe just what attributes the type has, since you probably don't need to differentiate between say int and long), is to use type traits.
But, for having completely different implementations for different types, you should use different implementations, so declare a method that takes MyComplex<double>, one that takes MyComplex<int>, etc.

String to long double conversion in c++98

Anyone know how to convert a string to long double? For example lets say we have
string S = "3.236568949"
I want to take what inside the string and convert it to a long double variable x.
Note: In c++11 their exist stold function do so but I'm using c++98 not c++11.
Also I don't need to cout the string with certain precision because I know setprecision function already but what I want is just to convert to long double. In other wards,I need x to equal the exact number inside the string and not an approximated version of the number. Finally I want to tell you that my string contains a valid number.
you can use the C function :
#include <stdlib.h>
int main(){
char* convertme="3.236568949";
double converted=atof(convertme);
return 0;
}
You can use a std::stringstream to convert the string into a long double. The std::stringstream acts just like cin but instead of getting the input from the user you load it into the stream with a std::string. That looks like
std::string data = "3.236568949"
std::stringstream ss(data);
long double ld;
ss >> ld;
Do note that when dealing with floating point numbers you are going to have to deal with imprecision. For more on this see Is floating point math broken?
You can use strtold() function from C99:
long double d = strtold( str.c_str(), nullptr );
to convert std::string to long double. Though floating point representation is approximate so nobody would guarantee that value after conversion is exactly the same is in your string.

converting to convert a string to double with limitation

I'm using c++ and I'm trying to convert a string to double, the string is given to me as an input in the form: "xx.yy", and it should stay that way, meaning no more than two digits after the dot.
I've tried atof and strod but outcome was no good, plus i can't use anything to spectacular' because it's for a course and no one will belive me
str_db = strtod(ptr, NULL);
item->price = str_db;
str_db is type double.
Thank you.

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

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.