How to get data from user input?

118 views Asked by At

I have a QTableWidget where the user inputs complex numbers in various styles. For example, the complex number (-15 + 8.14i) can be written like:

-15 + 8.14i

-15+8.14j

-15 +j 8,14

-15+ i8,14

i can also be j! Both values can be big (they are saved as double) and also negative. They can be written with "," and "." (so 3.14 and 3,14 are ment to be equal). There should be an error message when the user enters the number incorrectly.

CKomplex fromString(QString str) { // ckomplex is my custom class for complex numbers
    double numReal, numImag;

    QString strNew = "";
    // delete all spaces
    for (int i= 0; i< str.length(); i++) {
        if (!str[i].isSpace()) {
            strNew += str[i];
        }
    }


    QString part1 = "";
    int index;
    // get the first number
    for (int i= 0; i < strNew.length(); i++) { // iterate string
        if (strNew[i] != '+' && strNew[i] != '-') {
            part1 += strNew[i];
        } else { // e.g.: 5 + 3j -> the loop is at the "+"
            if (i != 0) {
                index = i; // save index at "+" to start for next number
                break;
            }
        }
    }
    numReal = part1.toDouble();


    QString part2 = "";
    // get the second number
    for (int i= index; i < strNew.length(); i++) {
        if (strNew[i].isDigit() || strNew[i] == '+' || strNew[i] == '-' || strNew[i] == '.' || strNew[i] == ',') { // ignore j or i
            part2 += strNew[i];
        }
    }
    numImag = part2.toDouble();

    return CKomplex(numReal, numImag);
}

This does work for basic input. But is not very fast or readable or useful. And it does cover just few possibilities of input (stuff like "-3 - 5,14" doesnt work). Is there an easier way to convert the string into a complex number without having so much loops and variables?

1

There are 1 answers

2
wally On

A single regular expression could parse each of the lines:

#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <regex>
#include <iostream>
#include <iomanip>
#include <exception>

class CKomplex {
public:
    CKomplex(double numReal, double numImag) : numReal{numReal}, numImag{numImag} {}
    double numReal;
    double numImag;
};

auto input_text{
R"(-15 + 8.14i
-15+8.14j
-15 +j 8,14
-15+ i8,14
bad line here
+23.4-j24
-35+42.3j
+24i
+2.342j
+24.523-i 432,52
24.523-i 432,52
23.4-j24
35+42.3j
24i
2.342j)"};

CKomplex fromString(std::string str) {
    double numReal{};
    double numImag{};

    std::regex r{R"(([+-]?) *([ij]?) *(\d+)[.,]?(\d*)([ij])?)"}; // 6 groups
    std::istringstream iss(str);
    auto it = std::sregex_iterator(str.begin(), str.end(), r);
    auto end = std::sregex_iterator();
    if(it == end || it->size() != 6)
        throw std::runtime_error("Could not parse line containing the following text: " + str);
    for(; it != end; ++it) {
        auto match = *it;
        auto sign = match[1].str();
        auto iorj_pre = match[2].str();
        auto decimal = match[3].str();
        auto fraction = match[4].str();
        auto iorj_post = match[5].str();

        double val{sign == "-" ? -1.F : 1.F};
        val *= std::stod(decimal + "." + fraction);
        if(iorj_pre == "i" || iorj_pre == "j" || iorj_post == "i" || iorj_post == "j")
            numImag += val;
        else
            numReal += val;
    }
    return{numReal,numImag};
}

std::ostream& operator<<(std::ostream& os, const CKomplex& complex_number)
{
    os << std::showpos << "(" << complex_number.numReal << " " << complex_number.numImag << "i)";
    return os;
}

int main()
{
    std::istringstream input_stream{input_text};

    for(std::string line{}; std::getline(input_stream, line);) {
        try { std::cout << std::setw(20) << line << ": " << fromString(line) << '\n'; }
        catch(std::exception& e) { std::cout << e.what() << '\n'; }
    }
    return 0;
}

Produces (live demo):

         -15 + 8.14i: (-15 +8.14i)
           -15+8.14j: (-15 +8.14i)
         -15 +j 8,14: (-15 +8.14i)
          -15+ i8,14: (-15 +8.14i)
Could not parse line containing the following text: bad line here
           +23.4-j24: (+23.4 -24i)
           -35+42.3j: (-35 +42.3i)
                +24i: (+0 +24i)
             +2.342j: (+0 +2.342i)
    +24.523-i 432,52: (+24.523 -432.52i)
     24.523-i 432,52: (+24.523 -432.52i)
            23.4-j24: (+23.4 -24i)
            35+42.3j: (+35 +42.3i)
                 24i: (+0 +24i)
              2.342j: (+0 +2.342i)