I already recommended to write a small parser (e.g. based on a syntax diagram like shown in SO: How to rearrange a string equation?).
In the following, I made a simpler approach following the way tried by OP (and without sketching a syntax diagram).
I.e. the input stream operator for my helper type Complex
tries to read two numbers.
If first number is followed by an i
this is actually the second number and input ends.
If second number is not followed by an i
it's actually not the second but missing and stream is reset to the position before.
The sample code:
#include <cmath>
#include <iomanip>
#include <iostream>
#include <sstream>
struct Complex {
float re, im;
};
std::istream& operator >> (std::istream &in, Complex &value)
{
value.im = 0;
// read 1st value
if (!(in >> value.re)) return in; // ERROR!
// check whether next char is 'i'
char c; if (!(in >> c)) return in; // End of Input
if (c == 'i') {
value.im = value.re; value.re = 0.0;
return in;
}
in.unget();
// remember start of imaginary
std::streampos pos = in.tellg();
if (!(in >> value.im)) return in; // ERROR or end of input
if (!(in >> c) || c != 'i') { // ERROR or premature end of input
value.im = 0.0;
in.clear();
in.seekg(pos);
return in;
}
return in;
}
std::ostream& operator << (std::ostream &out, const Complex &value)
{
return out << value.re << (std::signbit(value.im) ? "" : "+") << value.im << 'i';
}
int main()
{
// samples:
std::string samples[] = {
"1.23+45i",
" 1.23 +45i",
" 1.23E3 +45e-1i",
"Completely wrong!",
// multiple numbers in one line
"1.23+45i 1.23 +45i 1.23E3 +45e-1i",
"1.23 2.34-1i -2i"
};
int line = 1;
for (const std::string &sample : samples) {
std::cout << "Parse line " << line++ << " '" << sample << "':\n";
std::istringstream in(sample);
std::cout << "Got:";
Complex value;
while (in >> std::skipws >> value) std::cout << ' ' << value;
std::cout << '\n'
<< "Stopped with "
<< (in.eof() ? "End of Input" : !in.good() ? "Error" : "???")
<< '\n';
}
return 0;
}
Compiled and tested:
g++ (GCC) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Parse line 1 '1.23+45i':
Got: 1.23+45i
Stopped with End of Input
Parse line 2 ' 1.23 +45i':
Got: 1.23+45i
Stopped with End of Input
Parse line 3 ' 1.23E3 +45e-1i':
Got: 1230+4.5i
Stopped with End of Input
Parse line 4 'Completely wrong!':
Got:
Stopped with Error
Parse line 5 '1.23+45i 1.23 +45i 1.23E3 +45e-1i':
Got: 1.23+45i 1.23+45i 1230+4.5i
Stopped with End of Input
Parse line 6 '1.23 2.34-1i -2i':
Got: 1.23+0i 2.34-1i 0-2i
Stopped with End of Input
Live Demo on coliru
While fiddling I still realized some weaknesses like e.g. 1.23 + 45i
cannot be read because of space between +
and 45
. So, with even more code this could be improved for sure. On the other hand... OP didn't specify where spaces should be accepted and where not.