简体   繁体   English

C ++从istream指定输入并对其进行测试

[英]C++ Specify input from istream and test it

I have a class basically representing a tuple (double x, doubly y) and I have overloaded the << operator so I can print the class. 我有一个基本上表示一个元组(双倍x,双倍y)的类,并且我已经重载了<<操作符,以便可以打印该类。 Now I want to do the same for >>, so that it only supports following formats: x, (x) and (x,y). 现在,我想对>>做同样的事情,因此它仅支持以下格式:x,(x)和(x,y)。

I jave following code: 我喜欢以下代码:

std::ostream & operator<< (std::ostream &output, tuple &c){
    output << "(" << c.x << "," << c.y << ")" << endl;
    return output;
}

std::istream & operator>> (std::istream & input, tuple &c){
    // Check for following patterns: x, (x) or (x,y)
}

Can I loop through input and regex match? 我可以遍历输入和正则表达式匹配吗? In that case how? 在那种情况下怎么办? Also how could I test that it's actually working, something like this std::cin >> "(10.2,5.5)" 还有我怎么能测试它是否真的在工作,像这样的std :: cin >>“(10.2,5.5)”
or do I need to read from a file to test? 还是我需要从文件中读取内容进行测试?

Edit: The answer given did solve this problem, but I wanted to add a way to test it as it might be to use of someone other than me: 编辑:给出的答案确实解决了这个问题,但是我想添加一种测试它的方法,因为它可能是使用我以外的人:

tuple x(6,2);
stringstream ss;
ss << x;
ASSERT_EQUALS(ss.str(), "(6,2)\n");

Regex would just be unnecessary for a simple input task such as this. 对于这样的简单输入任务,正则表达式将是不必要的。 Here is how I would do it, without any checking for valid input or not, just parsing: 这是我的方法,无需解析任何有效输入,只需解析即可:

std::istream & operator>> (std::istream & input, tuple &c){
    // Check for following patterns: x, (x) or (x,y)
    char firstCharacter;
    input >> firstCharacter; // See what the first character is, since it varies

    if (firstCharacter == '(')
    {   // The simplest case, since the next few inputs are of the form n,n)
        char delimiters;
        input >> c.x >> delimiters >> c.y >> delimiters;
        //        N        ,           N        )
        // You also here have to check whether the above inputs are valid, 
        // such as if the user enters a string instead of a number
        // or if the delimeters are not commas or parentheses
    }
    else if (isdigit(firstCharacter) || firstCharacter == '-')
    {   //                               For negative numbers
        char delimiters;
        input.unget(); // Put the number back in the stream and read a number
        input >> c.x >> delimiters >> delimiters >> c.y >> delimiters;
        //        N           ,         (            N          )
        // You also here have to check whether the above inputs are valid, 
        // such as if the user enters a string instead of a number
        // or if the delimeters are not commas or parentheses
    }
    else
    { 
        // Handle some sort of a parsing error where the first character 
        // is neither a parenthesis or a number
    }

    return input;
}

A little late to the party, but here is regex solution. 开派对有点晚,但是这里是正则表达式解决方案。 While it is not pretty, it allows for negative numbers input as well as scientific notation. 它虽然不漂亮,但允许输入负数以及科学计数法。 It also will tolerate spaces between numbers: 它还可以容忍数字之间的空格:

#include <iostream>
#include <regex>
#include <tuple>

std::istream &operator>> (std::istream &input, std::tuple<double, double> &t)
{
    std::smatch m;
    std::string s;
    if (std::getline(input, s))
    {
        if (std::regex_match(s, m, std::regex(R"(\s*([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)\s*)"))) //x
            t = std::move(std::make_tuple(std::stod(m[1]), 0.0));
        else if (std::regex_match(s, m, std::regex(R"(\s*\(\s*([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)\s*\)\s*)"))) //(x)
            t = std::move(std::make_tuple(std::stod(m[1]), 0.0));
        else if (std::regex_match(s, m, std::regex(R"(\s*\(\s*([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)\s*,\s*([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)\s*\)\s*)"))) //(x,y)
            t = std::move(std::make_tuple(std::stod(m[1]), std::stod(m[2])));
    }
    return input;
}


int main() 
{
    std::tuple <double, double> t;
    std::cout << "Enter data in format num, (num) or (num1,num2): ";
    std::cin >> t;
    std::cout << "Tuple 0: " << std::get<0>(t) << std::endl;
    std::cout << "Tuple 1: " << std::get<1>(t) << std::endl;

    return 0;

} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM