【问题标题】:C++ Parsing a CSV file into vector of vectors: Loosing string 1st characterC ++将CSV文件解析为向量向量:丢失字符串第一个字符
【发布时间】:2019-12-10 03:50:19
【问题描述】:

我正在将 CSV 文件读入字符串向量的向量。我在下面写了代码。

#include<iostream>
#include<fstream>
#include<string>
#include <vector>
#include <fstream>
#include <cmath>
#include <sstream>

using namespace std;

int main()
{
    ifstream mesh;
    mesh.open("mesh_reference.csv");

    vector<vector<string> > point_coordinates;
    string line, word;

    while (getline(mesh,line))
    {
        stringstream ss(line);
        vector<string> row;
        while (getline(ss, word, ','))
        {
            row.push_back(word);
        }
        point_coordinates.push_back(row);
    }

    for(int i=0; i<point_coordinates.size(); i++) 
    {
        for(int j=0; j<3; j++)
            cout<<point_coordinates[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}

当我打印出向量的向量时,我看到我在向量行的 0 位置丢失了 Element 的第一个字符。基本上,point_coordinates[0][0] 显示的是 0.0001,而字符串应该是 -0.0001。我无法理解相同的原因。请帮忙。

典型的输出线是

 .0131 -0.019430324 0.051801

CSV 数据是

0.0131,-0.019430324,0.051801

文件中的 CSV 数据样本

    NODES__X,NODES__Y,NODES__Z
    0.0131,-0.019430324,0.051801
    0.0131,-0.019430324,0.06699588
    0.0131,-0.018630324,0.06699588
    0.0131,-0.018630324,0.051801
    0.0131,-0.017630324,0.050801
    0.0131,-0.017630324,0.050001
    0.0149,-0.017630324,0.050001
    0.0149,-0.019430324,0.051801

【问题讨论】:

  • 显示的代码没有明显的问题,所以问题一定出在没有显示的代码上。这就是为什么stackoverflow.com 的help center 为您提供了将问题中包含的任何代码格式化为minimal reproducible example 的指导,否则没有人能够帮助您。您需要edit,并包含任何人需要的所有内容(最多应该是几十行左右,包括任何示例输入),任何人都可以自己剪切和粘贴并重现您的问题。请参阅How to Ask 了解更多信息。
  • @SamVarshavchik,感谢您的建议,我已经编辑了代码以形成一个完整的程序。还提供了示例 CSV 数据。
  • 无法使用已发布的代码和数据进行复制。你确定你正在打开你认为你正在打开的数据文件吗?尝试删除它并再次运行程序。
  • 是的@NeilButterworth。如果我在 row.pushback 循环之后添加这一行:cout&lt;&lt;row[0]&lt;&lt;" "&lt;&lt;row[1]&lt;&lt;" "&lt;&lt;row[2]&lt;&lt;endl;,我将得到输出中的第一个字符。但是,结果向量正在成为问题,输出的左边缘有一个空白的字符空间。
  • 看看你评论中的代码,以及你程序中的代码。有什么东西不见了。特别是std::endl。您会看到输出从一行到下一行的明显伪影。

标签: c++ string file csv vector


【解决方案1】:

虽然问题已经解决,但我想向您展示一个使用一些现代 C++ 算法并消除小问题的解决方案。

  • 不要使用using namespace std;。你不应该这样做
  • 需要一个单独的文件。打开。 std::ifstream 构造函数将为您打开文件。析构函数会关闭它
  • 检查文件是否可以打开。 ifstreams ! 运算符已重载。所以你可以做一个布尔检查
  • 不要在与.size() 进行比较的for 循环中使用int。改用````size_t
  • 始终初始化所有变量,即使下一行有赋值
  • 对于标记化,您应该使用std::sregex_token_iterator。它正是为此目的而设计的
  • 在现代 C++ 中鼓励您使用算法

请在下面查看您的代码的改进版本:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>

const std::regex comma(",");

int main()
{
    // Open source file.
    std::ifstream mesh("r:\\mesh_reference.csv");

    // Here we will store the result
    std::vector<std::vector<std::string>> point_coordinates;

    // We want to read all lines of the file
    std::string line{};
    while (mesh && getline(mesh, line)) {
        // Tokenize the line and store result in vector. Use range constructor of std::vector
        std::vector<std::string> row{ std::sregex_token_iterator(line.begin(),line.end(),comma,-1), std::sregex_token_iterator() };
        point_coordinates.push_back(row);
    }
    // Print result. Go through all lines and then copy line elements to std::cout
    std::for_each(point_coordinates.begin(), point_coordinates.end(), [](std::vector<std::string> & vs) {
        std::copy(vs.begin(), vs.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::cout << "\n"; });

    return 0;
}

请考虑一下,如果您将来可能想使用这种方法

【讨论】:

  • 我所有的编码风格都是完全从 C 中借来的。我对 C++ 知之甚少。您的解决方案做得如此优雅,而我努力了几个小时才能让我的解决方案代码正常工作。感谢您指导我的代码的现代简洁版本。将进一步使用它。
猜你喜欢
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 2020-02-27
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多