在for循环

时间:2019-08-07 09:58:59

标签: c++ for-loop vector temporary-objects dangling-pointer

编辑:解决了我的问题。由于我的CSVReader分隔符错误,这是一个愚蠢的错误……我的循环按照我的期望运行! 谢谢你的支持!

我试图在一系列for循环中声明临时变量。为此,我对每个“向量容器”(即vector<vector<string> > containerXYZ)使用基于范围的循环,并在每个for循环中声明临时变量。

这是我的代码的一部分,可让您了解for循环:

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <iterator>

using namespace std;

//Global variables
string i {};                                            
string j {};

class CSVReader
{
...
  vector<vector<string> > getData1();
  vector<vector<string> > getData2();
  vector<vector<string> > getData3();
}

vector<vector<string> > CSVReader::getData1()
{...};
vector<vector<string> > CSVReader::getData2()
{...};
vector<vector<string> > CSVReader::getData3()
{...};

int main(int argc, char** argv)
{
  vector<vector<string> > Container1 = reader.getData1;  //reads data from file1
  vector<vector<string> > Container2 = reader.getData2;  //reads data from file2

  //-----FIRST LOOP....
  for(vector<string> vecOfContainer1 : Container1)
  {
    i = vecOfContainer1[0];  //Declaring temporary variables used for container3 in my vector-function
    j = vecOfContainer1[1];

    vector<vector<string> > Container3 = reader.getData3();  //reads data from file1

      //-----SECOND LOOP....
      for(vector<string> vecOfContainer2 : Container2)
      {
        string var1_str = vecOfContainer2[2];  //Temporary variables which probably cause the error...
        string var2_str = vecOfContainer2[3];

        float var1 = stof(var1_str);
        float var2 = stof(var2_str);

        //Do calculations...

      };
    };
    return 0;
  }

我现在的问题是代码构建正确,但是在运行时,它在完成循环并在输出中出现逻辑错误之前终止:

This application has requested the Runtime to terminate it in an unusual way.
              Please contact the application's support team for more information.
terminate called after throwing an instance of 'std::logic_error'
  what(): basic_string::_M_construct null not valid

RUN FAILED (exit value 3, total time: 3s)

经过一些研究,我认为“悬挂参考”是解决我的问题的关键词。但是,由于我的变量声明在第一个循环中效果很好,因此在第二个循环中效果不佳。我想在这里寻求帮助!?

让我知道您是否需要完整的代码。我认为这足以进行讨论...

2 个答案:

答案 0 :(得分:0)

您无需事先检查所有临时变量的实际大小,但可以使用vecOfContainer1[0]等进行访问而无需任何检查。

您应使用vecOfContainer1.at(0),它至少为您提供一个std::out_of_range异常,该异常应为您提供更多详细信息。

答案 1 :(得分:0)

好的...由于我缺乏调试能力,因此我将向感兴趣的每个人发布完整的代码:

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <iterator>

using namespace std;

//Global variables
string line {};
string i {};                                            
string j {};                                           



/*
 * CSV Reader class to open CSV file which is further parsed  
 * in vector containers
 */
class CSVReader
{
    string fileName, delimiter;
public:
    CSVReader(string filename, string delm = ";") :
        fileName(filename), delimiter(delm)
    {}
    vector<vector<string> > getContainer1();                                            //Function to fetch unique objects from CSV file
    vector<vector<string> > getContainer3();                                            //Fetch all corresponding lines to object_i,j
};

class CSVXReader
{
    string fileName, delimiter;
public:
    CSVXReader(string filename, string delm = ",") :                                    //Notice comma delimiter for CSVX file, instead of semicolon for CSVReader
        fileName(filename), delimiter(delm)
    {}

    vector<vector<string> > getContainer2();                                            //Fetch data from CSVX file
};

/*
 * Boolean function template to search for a string in vector and return "true"
 * Use it as: if(Contains(vector,item)){do...}  :if vector contains "item", do...
 */
template <typename T> 
const bool Contains( vector<T>& Vec, const T& Element) 
{
    if (std::find(Vec.begin(), Vec.end(), Element) != Vec.end())
        return true;

    return false;
};

/*
 * Parse through CSV file line by line 
 * and return the data in vector of vector
 * of strings
 */
vector<vector<string> > CSVReader::getContainer1()
{
    ifstream file(fileName);

    vector<vector<string> > Container1;                                                 //Vector of vector contains all unique objects_i,j with constants 

    while (getline(file, line))                                                         //Iterate through each line and split the content using delimiter
    {

        vector<string> vecOfContainer1;                                                 //Vector contains a row from CSV file
        boost::algorithm::split(vecOfContainer1, line, boost::is_any_of(delimiter));    //Vector content is delimited 

        i = vecOfContainer1.at(2);                                                      //Here: object No., e.g. 1_380
        j = vecOfContainer1.at(3);                                                      //hotspot = 1,2,...,10   i.e. element j of object_i
        int a = 0;                                                                      //Integer variable, used in following if-loop to validate whether 'object' & 'hotspot'
                                                                                    //appear for the first time or not 

        /*
         * Creating a vector containing only necessary constants of the
         * corresponding line to copy into 'Container1'
         */
        vector<string> constantsOfVec;
        constantsOfVec = vecOfContainer1;                                      
        constantsOfVec.erase(constantsOfVec.begin()+11,constantsOfVec.begin()+21);      //Deleting unnecessary elements of vecOfContainer1
        constantsOfVec.erase(constantsOfVec.begin()+4,constantsOfVec.begin()+8);


        /*
         * Searching whether 'object' i & 'hotspot' j exists in the whole 'Container1' already.
         * If it exists, a=>1, and at next if-function the current vector (i.e. line) is not added to 'Container1'
         * else, a=>0, and current vector is added! 
         */

        for(vector<string> constantsOfVec : Container1)                                 //Browsing through all vectors of 'Container1'
        {
            if(Contains(constantsOfVec, i) && Contains(constantsOfVec, j))              //Browsing through a vector (i.e. line) and searching for 'detail' i (e.g. 1_380) & hotspot j
            {
                    a = 1;
            }
        }
        if(a != 1)                                                                      //Line (or vector) is added to 'Container1' container if i&j appear for the first time
        {
            Container1.push_back(constantsOfVec);
        }
    }
    Container1.erase(Container1.begin());                                               //Deletes first line of CSV file, i.e. column header

    file.close();
    return Container1;    
};

vector<vector<string> > CSVReader::getContainer3()
{
    ifstream file(fileName);

    vector<vector<string> > Container3;                                                 //Vector of vector contains all lines of object_i,j

    while (getline(file, line))                                                         //Iterate through each line and split the content using delimiter
    {      
        vector<string> vecOfContainer1;                                                 //Vector contains a row from RAO file
        boost::algorithm::split(vecOfContainer1, line, boost::is_any_of(delimiter));    //Vector content is delimited 

        /*
         * Creating a vector containing only necessary elements of the
         * corresponding line to copy into 'Container3' container
         */
        vector<string> parameterOfVec;
        parameterOfVec = vecOfContainer1;                                      
        parameterOfVec.erase(parameterOfVec.begin()+21,parameterOfVec.end());   
        parameterOfVec.erase(parameterOfVec.begin()+8,parameterOfVec.begin()+12);
        parameterOfVec.erase(parameterOfVec.begin()+4,parameterOfVec.begin()+7);
        parameterOfVec.erase(parameterOfVec.begin(),parameterOfVec.begin()+2);

        if(Contains(parameterOfVec, i) && Contains(parameterOfVec, j))                  //Browsing through a vector (i.e. line) and searching for detail i and hotspot j of corresponding loop
        {
            Container3.push_back(parameterOfVec);
        };   
    };

    file.close();
    return Container3;
};

vector<vector<string> > CSVXReader::getContainer2()
{
    ifstream file(fileName);

    vector<vector<string> > Container2;

    while (getline(file, line))
    {
        vector<string> vecOfContainer2;
        boost::algorithm::split(vecOfContainer2, line, boost::is_any_of(delimiter));

        Container2.push_back(vecOfContainer2);

    };

    Container2.erase(Container2.begin());                                               //Deletes first line of CSVX file, i.e. column header

    file.close();
    return Container2;
};

int main(int argc, char** argv) 
{

    CSVReader readerCSV("CSV_Example_.csv");                                    //Creating an object of CSVReader to open CSV file
    CSVXReader readerCSVX("CSVX_Example.csvx");                                 //Creating an object of CSVXReader to open CSVX file

    vector<vector<string> > Container1 = readerCSV.getContainer1();                     //Read data from CSV file and insert all unique objects (i,j) in 'Container1'
    vector<vector<string> > Container2 = readerCSVX.getContainer2();


////------------------------------FIRST LOOP FOR OBJECT i, HOTSPOT j---------------------------------------------------------------------////

    for(vector<string> constantsOfVec : Container1)                                     //Iterating through 'Container1'
    {           

        i = constantsOfVec.at(2);                                                       //Declare Object No. and Hotspot of the current loop to be used 
        j = constantsOfVec.at(3);                                                       //in 'Container3' for inserting all vectors with exact same i&j in while-loop

        vector<vector<string> > Container3 = readerCSV.getContainer3();                         //Read data from CSV file and insert all lines with corresponding i&j in 'Container3' container


////------------------------------SECOND LOOP FOR TIME k---------------------------------------------------------------------------------////

        for(vector<string> vecOfContainer2 : Container2)                                //Iterating through 'Container2', i.e. time k
        {

            string var1_str = vecOfContainer2.at(10);
            string var2_str = vecOfContainer2.at(12);
            string var3_str = vecOfContainer2.at(16);

        //Converting strings of 'Container3' to floats with std::stof('string')
            float var1 = stof(var1_str);                                      
            float var2 = stof(var2_str);
            float var3 = stof(var3_str);

        //get parameterOfVec(var1,var2,var3)_ij for time k, i.e. find line in Container3 with closest parameters to current line of Container2

        };


    };   
    return 0;
}

我嵌套了循环,因为我想在遍历容器1时创建自己的Container3,例如push_back file1的所有行都属于object_i,j。 在第二个循环中,我正在浏览另一个file2,并且必须为Container2(file2)的每一行查找Container3(file1)中的相应行。必须对所有object_ij,即Container1(file1)的所有行重复此操作。 这就是为什么我一开始创建Container2以便为每个object_ij访问它的原因。根据我的理解,Container3是一个与每个object_ij对应的临时容器。

希望您能理解我的理解...期待任何建议。同时,我正在努力赶上调试器,并将尽快发布更多信息。

BR jtotheakob