C++ C++;|将字符串推入空向量会导致第一个元素损坏吗?

C++ C++;|将字符串推入空向量会导致第一个元素损坏吗?,c++,stdvector,stdstring,istringstream,C++,Stdvector,Stdstring,Istringstream,我一直在开发一个*.csv解析器,它大部分都能正常工作。基本上,解析是这样工作的: 为指定的*.csv文件打开一个流(必须在构造函数中提供文件路径、数据列数和分隔符) 获取每一行,直到文件结束。对于提取的每个原始csv行: i) 将该行流化为行流(使用std::istringstream) ii)将该流分解为更小的字符串标记(使用构造函数提供的分隔符),并推入字符串向量 提取的数据字符串可以通过私有接口数据库接口访问,直到解析器对象被销毁(或者直到我实现字符串处理器将其转换为可用数据) 解

我一直在开发一个
*.csv
解析器,它大部分都能正常工作。基本上,解析是这样工作的:

  • 为指定的
    *.csv
    文件打开一个流(必须在构造函数中提供文件路径、数据列数和分隔符)

  • 获取每一行,直到文件结束。对于提取的每个原始csv行:

    i) 将该行流化为行流(使用
    std::istringstream

    ii)将该流分解为更小的字符串标记(使用构造函数提供的分隔符),并推入字符串向量

  • 提取的数据字符串可以通过私有接口
    数据库
    接口访问,直到解析器对象被销毁(或者直到我实现字符串处理器将其转换为可用数据)

  • 解析器对象可以工作,除了向量的第一个字符串元素的第一个字符总是被删除。例如:

    0544,1,Kitchenware,2,27
    
    变成:

    544,1,Kitchenware,2,27
    
    这是一个无法接受的信息丢失,但我无法找出这个问题的原因。我通过在每个数据包迭代器之前推一个
    伪字符串来解决这个问题

    ,ummy,0544,Kitchenware,27
    
    但我仍然觉得这是一个非常糟糕的实施


    我怀疑这是line_流的问题,但不完全确定如何解决

    以下是源代码:

    #ifndef _CSVPARSER_HPP
    #define _CSVPARSER_HPP
    
    #include <fstream>
    #include <iostream>
    #include <sstream>
    #include <vector>
    
    using namespace std;
    
    const char DEFAULT_COLUMNS_SEPARATOR = ',';
    
    class csvStream {
     private:
      void _setOpen() { inStream.open(fpath, ios::in); }
    
     protected:
      string fpath;
      fstream inStream;
    
     public:
      explicit csvStream(const string& path) {
        fpath = path;
        _setOpen();
      }
    };
    
    template <typename T>
    class csvParser : protected csvStream {
     private:
      int numDataTypes;
      char col_separator;
      string extractedRawLine;
      // Database of extracted packets of data as strings.
      vector<vector<string>*> database;
    
      // Return a reference to <data as a packet of strings>.
      vector<string>& _rawToStringPacket() {
        // line stream buffer & token
        istringstream line_stream;
        static string token;
        // new packet on the heap
        vector<string>* packet = nullptr;
        packet = new vector<string>;
        // extract strings into packet
        line_stream.str(extractedRawLine);
    
        packet->push_back("dummy");
        for (int i = 1; i < numDataTypes + 1; ++i) {
          getline(line_stream, token, col_separator);
          packet->push_back(token);
        }
        return *packet;
      }
    
      /****************************PUBLIC-API****************************/
     public:
      // Explicit Constructor: Must supply path to a *.csv file and the number of
      // data columns.
      explicit csvParser(const string& path,
                         const int ntypes,
                         const char sptr = ',')
          : csvStream(path), numDataTypes{ntypes}, col_separator{sptr} {}
    
      // Extract all data while stream is open.
      void extractAllRaw() {
        // continue to extract data until the end of file:
        while (getline(*inStream, extractedRawLine)) {
          static vector<string>* temp = nullptr;
          temp = &_rawToStringPacket();
          database.push_back(temp);
        }
      }
    
      // Stream the data elements to standard output.
      void printDatabase(ostream& os = cout) {
        for (auto i : database) {
          for (int j = 0; j < static_cast<int>(i->size()); ++j) {
            os << (*i)[j] << ",";
          }
          os << '\n';
        }
      }
    };
    
    #endif
    
    \ifndef\u CSVPARSER\u水电站
    #定义CSVPARSER水电站
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    常量字符默认列分隔符=',';
    类csvStream{
    私人:
    void _setOpen(){inStream.open(fpath,ios::in);}
    受保护的:
    字符串fpath;
    河道内流;
    公众:
    显式csvStream(常量字符串和路径){
    fpath=路径;
    _setOpen();
    }
    };
    模板
    csvParser类:受保护的csvStream{
    私人:
    int numDataTypes;
    煤焦分离器;
    字符串提取行;
    //提取数据包作为字符串的数据库。
    矢量数据库;
    //返回对的引用。
    向量&u rawToStringPacket(){
    //行流缓冲区和令牌
    istringstream line_stream;
    静态字符串令牌;
    //堆上的新数据包
    向量*数据包=nullptr;
    分组=新向量;
    //将字符串提取到数据包中
    line_stream.str(extractedRawLine);
    数据包->推回(“虚拟”);
    对于(int i=1;i推回(令牌);
    }
    返回*数据包;
    }
    /****************************公共API****************************/
    公众:
    //显式构造函数:必须提供*.csv文件的路径和
    //数据列。
    显式csvParser(常量字符串和路径,
    康斯特国际酒店,
    常量字符sptr=',')
    :csvStream(path),numDataTypes{ntypes},col_分隔符{sptr}{
    //在流打开时提取所有数据。
    void extractAllRaw(){
    //继续提取数据,直到文件结束:
    while(getline(*流内,提取行)){
    静态向量*temp=nullptr;
    temp=&u rawToStringPacket();
    数据库。推回(临时);
    }
    }
    //将数据元素流化为标准输出。
    void printDatabase(ostream&os=cout){
    用于(自动i:数据库){
    对于(int j=0;jsize());++j){
    
    操作系统请先阅读以下内容:。我发现很难相信重现问题所需的所有代码。此代码过度使用了指针和动态分配的内存。如果减少这两项,问题可能会自行解决。代码如下:
    string*fpath;
    --为什么这是指向
    字符串的指针你说得对。我对内存管理想得太多了。我复制粘贴了你的代码并添加了一个main(),它对我很有用:用Windows编译器(Microsoft Visual Studio)编译的程序会处理这个问题,因为他们希望文件像Windows一样。用Unix编译器编译的程序(包括MingW)可能希望这些文件像Unix一样。carraige返回肯定能解释这一点。