【问题标题】:How do I convert a std::string containing doubles to a vector of doubles?如何将包含双精度的 std::string 转换为双精度向量?
【发布时间】:2014-08-22 10:02:38
【问题描述】:

我有两种输入案例,我想使用相同的方法。 第一种情况是给定的参数是一个 std::string 包含我需要转换成 int 的三个数字:

std::string pointLine = "1 1 1";

第二种情况是给定参数是一个 std::string 包含三个“尚未双打”,我需要将其转换为双打:

std::string pointLine = "1.23 23.456 3.4567"

我写了如下方法:

std::vector<double> getVertexIndices(std::string pointLine) {


vector<int> vertVec;

vertVec.push_back((int) pointLine.at(0));
vertVec.push_back((int) pointLine.at(2));
vertVec.push_back((int) pointLine.at(4));

return vertVec;

}

这适用于第一种情况,但不适用于应该转换为双精度的行。

所以我尝试了解决方案 Double split in C 。 我知道我的分隔符是“”。

这是我现在想出的,但是在第一次调用以下方法后程序崩溃了:

std::vector<double> getVertexIndices(std::string pointLine) { 

vector<double> vertVec;
char * result = std::strtok(const_cast<char*>(pointLine.c_str()), " "); 

while(result != NULL ) {
    double vert = atof (result);
    vertVec.push_back(vert);
    char * result = std::strtok(NULL, " ");
}
return vertVec;

}

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    您可以直接从迭代器初始化向量,而不是复制。

    // include <string>, <vector>, <iterator> and <sstream> headers
    std::vector<double> getVertexIndices(std::string const& pointLine)
    {
      std::istringstream iss(pointLine);
    
      return std::vector<double>{ 
        std::istream_iterator<double>(iss),
        std::istream_iterator<double>()
      };
    }
    

    这对您的整数的工作方式完全相同。您的 int-approach 不会执行您对 "123 456 789" 等字符串的预期操作

    【讨论】:

    • 谢谢!这非常适合我想要的。感谢您就多于一位的整数发表评论。我刚刚遇到了这个问题。
    【解决方案2】:

    使用std::istringstream:

    std::vector<double> getVertexIndices(std::string pointLine)
    {
      vector<double> vertVec;
      std::istringstream s(pointLine);
      double d;
      while (s >> d) {
        vertVec.push_back(d);
      }
      return vertVec;
    }
    

    其实很简单。您构造一个将从字符串中读取的流。然后只需使用正常的流提取来填充向量。

    当然,您可以利用标准库迭代器适配器和类似的工具来生成如下内容:

    std::vector<double> getVertexIndices(std::string pointLine)
    {
      std::vector<double> vec;
      std::istringstream s(pointLine);
      std::copy(
        std::istream_iterator<double>(s)  // start
        , std::istream_iterator<double>()  // end
        , std::back_inserter(vec)  // destination
      );
      return vec;
    }
    

    作为旁注(感谢@ikh),您可能希望将函数更改为采用const std::string &amp; - 无需按值获取字符串。

    【讨论】:

    • 感谢您的解决方案。我最喜欢提前初始化所有东西。它有帮助,但我选择了另一个,因为我认为它更时尚,并且不必编写循环让我认为它在性能方面更好。备注:表演的东西只是一种感觉,没有知识支持。
    【解决方案3】:

    您尝试的主要问题是strtok() 将修改作为输入传递的指针。使用通过std::string::c_str() 获得的指针这样做会在字符串对象内部造成严重破坏。

    这里提供的所有其他答案都很好。根据您所说,您只需要读取 3 个双精度数(一个 x、y、z 顶点),因此您可以优化函数以使用其他不分配内存的固定大小容器(std::vector 将分配)。在以下示例中,我使用了 std::tuple 来返回结果。我还使用了std::stod(),这是一个 C++11 函数,可以从字符串中解析双精度。如果转换失败,它将抛出异常,这对您的应用程序也可能有用。

    #include <iostream> // std::cout
    #include <string>   // std::stod
    #include <tuple>    // std::tuple
    
    std::tuple<double, double, double> getVertexIndices(const std::string & pointLine)
    {
        size_t xEnd, yEnd;
        const double x = std::stod(pointLine, &xEnd);
        const double y = std::stod(pointLine.substr(xEnd), &yEnd);
        const double z = std::stod(pointLine.substr(xEnd + yEnd));
        return std::make_tuple(x, y, z);
    }
    
    // Test case:
    int main()
    {
        const std::string pointLine1 = "1 2 3";
        const std::string pointLine2 = "1.23 23.456 3.4567";
    
        std::tuple<double, double, double> v1 = getVertexIndices(pointLine1);
        std::cout << "x = " << std::get<0>(v1) << std::endl;
        std::cout << "y = " << std::get<1>(v1) << std::endl;
        std::cout << "z = " << std::get<2>(v1) << std::endl;
    
        std::tuple<double, double, double> v2 = getVertexIndices(pointLine2);
        std::cout << "x = " << std::get<0>(v2) << std::endl;
        std::cout << "y = " << std::get<1>(v2) << std::endl;
        std::cout << "z = " << std::get<2>(v2) << std::endl;
    
        return (0);
    }
    

    【讨论】:

    • 感谢您的解释!我找到了另一种更好用的解决方案,但您的 cmets 有助于更清楚地理解事情!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 2010-10-16
    相关资源
    最近更新 更多