Search code examples
c++arraysdynamicaccess-violation

How can I store a string(from a file with n number of lines) in a dynamic array? C++


Newb here... taking a C++ class on data structures. I am making a program that takes a list of chores from a text file and stores them in a dynamic array.

//In header/ In class:

private:
/* var to keep len of list */
int len = 99; // Not sure what to set this to or if I need to even set it.
/* add appropriate data structure to store list */
string *arr = new string[len];

//In .cpp:

ListOfChores::ListOfChores(string fileName) {
ifstream file(fileName, ifstream::in);
string line;
    if (file.is_open()) //Checking if the file can be opened
    {
        while (!file.eof()) // To get all the lines.
        {
            getline(file, line); // Gets a single line
            arr[len] = line; // Store a line in the array
            len++; // Increases the array size by one
        }
        file.close(); // Closes file
    }
    else cout << "Unable to open file" << endl; // Gives error if the file can't be opened
}

But I am getting an error for storing a line in the array. It says "Access violation reading location." There is another function executed in the main.cpp for printing the lines.


Solution

  • You overrun your array buffer at once because len is already 99. You should have a notion of capacity and length. Capacity is the maximum you can store without reallocating, and length is the actual number of data lines.

    Please avoid this C-style array in C++ code. Use vector, which has been around for at least 20 years (STL) if I'm not mistaken.

    (you're not a lost cause, you are already using std::string :))

    Check this:

    #include <vector>
    //In header/ In class:
    
    private:
    
    /* add appropriate data structure to store list */
    std::vector<string> arr;   // define a vector
    
    //In .cpp:
    
    ListOfChores::ListOfChores(string fileName) {
    ifstream file(fileName, ifstream::in);
    string line;
        if (file.is_open()) //Checking if the file can be opened
        {
           while (getline(file, line))
           {
               arr.push_back(line);
           }
            file.close(); // Closes file
        }
        else cout << "Unable to open file" << endl; // Gives error if the file can't be opened
    }
    

    Now arr.size() holds the number of lines, it is no longer limited to 99 lines but to the max. program memory capacity. You can still access line number 13 by arr[12] or arr.at(12) for boundary checked access.

    proper way to iterate through it (C++11) for instance to print all lines:

    for (auto s : arr)
    {
       std::cout << s << std::endl;
    }
    

    Now, if you REALLY have to use an array, you can emulate/mimic what vector does (well, not as performant I'm sure, but does the job):

    private:
    
     int len=0;
     int capacity=100;
     string *arr = new string[capacity];
    

    now in the code, just before inserting (untested, but the idea is right):

    if (len>=capacity)
    {
       string *narr = new string[capacity+100];
       for (int i = 0; i < capacity; i++)
       {
            narr[i] = arr[i];
       }
       delete [] arr;
       arr = narr;
       capacity += 100; // growth
    }
    

    (you cannot use realloc or memcpy because you're handling objects in the arrays)