C++ 指定来自 istream 的输入并测试它
C++ Specify input from istream and test it
我有一个 class 基本上表示一个元组(双 x,双 y),我重载了 << 运算符,所以我可以打印 class。现在我想对 >> 做同样的事情,所以它只支持以下格式:
x, (x) 和 (x,y).
我有以下代码:
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)
}
我可以循环输入和正则表达式匹配吗?那怎么办呢?
另外我怎么能测试它是否真的有效,就像这样
std::cin >> “(10.2,5.5)”
还是我需要读取文件进行测试?
编辑:
给出的答案确实解决了这个问题,但我想添加一种方法来测试它,因为它可能会使用除我以外的其他人:
tuple x(6,2);
stringstream ss;
ss << x;
ASSERT_EQUALS(ss.str(), "(6,2)\n");
正则表达式对于像这样的简单输入任务来说是不必要的。这是我的做法,不检查是否有效输入,只是解析:
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;
}
聚会有点晚了,但这是正则表达式解决方案。虽然它不漂亮,但它允许输入负数和科学记数法。它还将容忍数字之间的空格:
#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;
}
我有一个 class 基本上表示一个元组(双 x,双 y),我重载了 << 运算符,所以我可以打印 class。现在我想对 >> 做同样的事情,所以它只支持以下格式: x, (x) 和 (x,y).
我有以下代码:
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)
}
我可以循环输入和正则表达式匹配吗?那怎么办呢?
另外我怎么能测试它是否真的有效,就像这样
std::cin >> “(10.2,5.5)”
还是我需要读取文件进行测试?
编辑: 给出的答案确实解决了这个问题,但我想添加一种方法来测试它,因为它可能会使用除我以外的其他人:
tuple x(6,2);
stringstream ss;
ss << x;
ASSERT_EQUALS(ss.str(), "(6,2)\n");
正则表达式对于像这样的简单输入任务来说是不必要的。这是我的做法,不检查是否有效输入,只是解析:
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;
}
聚会有点晚了,但这是正则表达式解决方案。虽然它不漂亮,但它允许输入负数和科学记数法。它还将容忍数字之间的空格:
#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;
}