【问题标题】:Need help to understand where i am going wrong with strings需要帮助来了解我的字符串哪里出错了
【发布时间】:2017-01-11 02:36:23
【问题描述】:

在 c++ 中,我们有 std::to_string 将 int/float/double 转换为字符串。所以只是为了测试我对模板的理解,我尝试了下面的代码:

#include "iostream"
#include "sstream"
#include "string"
using std::cout;

template <typename T>
std::string getString(const T& data){
    std::stringstream ss;
    cout << '\n' << data << '\n';
    ss << data;
    std::string s;
    ss >> s;
    return s;
}

int main(int argc , char** argv){
    cout << getString(1.0000011);
    cout <<' '<<std::to_string(1.0000011);
    return 0;    
}

但是,输出没有意义,to_string 给了我1.0000011,而getString 得到 1 并给了我 1。因为我使用模板不应该 getString 得到 1.0000011 并给我也是1.0000011?

【问题讨论】:

    标签: c++ string templates stl


    【解决方案1】:

    您可以在&lt;iomanip&gt; 标头中使用std::setprecision 来设置std::stringstream 在格式化数字数据时将使用的精度。

    例如:

    std::stringstream ss;
    ss << std::setprecision(9) << data;
    cout << ss.str();
    

    将打印:

    1.0000011
    

    这是一个在线快速演示:cpp.sh/9v7xf

    附带说明,您不必创建 string 并从 stringstream 输出 - 您可以将 getString() 中的最后 3 行替换为:

    return ss.str();
    

    【讨论】:

    • 考虑使用std::numeric_limits&lt;T&gt;::digits10而不是9。
    【解决方案2】:

    为了外观,数值通常会被截断。您可以从 iomanip 标准标头中提供 std::fixed 操纵器以避免此问题。

    #include "iomanip" // <- Add this header
    #include "iostream"
    #include "sstream"
    #include "string"
    using std::cout;
    
    template <typename T>
    std::string getString(const T& data)
    {
        std::stringstream ss;
        cout << '\n' << data << '\n';
        ss << std::fixed << data;
        //    ^^^^^^^^^^^^^ Add this
        std::string s;
        ss >> s;
        return s;
    }
    
    int main(int argc, char** argv)
    {
        cout << getString(1.0000011);
        cout << ' ' << std::to_string(1.0000011);
        return 0;
    }
    

    【讨论】:

    • 单独使用'std::fixed`会截断字符串,所以它是1.000001
    【解决方案3】:

    &lt;iomanip&gt; 需要包括在内,并且在将浮点值输出到流时必须使用std::setprecision。使用您的示例,这看起来像:

    #include <iostream>
    #include <iomanip> //include this.
    #include <sstream>
    #include <string>
    
    template <typename T>
    std::string getString(const T& data){
        std::ostringstream ss;
        ss << std::setprecision(8);
        std::cout << std::setprecision(8);
        std::cout << data << '\n';
        ss << data;
        return ss.str();
    }
    
    int main(int argc , char** argv){
        std::cout << getString(1.0000011) << "\n";
        std::cout << std::to_string(1.0000011) << std::endl;
        return 0;
    }
    

    哪些打印:

    1.0000011
    1.0000011
    1.000001
    Program ended with exit code: 0
    

    注意 to_string 单独截断浮点数!!!我怀疑这是不受欢迎的行为,但 to_string 不能直接操作,所以...

    如果需要,您可以使用解决方案 found here 解决此问题。

    否则,在插入流以精确转换字符串时,只需使用std:set_precision()

    【讨论】:

    • 我会改用std::ostringstream。而且您仅在std::cout 上使用std::setprecision(),但在ss 流上也没有使用。
    • @Remy Lebeau,你选择 std::ostringstream 的原因是什么
    • @Arup std::stringstream 是为输入和输出而设计的,但getString() 只需要输出,这就是std::ostringstream 的设计目的。
    猜你喜欢
    • 2011-10-21
    • 2018-08-11
    • 2021-05-23
    • 1970-01-01
    • 2017-06-19
    • 2016-05-03
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多