Search code examples
c++recursionfstreamiostream

How to get the next line in a recursive function


I'm trying to create a recursive function, that will go through a file, and for each line, will create an instance of an object, give this object a name, list of attributes, and a previous name (all names are unique, so I don't need to worry about similarities).

Here's the code:

    void getTags(string prevname){
        fstream file;
        file.open("source.txt");

        string name;
        // Getting current line, and splitting it.
        string str;


        getline(file, str);
        cout << str << endl;

        vector<string> currentLine = splitString(str, ' ');

        // Getting tag name
        if(!isClosing(str)){

            for (int i = 1; i < (int)currentLine[0].size(); i++){
                name += currentLine[0][i];
            }

            Tag tag = Tag(name, prevname);

            if(hasAttr(str)){
                vector<pair<string, string>> temp = getAttr(currentLine);
                for(int i = 0; i < (int)temp.size(); i++){
                    tag.addAttribute(temp[i]);
                }
            }
            
            tags.push_back(tag);
            getTags(name);
        } else {
            getTags(prevname);
        } 
    }
};

For some reason, my getline(file, str) isn't getting the next line, and is instead just recursing until I get a segmentation fault. I've also tried file >> str. But that didn't work either.

I've tried printing the line to check whether it does go to the next line, but it will always stay on the first line.

I'm not sure exactly where I've gone wrong, any help would be appreciated.

Each line in the file would look something like: name value="value" value2 = "value2"


Solution

  • Your first problem is that your recursion has no base case (i.e. terminating condition), and so getTags is being called until you fill up the call stack, at which point you get a segmentation violation. The way to fix this is to create a terminating condition which, in this case, would be when you exhaust all of the input in the file.

    Your second problem is that each recursive call opens the file again and assign it to a new instance of fstream file. This means that your getline call is always going to read the first line, regardless of how many recursive calls you've made so far (keep in mind that local variables defined in one recursive call are not carried over into subsequent calls). One way to fix this is to open the file prior to kicking off the recursion and pass the fstream as a parameter to getTags. That way, you're not needlessly opening the file more than once and you're actually able to read the file properly.

    Given the above two points, the general structure of getTags might look something like this:

    void getTags(fstream &file, string prevName) {
        string line;
        
        result = getline(file, line);
    
        if (!result) {
            // This is your base case. If result == false, the call to getline failed (due to EOF or some other reason)
            return;
        }
    
        // Main function logic here...
    
        vector<string> currentLine = splitString(line, ' ');
    
        if (!isClosing(line) ) {
            // ...
    
    }