-2

I'm quite new to c++ and im trying to figure out how to use recursive function to read a .txt file and to save them in a string. I want the function to return a value of true when the reading is finished. I've tried to find solutions on the internet but so far no luck. I've tried the following:

void readFile(ifstream& stream, vector<string> v)
{
    if (stream.eof()) {
        return true;
    }
    else {
        string line;
        getline(stream, line);
        v.pushback(line);
        readFile(stream, v);
    }
}

Note that I want to use these parameters and I don't want to change them

kgf3JfUtW
  • 13,702
  • 10
  • 57
  • 80
Joshua
  • 19
  • 1
  • 1
  • 11
    Recursion to read a text file? Well, this is stackoverflow after all... – wally Oct 25 '16 at 19:49
  • 1
    You clearly havent tried this, otherwise you would know that it wont compile. Why dont you try it first? – Fantastic Mr Fox Oct 25 '16 at 19:54
  • Also there are no question marks, so what is your question ... ? – Fantastic Mr Fox Oct 25 '16 at 19:54
  • Better if you share the problem you are facing. What part s not working ? – Shasha99 Oct 25 '16 at 20:00
  • check for error after getline. Return bool from void. the vector is passed by copy. With some minor fixes this would technically be "a recursive function to read a file", and because it is tail recursive, most compilers would fix the big problem here (that there is no reason to use recursion for this). – Kenny Ostrom Oct 25 '16 at 20:02
  • @KennyOstrom Not to mention that it pushes each line to a different temporary vector – SomeWittyUsername Oct 25 '16 at 20:04
  • @SomeWittyUsername That was mentioned: `the vector is passed by copy` – Fantastic Mr Fox Oct 25 '16 at 20:05
  • @Ben Sorry, must've overlooked this – SomeWittyUsername Oct 25 '16 at 20:06
  • I'm curious about the nature of your question, too? Is your issue about compilation or method? Like @flatmouse mentioned, recursion would work but is unnecessary in this case. Why not read each line in simple sequence? Not to mention the issue of killing the stack memory for excessively large files. – Loic Argelies Oct 25 '16 at 20:26
  • May be he is curious to play with recursion – Shasha99 Oct 25 '16 at 20:30
  • 1
    @flatmouse While this approach is terrible, tail recursion nicely takes care of the stack issue if properly implemented. And you're a SCHEME developer who just can't face the light. – 3Dave Oct 25 '16 at 20:42
  • 1
    @Shasha99 and that's why we invented the Fibonacci sequence. :) – 3Dave Oct 25 '16 at 20:43
  • 1
    `if(stream.eof())` will bring you grief. It is the recursive version of http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – user4581301 Oct 25 '16 at 20:49
  • @DavidLively [λ](http://stackoverflow.com/a/1283081/1460794) – wally Oct 25 '16 at 21:01

2 Answers2

1

Since you are not passing reference to the vector, So even if you push_back() the line, it won't persist once that particular call is over.

I am assuming that you have already opened the file:

int main()
{
   ifstream f;
   f.open("input.txt");
   cout<<readFile(f);

}

So you have 2 options:

  1. Either pass the vector by reference.
  2. Or don't pass the vector at all. You may keep it in arguments if you have strict requirements, but you are not supposed to use this. And return the line read by that call. Return "" when eof() is reached. Do something like this:

    string readFile(ifstream& stream, vector<string> v){
       if(stream.eof())
          return "";
    
       string line;
       getline(stream, line)
       return line + "\n" + readFile(stream, v)
    }
    
Shasha99
  • 1,746
  • 2
  • 16
  • 30
  • It's worth noting that, with a large file, this may have some pretty severe perf cost. Every time you concatenate a string, it is potentially reallocated and copied, then the new parts copied into the new buffer. If you're reading a 10k line file, that will hurt. A 100k-line file would be unusable. But, the basic principle is there. Still, I wonder what possible reason one would have for reading a file this way. – 3Dave Oct 25 '16 at 20:40
  • We could do this all day. Really last one. – 3Dave Oct 25 '16 at 20:41
  • @DavidLively, yes you are absolutely right. The files lines should be read and then consumed or should be stored in some mutable DS if file is not that large. But it seemed like he is stuck in recursion. – Shasha99 Oct 25 '16 at 20:42
  • I know he doesn't want to change the parameters, but would it stop being recursive if he used `vector& v` ? – infixed Oct 25 '16 at 20:46
  • No, but i think he wants his recursive approach to be corrected. Its not making any sense BTW. Still ... – Shasha99 Oct 25 '16 at 20:49
  • 1
    Maybe the official response should be **"Don't do that. Pursue a career in agriculture."** – 3Dave Oct 25 '16 at 20:53
  • No, we should not underestimate. I still remember my old days. – Shasha99 Oct 25 '16 at 20:56
0

Problems that immediately jump out at me:

  1. v is passed by value. This means a lot of copies, copying, and no changes to the original v. This needs to be changed to pass by value: void readFile(ifstream& stream, vector<string> & v)

  2. if (stream.eof()) will always allow reading one line past the end of the file with unpredictable results. Something like if (!std::getline(stream, line)) would resolve this, but a better solution will follow.

  3. You can't return true from a void function.

  4. Needless stack killer. A large file will quickly eat up the whole stack or whatever the implementation uses as an automatic datastore.

Possible implementation:

void readFile(std::istream& stream, std::vector<std::string> & v)
{
    std::string line;
    if (std::getline(stream, line))
    {
        v.push_back(line);
        readFile(stream, v);
    }
}

Notes:

  1. istream in place of ifstream. This allows a wider variety of inputs and testing with a stringstream.
  2. Resolving point 1 above v is passed by reference.
  3. Resolving point 2 above, line is pushed into v and the recursive call is made only if data was read from stream. If no data was read, v is not updated and the recursion ends.
  4. There is no reliance on using namespace std;. This removes a common source of hard to spot errors.
  5. This will still kill the stack, but it will kill it more slowly. This is recursion so nothing can stop the eventual stack overflow if given sufficient input.
Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54