【问题标题】:How to get data from user input?如何从用户输入中获取数据?
【发布时间】:2016-12-28 16:33:43
【问题描述】:

我有一个 QTableWidget,用户可以在其中输入各种样式的复数。 例如,复数 (-15 + 8.14i) 可以写成:

-15 + 8.14i

-15+8.14j

-15 +j 8,14

-15+ i8,14

i也可以是j! 这两个值都可以很大(它们被保存为双精度值),也可以为负值。它们可以写成“,”和“。” (所以 3.14 和 3,14 是相等的)。当用户输入错误的数字时应该有错误消息。

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);
}

这确实适用于基本输入。但不是非常快或可读或有用。它确实涵盖了输入的几种可能性(“-3 - 5,14”之类的东西不起作用)。有没有更简单的方法可以将字符串转换为复数而无需那么多循环和变量?

【问题讨论】:

    标签: c++ input qstring qtablewidgetitem


    【解决方案1】:

    单个regular expression 可以解析每一行:

    #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;
    }
    

    制作 (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)
    

    【讨论】:

    • **什么 std::istringstream iss(str);做? (抱歉重复发帖)
    • YVW 它从std::string 创建一个std::istringstream,然后使用正则表达式迭代器对其进行迭代。
    猜你喜欢
    • 1970-01-01
    • 2018-01-07
    • 2013-03-15
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多