Split a 3-variable equation into doubles and characters in C++ - c++

I'm working on an assignment with equations, but I can't figure out how to input the different parts of the equation.
The equation is always formatted:
[double][x/y/z][sign][double][x/y/z][sign][double][x/y/z]=[double].
An example: 2.5y+4.7x+7z=46
To accomplish this, I tried using four double variables and six character variables.
double a,d,g,j;
char b,c,e,f,h,i;
so that the equation splits into the variables a b c d e f g h i, which I can then manipulate.
If there were whitespaces anywhere in the equation, I could have used istringstream to split them, but there aren't. I am not allowed to change the input file.
How can I put the numbers in doubles, and the letters/symbols in characters?

You can use istringstream and out of stream operator.
For example:
std::istringstream iss("2.5y+4.7x+7z=46");
double a,b,c,s;
char v1,v2,v3;
iss >> a; // read 1st koef
iss >> v1; // read 1st var's name
iss >> b; // read 2nd koef
iss >> v2; // read 2nd var's name
iss >> c; // read 3rd koef
iss >> v3; // read 3rd var's name
iss.ignore(); // skip '=' symbol
iss >> s; // read sum
Signs in equation is sign of relevant koefs.

Related

How can I limit the number of inputs while using istringstream for parsing (C++)

I should get multiples lines of input from cin and I need to take only 2 integers for each lines.
I used while(getline(cin, input)) and istringstream iss(input) to handle errors.
and I used the return value of iss >> d (double type variable), iss >> s (string type variable)
to handle the error like ( 1 2 extrainput ; that is, integer integer string)
because I thought that there is no other case that input value is neither double nor string
Is there any other elegant way to limit the number of inputs for each line?
(If there are more than 3 input values, it should be considered as error case)
The most elegant way I know is just to wrap it in operator>> with a custom type.
std::istream& operator>>(std::istream& stream, int_pair& pair) {
std::string tempstring;
if (!std::getline(stream, tempstring)) return stream;
std::stringstream line(tempstring);
int_pair temppair; //temp so that invalid end of line doesn't modify parameter
line >> temppair.first;
line >> temppair.second;
std::getline(line, tempstring);
if (!tempstring.empty()) stream.setstate(std::ios::failbit);
pair = temppair;
return stream;
}
Then usage becomes elegant
int main(){
int_pair one_pair;
std::cin >> one_pair;
std::cout << one_pair;
std::vector<int_pair> vector;
std::copy(std::istream_iterator<int_pair>(std::cin), {}, std::back_inserter(vector));
std::copy(vector.begin(), vector.end(), std::ostream_iterator<int_pair>(std::cout));
}
http://coliru.stacked-crooked.com/a/0ceb5b7922ac03b5
(I have a bug somewhere, the second call to getline on the input is failing and I don't know why, but the point is valid regardless)

C++: how to input values separated by comma(,)

int a, b, c, d;
There are 4 variables.
I want user to input 4 values, and each value is separated by comma(,)
Just like this:
stdin:
1,2,3,4
The following code works in C
scanf("%d,%d,%d,%d", &a, &b, &c, &d);
But how should I code in C++?
I’m kind of surprised at the incorrect commentary here[1].
There are two basic routes you can take:
handle the separator with a manipulator-style object, or
imbue the stream with a specialized facet that requires whitespace to include a comma.
I will focus on the first; it is typically a bad idea to imbue shared streams with weird behaviors even temporarily (“shared” in the sense that other parts of your code have access to it as well; a local stringstream would be an ideal candidate for imbuing with specialized behaviors).
A ‘next item must be a comma’ extractor:
#include <cctype>
#include <iostream>
struct extract
{
char c;
extract( char c ): c(c) { }
};
std::istream& operator >> ( std::istream& ins, extract e )
{
// Skip leading whitespace IFF user is not asking to extract a whitespace character
if (!std::isspace( e.c )) ins >> std::ws;
// Attempt to get the specific character
if (ins.peek() == e.c) ins.get();
// Failure works as always
else ins.setstate( std::ios::failbit );
return ins;
}
int main()
{
int a, b;
std::cin >> a >> extract(',') >> b;
if (std::cin)
std::cout << a << ',' << b << "\n";
else
std::cout << "quiznak.\n";
}
Running this code, the extract manipulator/extractor/whatever will succeed only if the next non-whitespace item is a comma. It fails otherwise.
You can easily modify this to make the comma optional:
std::istream& operator >> ( std::istream& ins, optional_extract e )
{
// Skip leading whitespace IFF user is not asking to extract a whitespace character
if (!std::isspace( e.c )) ins >> std::ws;
// Attempt to get the specific character
if (ins.peek() == e.c) ins.get();
// There is no failure!
return ins;
}
...
std::cin >> a >> optional_extract(',') >> b;
Etc.
[1] cin >> a >> b; is not equivalent to scanf( "%d,%d", ...);. C++ does not magically ignore commas. Just as in C, you must treat them explicitly.
The same for the answer using getline() and a stringstream; while the combination is valid, the actual problem is just shifted from std::cin to another stream object, and still must be treated.

C++ String stream ignore() not working

I was solving a question on hackerrank and came across this problem involving string streams.
https://www.hackerrank.com/challenges/c-tutorial-stringstream/problem
For Extracting data, hackerrank has given an example:
stringstream ss("23,4,56");
char ch;
int a, b, c;
ss >> a >> ch >> b >> ch >> c; // a = 23, b = 4, c = 56
However, when I try to export it to a vector, I have to escape the ',' using:
stringstream ss(str);
vector<int> vect;
int i;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
Why can't I use the extraction operation to get the required word here? Shouldn't the stream escape the ','(Sorry for the noob-level question)?
operator>> extracts the next delimited token, only so far as characters actually belong to the requested data type. So, when using operator>> to read an int, it will extract only digits, not letters, punctuation, etc. That means a comma following a number has to be read separately.
In the first example:
ss >> a reads the first int in the stream
then >> ch reads the comma after it
then >> b reads the next int
then >> ch reads the comma after it
then >> c reads the next int
In the second example:
ss >> i reads the next int in the stream, breaking the loop if fails or EOF
then ss.peek() checks if a comma exists (since the last int doesn't have one), and if found then ss.ignore() skips past it
goto #1
If you try to use operator>> to read a comma that doesn't exist, it will set the stream's eofbit state and fail the extraction. If you use while (ss >> i >> ch), the while would evaluate as false when the last int is reached. Even though ss >> i would succeed, >> ch would fail, and thus i would not be added to the vector.
In theory, you could replace if (ss.peek() == ',') ss.ignore(); inside the loop with char ch; ss >> ch instead. The end effect would be the same, at least for a string like "23,4,56". But, let's say you were given something like "23 4 56" instead. The first example would fail to handle that correctly, but the second example would handle it just fine when using peek()+ignore(), but not when using ss >> ch.
I think you can use this code to escape the ','
std::string valstr;
while (std::getline(ss, valstr, ','))
{
vect.push_back(std::stoi(valstr));
}

ignore to the n° whitespace with ifstream

I have a data file with a lot of columns of doubles but I want to read only two of them with a while loop
double x, y;
ifstream in;
double foo;
while( in >> foo ) {
in >> foo;
in >> foo;
...
in >> x;
in >> y;
... something with x and y
}
Two questions
1) There is a way to do the same thing without a fake double foo?
2) there is a way to do that without repeat in >> foo (or a for loop) like stream to the n° whitespace with a one-line code? There is a built-in function to skip to the n° whitespace?
What I would suggest instead is to read an entire row in a string and use a stringstream to manipulate it or just use something like find_last_of functions from the string class itself to pick out the last two columns and then convert it back to a double.

Start reading from a line containing a specific string

I'm trying to read some xyz coordinates from an input file.
This is the input file I have:
input.inp
POSITIONS
1.5 2.5 1.5 C
3.2 1.5 4.5 C
1.4 4.2 3.2 C
I want to write a function that searches the input file for the string containing " C" and then starting reading the coordinates from that line. How do I do this in c++? (I don't want to search for the the word POSITIONS, as that part of the input file may change later).
ifstream file("in");
string line;
while (getline(file, line)) {
if (line.find(" C") == string::npos)
continue;
istringstream ss(line);
double x, y, z;
ss >> x >> y >> z;
if (!ss)
continue; // error
// ok
}
You should read all the line to string variable. Analyse it and if you want to read this numbers you may use stringstream(<sstream>)
string a = "";
in >> a;
//Check whether the line has C at the end or other tests and then
stringstream b(a, stringstream::in);
double c1=0, c2=0, c3=0;
b >> c1 >> c2 >> c3;
Will read the numbers from that line.