【问题标题】:C++ convert string to typedef OR istream overloadC++ 将字符串转换为 typedef 或 istream 重载
【发布时间】:2012-05-17 17:16:53
【问题描述】:

我有一个类模板,除其他外,它应该重载 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&lt;string&gt;,但我需要找到一种方法使其也适用于任何原始数据类型,例如Set&lt;integer&gt;

我试过了

stringstream(tmp) >> val

但这不适用于Set&lt;string&gt;

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

【问题讨论】:

  • 请显示您的所有代码,而不仅仅是这个子集。有点不清楚到底发生了什么。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您可以使用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 不会(您需要手动检查)。

    【讨论】:

    • 谢谢!谢谢你!!谢谢你!!!我不想碰 Boost,因为我不确定它是否可以在我的学校计算机上使用,所以我选择了“替代”。伙计,如果你是一个漂亮的女孩,我会给你一个大大的吻。哎呀,无论如何我可能会这样做! :D 说真的,我不敢相信我没有尝试过。
    • @Michael 如果这个答案对你有帮助,你可以点击它旁边的灰色复选标记来接受它,这样以后的人就知道去哪里找了。
    【解决方案3】:

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

    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&gt;&gt;。嗯,std::istream 有两种operator&gt;&gt;

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

    因此,上述语句只能流式传输到 std::istream 中有成员 operator&gt;&gt; 的内置类型。

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

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

    这需要再次进行错误处理以检查整个str 是否被解析为val,因此,正如其他人所说,使用boost::lexical_cast&lt;&gt; 为您进行错误检查更容易:

    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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-06-26
      • 2013-09-08
      • 2020-08-27
      • 2010-11-08
      • 1970-01-01
      • 2015-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多