1

我有一个类模板,除其他外,它应该重载 istream,以便它接受用户的输入并将其添加(推送)到一个包含 T 类型元素的向量中。

    friend istream &operator>> (istream &in, Set<T> &s)
    {
        int ctr = 0;
        string tmp;
        T val;
        while (true) {
            cout << "\tElement #" << ctr + 1 << ": ";
            getline (in, tmp);
            if (tmp == "\0") break;
            // MISSING CODE HERE: "Convert" tmp into val
            s.add(val);
            ctr = s.size();
        }
        return in;
    }

这适用于Set<string>,但我需要找到一种方法使其也适用于任何原始数据类型,Set<integer>例如 。

我试着做

stringstream(tmp) >> val

但这不适用于Set<string>.

我猜输入需要作为字符串读入;那么,如何将输入字符串转换为 T 类型以将其传递给 .add() 函数?

4

3 回答 3

1

如果它不是字符串,您可以使用一个stringstream对象(从创建)来提取正确的值。请注意,如果您需要的不仅仅是内置类型(例如) ,则tmp必须覆盖operator>>ostreamint

convert()或者,您可以为遇到的每个函数定义一个函数的重载,T以提供从字符串tmp到所需类型的正确转换。将根据您的模板参数选择适当的重载(如果存在)。

于 2012-05-17T17:31:06.503 回答
1

您可以使用boost::lexical_cast按字典顺序将字符串转换为其他类型。

template<class T>
friend istream &operator>> (istream &in, Set<T> &s) {
    int ctr = 0;
    string tmp;
    T val;
    while (true) {
        cout << "\tElement #" << ctr + 1 << ": ";
        getline (in, tmp);
        if (tmp == "\0") break;
        val = boost::lexical_cast<T>(tmp);
        s.add(val);
        ctr = s.size();
    }
    return in;
}

或者,您可以使用std::istringstream.

std::istringstream sstream(tmp);
sstream >> val;

请注意,boost::lexical_cast如果转换不成功,则会抛出异常,并且std::istringstream 不会(您需要手动检查)。

于 2012-05-17T17:34:05.377 回答
0

您可能希望解决代码中的一些问题:

getline (in, tmp);

即需要检查返回值:

if(!getline (in, tmp))
    // handle end-of-file or read failure
// read okay, tmp contains the read line

下一个:

if (tmp == "\0") break;

在文本文件中嵌入零并不常见。可能是这块试图检测文件结束条件,应该通过检查getlineorif(in)语句的返回值来处理。

stringstream(tmp) >> val;

这会创建一个临时字符串流并尝试对其进行调用operator>>。好吧,有两种operator>>for std::istream

  • std::istream接受临时(右值)和左值std::istream对象的成员函数
  • 独立的那些std::istream通过引用非常量,不接受 r 值。(在 C++11 中,它也可以接受它作为std::istream&&允许 r 值)。

operator>>因此,上述语句只能流式传输到具有 in 成员的内置类型std::istream

因此,该语句可以替换为:

std::istringstream ss(tmp);
ss >> val;

那将需要再次进行错误处理以检查是否将整个str解析为val,因此,正如其他人在这里所说的那样,为您进行错误检查更容易使用boost::lexical_cast<>

val = boost::lexical_cast<T>(tmp);

如果您不坚持阅读整行,而是阅读空格分隔的标记,则循环可能如下所示:

template<class T>
friend std::istream &operator>>(std::istream &in, Set<T> &s) {
    int ctr;
    T val;
    while(in >> val) {
        ctr = s.size();
        std::cout << "\tElement #" << ctr + 1 << ": ";
        s.add(val);
    }
    // end-of-file or parsing failure
    if(!in.eof()) {
        // handle failuer to parse or read error
    }
}
于 2012-05-17T17:41:52.610 回答