简体   繁体   中英

segmentation fault 11 error while importing csv

I'm making a function importcsv() which takes in a filename and outputs a 2D array. For some reason, whenever I use the following version of importcsv(), the compiler runs smoothly, but the executable always returns a "segmentation fault: 11" error.

typedef vector<vector<double> > matrix;

matrix importcsv(string filename)
{
   ifstream myfile (filename);  //Constructs a stream, and then asssociates the stream with the file "filename"

   matrix contents; // Vector which will store the contents of the stream.
   int i, j;
   while(!myfile.eof())
   {
       if(myfile.get()==','){++j;}
       else if(myfile.get()=='\n'){++i; j=0;}
       else{
        contents[i][j]=2;}
   }
   return contents;
}

Can anyone find the source of the error? btw I have the following header:

#include <fstream>
#include <iostream>
#include <array>
#include <vector>
using namespace std;

You are getting "segmentation fault: 11" since you have not allocated memory for contents . contents[i][j] will work only if contents has something in it.

You can divide reading of the file and constructing the matrix into various parts:

  1. Reading all the numbers in a line and treating it as a row of contents .
  2. Reading a number from the line and treating it as a column of a row.

This way, the program can be simplified. This also helps you easily isolate problems when there are any and fix them.

typedef vector<vector<double> > matrix;

double readNextNumber(std::istream& str)
{
   double n = 0.0;
   str >> n;

   // Skip until we get ',' or '\n'
   while (str)
   {
     int c = str.getc();
     if ( c == ',' || c == '\n' || c == EOF )
        break;
   }
   return n;
}

std::vector<double> importRow(std::ifstram& myfile)
{
   std::string line;
   std::vector<double> row;

   // Read a line as a string.
   // Then parse the string using std::istringstream.
   // When you have finished parsing the line, you know
   // you have finished constructing a row of the matrix.
   std::getline(myfile, line);
   if ( myfile )
   {
      std::istringstream str(line);
      while (str)
      {
         double n = readNextNumber(str);
         if (str)
         {
            row.push_back(n);
         }
      }
   }
   return row;
}

matrix importcsv(string filename)
{
   ifstream myfile (filename);  //Constructs a stream, and then asssociates the stream with the file "filename"

   matrix contents; // Vector which will store the contents of the stream.
   while(!myfile.eof())
   {
       std::vector<double> row = importRow(myfile);
       if (myfile)
       {
          contents.push_back(row);
       }
   }
   return contents;
}

You haven't defined the size of contents . So by default, it will be a vector of 0 element. Therefore the calls to the operator[] will lead to a segmentatin fault.

Implementing the advice of the others here, the quick fix is to use resize() before reading each value into the array:

//WARNING: THIS PROGRAM UTILIZES C++11
#include <fstream>
#include <iostream>
#include <array>
#include <vector>
#include <cctype>
#include <thread>
using namespace std;
typedef vector<vector<double> > matrix;

matrix importcsv(string filename)
{
    ifstream myfile ("wavelengthtorgb.csv");  //Constructs a stream, and then asssociates the stream with the file "filename".
    matrix contents {{0.0}};
        char nextchar; double data; int i,j;

    while(!myfile.eof())
    {
    myfile.get(nextchar);
        if(nextchar==',')
        {
            ++j; 
            contents[i].resize(j+1); 
            cout<<"encountered a comma."<<" contents is now " <<i+1<<" x "<<j+1<<'\n';
        }
        else if(isspace(nextchar))
        {
            myfile.get(); //You might not need this line - first run with this line, and if there is an error, delete it, and try again.
            ++i; 
            contents.resize(i+1);
            j=0; 
            contents[i].resize(j+1);
            cout<<"encountered a carriage return."<<" contents is now " <<i+1<<" x "<<j+1<<'\n';
        }
        else
        {
            myfile.unget();
            myfile >> data;
            contents[i][j]=data;
            cout<< "encountered a double."<<" contents("<<i<<','<<j<<")="<<data<<'\n';
        }
    }
    return contents;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM