0

So I made this practice file for my project to try and read a file containing integer numbers, and store them in an int vector. My problem is whenever I run the program, it will give me "Segmentation fault (core dumped)" during the call to the readFile() function.

Do not mind the extra imports, I just copy and paste the same imports to all my practice files. Also the cout << "hi" << endl; is just to see when the program has the error.

#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cassert>
#include <vector>
using namespace std;

vector<int> readFile(string fileName);

int main()
{
    vector <int> intvec = readFile("ints.txt");
    cout << "hi" << endl;
    for (int i = 0; i < intvec.size(); i++)
    {
        cout << intvec[i] << endl;
    }
    return 0;
}

vector<int> readFile(string fileName)
{
    ifstream inFile(fileName);
    vector<int> inputVec;
    int i = 0;
    while (!inFile.eof())
    {
        inFile >> inputVec[i];
        i++;
    }
    inFile.close();
    return inputVec;
}
Tu Tran
  • 1,877
  • 1
  • 25
  • 46
jussaw
  • 3
  • 1
  • Helpful reading: [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – user4581301 Mar 26 '17 at 01:55

3 Answers3

1

c++ std::vectors need to be resized before adding to them. Try the "push_back" function instead, that adds them on the end and resizes the vector to fit.

BTW unlike e.g. JavaScript you can't use "vector[i] == value" to automatically resize a c/c++ array/vector.

BTW, square brackets [] operator in c arrays and std::vector is completely different to that in JavaScript. JavaScript arrays are associative maps and using array[value] causes it to create a key "value" automatically. But this is extremely slow. The square brackets operators in c/c++ don't work like that. They are a much faster direct memory access system.

If you have an array called "myArray" and you asked for myArray[10], the computer just looks at whatever is inside the computers RAM 10 addresses beyond the start of myArray (multiplied by the size of the elements, so myArray[10] would be 40 bytes past the start of an array with 4-byte values such as int or float.

It's designed for pure speed, so there's no bounds checking added to this. it's entirely up to the c/c++ programmer to ensure that you don't read or write outside the bounds with square brackets operatork, but the payoff is much faster programs. You can add your own bounds checking to your own code, or you can just be careful not to read past the range you've allocated.

Jason Lang
  • 999
  • 8
  • 17
  • There are some assumptions here. _"But this is extremely slow"_ Probably not. Generally you're right though so +1 – Lightness Races in Orbit Mar 26 '17 at 01:27
  • It would be slow if std::vectors did bounds checking on every single call and resized automatically. Remember the check needs to be on **every** call, not just ones that exceed the bounds. – Jason Lang Mar 26 '17 at 01:29
  • Yep you basically got it. Generally I try to steer people away from talking about C++ in terms of low-level functions _at all_, because it is quite deliberately an abstraction from all that. But the end result is the same in this case. :) – Lightness Races in Orbit Mar 26 '17 at 01:31
1

You would want to do this

while (inFile >> i)
{
    inputVec.push_back(i);
}

In your code, you define inputVec without giving it an initial capacity, so you can assume that its size is 0. So when you write inputVec[i], you're actually trying to access an index out of the vector's boundaries. It's like accessing the 5th element in an array of size 4.

By using push_back, you can add elements to the vector and it'll adjust the size dynamically.

Islam Hassan
  • 1,684
  • 4
  • 24
  • 40
0

Using the std::copy algorithm and iterators, a vector can be filled with the following:

#include <fstream>
#include <iterator>
#include <algorithm>
#include <vector>

int main()
{
    std::vector<int> intvec;
    std::ifstream ifs("ints.txt");
    std::copy(std::istream_iterator<int>(ifs),
              std::istream_iterator<int>(),    
              std::back_inserter(intvec));
}

Note: The std::back_inserter automatically calls push_back for each item in the stream.

PaulMcKenzie
  • 31,493
  • 4
  • 19
  • 38