Why cant I continue extracting values after first loop ?

Jan 24, 2016 at 2:30pm
Hello, I have to use "Data" function multiple times, but after first time using it, I cant extract any more values. Does it have something to do with it reopening ? And if text file is opened outside this function, it works well, but my text file must be in a function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void Data(int y, int &Groups, string *&Name, int &People, int *&Grades)
{
    ifstream ifile("text.txt");
    if(y==0)
    {
        ifile >> Groups;
        Name=new string[Groups];
    }
        ifile >> Name[y] >> People;
        Grades=new int[People];
        for(int i=0;i<People;i++)
        {
            ifile >> Grades[i];
        }
    }
int main()
{
    int Groups, People, *Grades, g=0;
    string *Name;
    Data(g, Groups, Name, People, Grades);
    for(g=1;g<Groups;g++)
    {
        Data(g, Groups, Name, People, Grades);
    }
 return 0;
}
Last edited on Jan 24, 2016 at 2:32pm
Jan 24, 2016 at 2:42pm
I need to see the text file to correctly identify the error. But the line that has the possibility of error is

ifile >> Groups;

This code is changing the value of Groups. As the variable Groups is passed by reference the value is also changed in the main. So that may be why the condition in the loop is failing.
Jan 24, 2016 at 2:47pm
If my ifstream is used before Data function, all is working fine. Groups value is changed only once, before the loop. Heres the text :
4
IF4/8 5 5 7 8 9 10
IF4/9 5 8 5 10 5 6
IF4/10 4 5 5 7 9
IF3/5 4 6 7 9 8
Last edited on Jan 24, 2016 at 2:56pm
Jan 24, 2016 at 9:08pm
Don't you need a function prototype?
Jan 24, 2016 at 9:25pm
I need to prototype it only if I want to do it below main function. And I like doing everything above :P
Jan 24, 2016 at 9:26pm
Good to know!
Jan 24, 2016 at 9:27pm
I think you need to go back to the drawing board with your code.

The way you are getting your function "Data" to reopen the file each time you want to read a line (I'm guessing) is a mistake. Every time the file is reopened file reads start again from the first line, so all calls to the function Data after the first will try to read the value of Groups and get confused from there.

Adding output to your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

void Data(int y, int &Groups, string *&Name, int &People, int *&Grades)
{
    ifstream ifile("text.txt");
    if(y==0)
    {
        ifile >> Groups;
        cout << "Groups = " << Groups << "\n";
        Name=new string[Groups];
    }

    ifile >> Name[y] >> People;
    cout << "Name[" << y << "] = " << Name[y] << ", People = " << People << "\n";
    Grades=new int[People];
    for(int i=0;i<People;i++)
    {
        ifile >> Grades[i];
        cout << "Grades[" << i << "] = " << Grades[i] << "\n";
    }
}

int main()
{
    int Groups, People, *Grades, g=0;
    string *Name;
    cout << "* * * call Data with g = " << g << "\n";
    Data(g, Groups, Name, People, Grades);
    for(g=1;g<Groups;g++)
    {
        cout << "* * * call Data with g = " << g << "\n";
        Data(g, Groups, Name, People, Grades);
    }
    return 0;
}


I get:

* * * call Data with g = 0
Groups = 4
Name[0] = IF4/8, People = 5
Grades[0] = 5
Grades[1] = 7
Grades[2] = 8
Grades[3] = 9
Grades[4] = 10
* * * call Data with g = 1
Name[1] = 4, People = 0
* * * call Data with g = 2
Name[2] = 4, People = 0
* * * call Data with g = 3
Name[3] = 4, People = 0


You need to open the file once and read all lines.

Andy

Ps As it stands, the function Data would allocate buffers repeatedly against the Grades variables, to you are leaking memory.
Last edited on Jan 24, 2016 at 9:31pm
Jan 24, 2016 at 9:28pm
You should also use the .eof() to check if it's the end of file
Jan 24, 2016 at 9:35pm
Thats the problem im having, I dont know how to stop text file from reopening, but still keeping it inside Data function. Im not yet sure if Im allowed to put ifstream outside it. And Zarman, I dont think I need to use it if I know how many lines there will be by "Groups" variable.
Jan 24, 2016 at 9:38pm
Have you tried .close()?
Jan 24, 2016 at 9:43pm
File always reopens due to that function, but I have tried that, didnt make a difference.
Jan 24, 2016 at 9:48pm
I'm no pro at c++ but I don't think you ever used the .open() so that you could use .close()
It should be
ifstream ifile;
ifile.open("yo textile.txt");
//do your stuff
if (ifile.eof())
ifile.close();

Also you are outputting data right? I don't even think you declared your file correct.
Should it be
ofstream file; ?
Last edited on Jan 24, 2016 at 9:53pm
Jan 24, 2016 at 9:52pm
Its not a must to use .open() to open a text file and to be able to use .close(). Ive worked with text files before, everything was working fine.
Jan 24, 2016 at 11:43pm
I'm no pro at c++ but I don't think you ever used the .open() so that you could use .close()
It should be
ifstream ifile;
ifile.open("yo textile.txt");
//do your stuff
if (ifile.eof())
ifile.close();


The typical usage should be:
1
2
3
4
    std::ifstream in("filename.ext");
    while ( input extraction is successful )
        // do stuff.
    // file is closed automatically when the stream object goes out of scope. 


@OP: This is very poor design. In addition to the issue with the file being re-opened on every call, you've got a memory leak there too. Big surprise with the manual memory management.

I would suggest opening the file in main and feeding the function a reference-to-std::istream from which to extract data. That will fix your file problem, but won't fix the poor design or memory leaks. One thing at a time, I suppose. ;)

Last edited on Jan 24, 2016 at 11:43pm
Jan 25, 2016 at 6:18am
I know about "new" which caused me a memory leak, but I don't currently bother using "delete" for very small programs. Are there any other memory leaks I wouldn't know about ?
Jan 25, 2016 at 6:38am
whenever you use a new, you need to use a delete. it's a good habit to get into. Btw u can use .good() to check if extraction is good
Last edited on Jan 25, 2016 at 6:38am
Jan 25, 2016 at 6:47am
whenever you use a new, you need to use a delete. it's a good habit to get into.


Better yet, don't use new or delete at all :+)

First try to accomplish want you want with the STL containers and algorithms. std::vector looks good for this.

Some situations require a pointer, use a smart pointer std::unique_ptr
Jan 25, 2016 at 6:58am
Arquon wrote:
I need to prototype it only if I want to do it below main function. And I like doing everything above :P


Prefer to use a function declaration (prototype) before main with function definitions after main. That way main is always at the top, one doesn't have to go looking for it :+)
Topic archived. No new replies allowed.