C ++将字符串转换为typedef或istream重载

时间:2012-05-17 17:16:54

标签: c++ class templates typedef operator-keyword

我有一个类模板,除其他外,它应该重载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()函数?

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分: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 不会(您需要手动检查)。

答案 2 :(得分: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;

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

stringstream(tmp) >> val;

创建一个临时字符串流并尝试在其上调用operator>>。好吧,operator>>有两种std::istream

  • std::istream成员函数接受临时(r值)和l值std::istream对象
  • 通过引用非常量来取std::istream的自由站点,它不接受r值。 (在C ++ 11中,它也可以接受std::istream&&允许r值)。

因此,上述语句只能流式传输到operator>>中有成员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
    }
}