2016-12-28 71 views
0

我有一个QTableWidget,其中用户输入各种样式的复杂数字。 例如,复数(-15 + 8.14i)可以写成像:如何从用户输入中获取数据?

-15 + 8.14i

-15 + 8.14j

-15 + J 8,14

-15+ i8,14

也可以Ĵ! 这两个值都可能很大(它们被保存为双倍),也是负值。它们可以用“,”和“”来书写。 (所以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”这样的东西不起作用)。有没有更简单的方法来将字符串转换为复数,而没有太多的循环和变量?

回答

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) 
+0

感谢您的代码, –

+0

**什么的std :: istringstream ISS(STR) ;做? (sry for double post) –

+0

YVW它从'std :: string'创建一个'std :: istringstream',然后使用regex迭代器进行迭代。 – wally