【问题标题】:c++ convert vector of strings to vector of doubles from a given .dat filec ++将字符串向量转换为给定.dat文件中的双精度向量
【发布时间】:2014-12-03 21:06:04
【问题描述】:

所以我有很多问题,但我会从我认为应该很简单的问题开始。我被分配了一项任务,将模板文件与查询文件进行比较,计算点积,并返回 10 个最近的邻居。我想我可以很容易地进行计算,但是我很难处理文件 i/o。我能够将数据读入字符串向量,但我不确定如何在保持顶点完整性的同时将其转换为双精度向量。如果我尝试使用字符串流或迭代器,我最终会为每个数字分配它自己的索引号,而不是每行都获得它自己的索引号。这就是我所拥有的……你能帮帮我吗?

为澄清目的而编辑:

我将查询文件与包含图像集合的模板文件进行比较,以获得 10 个最近的邻居。一个查询文件包含一个“集合”(因为没有更好的描述)。一个模板文件包含 138 行数据。现在,我想做的就是打印模板文件中的每一行数据以及 .dat 文件中相应的索引号,但格式允许我进行必要的计算。一旦一切都说完了,我将需要计算两个向量之间的余弦(一个查询和模板中的第 i 行),所以我实际上需要分解模板的第 i 行以计算它之间的余弦和查询文件。这更清楚吗?

这里是查询文件的链接:https://www.dropbox.com/s/6xytafmojrct3lh/001_AU01_query.dat?dl=0 这是模板文件的链接:https://www.dropbox.com/s/vnqi7h1btxdsf9u/001_template.dat?dl=0

示例输出类似于:“001_AU01_query: 15 20 135 19 36 22 105 95 55 68”,其中数字表示与查询数据最匹配的相应模板文件的行号。

再次感谢您的帮助。

void NearestNeighbor::readQuery(){
        vector<string> queryVector;
        string line;
            ifstream queryData;
        queryData.open("001_AU01_query.dat");
        if (queryData.fail()) {
            cout << "Unable to read query.dat file";
            exit(1);
        }
        //populate the vector with the template info
        while(getline(queryData, line, '\n')){
            queryVector.push_back(line);
        }
        //this prints the contents of the queryVector to the console
        for ( unsigned int i = 0; i < (queryVector.size()); i++){
            cout << "Index[" << i << "] " << queryVector[i] << endl;
        }
        queryData.close();
    }//end readQuery()

如果您认为这会有所帮助,我很乐意发布输入和预期输出的示例。 提前致谢!

【问题讨论】:

  • 你的程序中没有“索引号”,只有向量中的位置,显然每个元素都有自己的位置。你不能有vector&lt;double&gt;,其中几个双精度数在向量中的同一索引处。我认为你需要更好地解释这个问题,这可能会让你更好地理解它。 “线”如何对应“数字”?你的整个问题太模糊了,任何人都无法提供帮助。
  • 如果您能向我们展示一个示例输入及其预期输出,那就更清楚了。
  • @anmolSinghJaggi 我更新了问题以包含指向示例查询和模板数据的链接以及预期的输出。再次感谢。

标签: c++ file-io vector


【解决方案1】:

您只需要选择正确的数据结构,其他一切都应该从那里开始。

单个一维vector&lt;double&gt; 将不起作用,因为您无法跟踪数据每行中的值。但是,vector&lt;double&gt; 适合将值存储在单行数据中。然后,您只需为每一行使用其中一个。

所以更合适的数据结构是vector&lt;vector&lt;double&gt;&gt;。即二维向量:

void readQuery(std::istream& queryData){
  std::vector<std::vector<double>> queryVector;
  std::string line;

  while(getline(queryData, line, '\n'))
    queryVector.push_back(splitData(line));

  for (unsigned i = 0u; i != queryVector.size(); ++i) {
    std::cout << "Index[" << i << "] ";
    for(double value : queryVector[i])
        std::cout << value << " ";
    std::cout << "\n";
  }
}

这需要一个函数splitDatastring 拆分为vector&lt;double&gt;。您可以在 SO 上找到大量关于拆分字符串的最佳方式的示例(和辩论),但示例实现可能是:

std::vector<double> splitData(const std::string& line) {
  std::istringstream iss(line);
  std::istream_iterator<double> begin(iss);
  std::istream_iterator<double> end;
  return {begin, end};
}

Live demo Live demo C++03

【讨论】:

  • 这看起来很像我认为我需要的。什么是 auto i = 0u,不过……是 boost 还是 C++11?我将如何使用常规的 ol' C++ 来做到这一点?感谢您的所有帮助!
  • @user3882751 是的,auto 是 C++11。我删除了它,因为这种用法有点无缘无故。但在我的示例中可能还有其他一些 C++11(例如,基于范围的 for 循环遍历一行中的值)。在我看来,C++11 普通的 C++。 C++14 和 C++1z 是新标准。
  • @user3882751 我添加了一个“常规的 ol' C++”现场演示链接。
  • 好的。我打算将我的项目更新到 C++11。我已经看过很多了,所以使用它和/或新标准也是有意义的。我不确定它是否会在我学校的服务器上编译,但尝试一下也无妨。我真的很感谢你抽出时间来帮助我。这些东西有时会让一个相对聪明的人感到愚蠢。
  • 我已经将我的项目更新为 C++11,这正是我需要它做的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 2015-04-10
  • 1970-01-01
相关资源
最近更新 更多