1

I am trying to read a text file containing 9 lines of single integers into a vector. VS Code returns no syntax error but when I debug the program, I got a segmentation fault under main(I commented on the specific line). Am I doing something wrong with my implementation? Thank you in advance!

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
vector <int> list = {};

int count_line(){   //Count the number of accounts in the txt file
    int count = 0;
    string line;
    ifstream count_file;
    count_file.open("text.txt"); //The text file simply have 9 lines of single integers in it
    if (!count_file){
        cerr<<"Problem reading from file"<<endl;
        return 1;
    }
    while (!count_file.eof()){
        getline(count_file,line);
        count ++;
    }
    count_file.close();
    return count - 1;
}

int main(){
    int i{0};
    count_line();
    ifstream input {"text.txt"};
    if (!input){
        cout<<"Problem reading from file"<<endl;
        return 1;
    }
    while (i <= count_line() && count_line() > 0){
        input>>list[i]; //I am getting a segmentation fault error here
        i++;
    }
    for (int k = 0; k < 9 ; k++){
        cout<<list[k];
    }
}
Brian
  • 13
  • 3
  • I highly recommend searching the internet before posting. There are already a plethora of questions on StackOverflow with the same title. Also search the internet for "C++ read file comma separated" to get examples of reading from a text file. – Thomas Matthews May 05 '20 at 18:54
  • You may want to keep a `std::vector` of file positions as you read each line. This will allow you to more efficiently access a line in the file (look up the file position, then set the file position to that value). – Thomas Matthews May 05 '20 at 18:55
  • Your code have a problem described in [c - Why is “while ( !feof (file) )” always wrong? - Stack Overflow](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). You made a workaround by subtracting 1 from `count`, but then your program will report 0-line file as having -1 lines. – MikeCAT May 05 '20 at 18:57
  • Does this answer your question? [How to read in a text file into a vector of a class](https://stackoverflow.com/questions/27152521/how-to-read-in-a-text-file-into-a-vector-of-a-class) – Jay May 05 '20 at 19:01

2 Answers2

3

This vector:

vector <int> list = {};

Has exactly zero members. You never try and increase its size so any access to this array will result in a bad result.

There are a couple of places you accesses this vector:

input>>list[i];

// and

cout<<list[k];

These are both invalid access to the list.

To fix the problem you can read the data into a value and then append it to the vector:

int value;
input >> value;
list.emplace_back(value); // emplace back expands the vector by one place.

But that is not your only problem:

 while (i <= count_line() && count_line() > 0){

This while statement contains to calls that open a file parse the whole file and return a count. I doubt the compiler can optimize that away so that is exceedingly expensive call to make.

Can you just read values until there are none left?

 int   value;
 while(input >> value) {
     list.emplace_back(value);
 }

But the proper way to do this:

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

 int main()
 {
     std::ifstream     file("text.txt");
     std::vector<int>  data(std::istream_iterator<int>{file},
                            std::istream_iterator<int>{});

     for(auto val: data) {
         std::cout << val << " ";
     }
     std::cout << "\n";
 }
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • That's an excellent suggestion! Can I assign values to the vector by index instead of using push_back()? – Brian May 05 '20 at 19:07
  • @Brian: You can assign values to a vector using an index **iff** the vector already has at least that amount of size. Using the index will **NOT** increase the size of the vector. Using `push_back()` or `emplace_back()` will expand the size of the vector. – Martin York May 05 '20 at 19:09
  • I see how it is. For some very complicated reasons, I cannot append the data to the vector like you suggested, is there a way to assign the size of the vector beforehand with empty placeholders? – Brian May 05 '20 at 19:11
  • @Brian You can manually re-size the vector by calling `resize()` which will explicitly set the size of the vetor as required. But it is easier to simply use `push_back()`. – Martin York May 05 '20 at 19:11
  • Like I would like to control where the data is being appended to, instead of just adding it to the next index – Brian May 05 '20 at 19:12
  • @Brian: If you know the size of the vector before you start. You can pass this number to the constructor of the vector and it will be created with the correct size. `std::vector data(15);`. Now you can assign values of 0 -> 14 to `data` – Martin York May 05 '20 at 19:12
  • I will try to explain my situation in a brief manner here. I have another program with a vector that stores an instance of a class containing three attributes. The three attributes together represent a bank account. I am trying to read a txt file containing these three attributes(name, balance, account number) and assigning them back into this vector. If I use push_back, I won't be able to assign all three attributes into the same index. The program above is just my attempt to see how this all works. Thanks for helping me! I really appreciate this. – Brian May 05 '20 at 19:15
  • @Brian That's a different question. Hold on let me nock something up in gist for you. – Martin York May 05 '20 at 19:21
  • @Brian: https://gist.github.com/Loki-Astari/72231e096d55073195259d0744f1dba1 – Martin York May 05 '20 at 19:38
0

You must allocate elements before using them.

one of fix:

    while (i <= count_line() && count_line() > 0){
        if (list.size() <= (size_t)i) list.resize(i + 1); // add this
        input>>list[i];
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • This work, thank you very much! I am a beginner at c++, can you explain what the code does? I have never seen an if statement written like this before! – Brian May 05 '20 at 18:56
  • It allocate elements when the element number is insufficient so that `list[i]` becomes available. [std::vector::resize - cppreference.com](https://en.cppreference.com/w/cpp/container/vector/resize) – MikeCAT May 05 '20 at 18:59
  • So it is allocating space of the vector? – Brian May 05 '20 at 19:02
  • Yes, by resizing the vector. – MikeCAT May 05 '20 at 19:05