Object value is not saving as it is passed through classes

I am working on creating a Game of Life in C++ for my Data Structures course. I've been stuck on this for a few days and am officially stumped. I am having trouble with passing the values of my height and width variables between classes. In the FileParser class, the values print correctly (5,7), but when I pass and print those same values, they are both 0. Then when they are passed into main, they print (8,0). I’ve attempted multiple solutions but I am stumped. From looking at my code and around the internet there should not be a problem there? Also, if I uncomment line 41, I get a Segmentation fault after the first iteration of the for loop.

I apologize for the lengthy code it is just because the retrieval and passing of the values require multiple classes and functions.

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
39
40
41
42
43
44
// MAIN 
#include "UserIO.h" 
#include "FileParser.h"
#include "ClassicMode.h"
#include <iostream> 

using namespace std; 

int main (int argc, char** argv)
{
    // initialize new class instances 
    UserIO user;
    user.Config();
    cout << "test main 1" << endl; // delete later 
    ClassicMode cm;

    int boundMode = user.BoundMode();

    cout << "test main 2" << endl; // delete later 
    int height = user.h; 
    cout << "test main 3" << endl; // delete later 
    int width = user.w; 
    
    cout << height << " main height" << endl; // delete later 
    cout << width << " main width" << endl; // delete later 

    cout << "test main 4" << endl; // delete later 
    
    // Classic Mode 
    if (boundMode == 1) 
    {
        // I can finish this function once this problem is resolved  
        cout<< "test main 5" <<endl; // delete later 

        // iterate through grid for r and c 
        for (int r = 0; r < height; r++)
        {
            for (int c = 0; c <= width; c++)
            {
                cout<<"test main 6" << " r: " << r << " c: " << c <<endl; // delete later 
                // cm.classicNeighbors(r, c, height, width);
            }
        }
    }


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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// FILEPARSER CLASS
#include "FileParser.h" 
#include <iostream> 
#include <fstream> 
#include <string>
#include <stdexcept>

using namespace std; 


// opens file from a pre-defined file path 
// and checks if that file exists, if not it prompts user for a new file 
void FileParser::openFile(string filePath) 
{
    inFile.open(filePath); 
    while (!inFile.is_open())
    {
        cout<<"File cannot be found, name a new file."<<endl; 
        string newPath; 
        cin>>newPath; 
        inFile.open(newPath);
    }
}

// get an int from the file line 
int FileParser::fpGetInt(string line)
{
    int lineInt; 
    while (true)
    {
        try 
        {
            lineInt = stoi(line);
            break; 
        }
        catch(invalid_argument& e)
        {
            cout<<"This input is invalid. Please enter an integer. fp1"<<endl; 
        }
        break; 
 
    }
    return lineInt; 
}

// get the dimensions from the map file 
void FileParser::findHW(string fileName)
{
    inFile.open(fileName); 
    while (!inFile.is_open())
    {
        cout<<"File cannot be found, name a new file."<<endl; 
        string newPath; 
        cin>>newPath; 
        inFile.open(newPath);
    }
    
    string line; 
    cout<<"test fp 1"<<endl; // delete later 

    getline(inFile, line);
    int rowInt = fpGetInt(line); 
    cout<<rowInt<<" rowInt fp "<<endl; // delete later 

    getline(inFile, line);
    int colInt = fpGetInt(line); 
    cout<<colInt<<" colInt fp "<<endl; // delete later 
}


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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// USERIO CLASS
#include "UserIO.h" 
#include "FileParser.h"
#include <iostream> 
#include <fstream> 
#include <string>
#include <stdexcept>

using namespace std; 

int UserIO::GetInt()
{
    int xInt; 
    string x;
    cin>>x;
    if (cin.fail())
    {
        cin.clear();
        cin.ignore(1000,'\n');
        cout<<"This input is invalid. Please enter an integer. userIO 1"<<endl; 
        cin>>x; 
    }
    while (true)
    {
        try 
        {
            xInt = stoi(x);
            break; 
        }
        catch(invalid_argument& e)
        {
            cout<<"This input is invalid. Please enter an integer. userIO 2"<<endl; 
        }
        break; 
 
    }
    return xInt;
}

double UserIO::GetDouble() 
{
    double y;
    cin>>y;
    if (cin.fail())
    {
        cin.clear();
        cin.ignore(1000,'\n');
        cout<<"This input is invalid. Please enter a decimal value between 0 and 1."<<endl; 
        cin>>y; 
    }
    return y;
}

void UserIO::Config()
{
    while (true) // loops until a viable input is given 
    {
        FileParser fp;

        cout<<"Would you like to provide a file or use a random configuration?"<<endl; 
        cout<<"Enter '1' to enter a file path or '2' to use random configuration."<<endl; 
        int configChoice = GetInt();
        double startPop; 

        if (configChoice == 1)
        {
            cout<<"Enter the path of the map file you would like to use: "<<endl; 
            string filePath; 
            cin>>filePath; 
            
            fp.findHW(filePath);

            int h = fp.rowInt; 
            cout << h << " user IO height "<< endl; // delete later 
            int w = fp.colInt; 
            cout << h << " user IO width "<< endl; // delete later 
            break; 
        }
        else if (configChoice == 2) 
        {
            cout<<"What is the height (number of rows) of your world?"<<endl; 
            int h = GetInt(); 
            cout << h << endl; 
            cout<<"What is the width (number of columns) of your world?"<<endl; 
            int w = GetInt();
            cout << w << endl; 
            cout<<"Enter a decimal value between 0 and 1 for the initial population density of your world: "<<endl;
            startPop = GetDouble();
            
            while (true) // loops until viable input is given 
            {
                if (startPop >0 && startPop<1) 
                {
                    cout<<"test userIO 1"<<endl; // delete later 
                    break; 
                }
                else 
                {
                    cout<<"This input is invalid."<<endl; 
                    cout<<"Enter a decimal value between 0 and 1 for the initial population density of your world: "<<endl;
                    startPop = GetDouble();
                }
            }
            break; 
        }
        else 
        {
            cout<<"This input is invalid."<<endl; 
        }
    }
    
}

int UserIO::BoundMode() 
{
    int modeInt;

    while(true)
    {
        cout<<"What boundary mode would you like to use?"<<endl; 
        cout<<"Enter '1' for Classic Mode, '2' for Doughnut Mode, or '3' for Mirror Mode."<<endl; 
        modeInt = GetInt();

        // Check if input is valid 
        if (modeInt != 1 && modeInt != 2 && modeInt != 3) 
        {
            cout<<"Invalid entry."<<endl; 
        }
        else
        {
            cout<<modeInt<<endl;  
            break; 
        }
    }

    return modeInt; 
}



The output is this:

Would you like to provide a file or use a random configuration?
Enter '1' to enter a file path or '2' to use random configuration.
1
Enter the path of the map file you would like to use:
mapfile.txt
test fp 1
5 rowInt fp
7 colInt fp
0 user IO height
0 user IO width
test main 1
What boundary mode would you like to use?
Enter '1' for Classic Mode, '2' for Doughnut Mode, or '3' for Mirror Mode.
1
1
test main 2
test main 3
9 main height
0 main width
test main 4
test main 5
test main 6 r: 0 c: 0
test main 6 r: 1 c: 0
test main 6 r: 2 c: 0
test main 6 r: 3 c: 0
test main 6 r: 4 c: 0
test main 6 r: 5 c: 0
test main 6 r: 6 c: 0
test main 6 r: 7 c: 0
test main 6 r: 8 c: 0

Any help would be appreciated!
Last edited on
> delete later
¿ever heard of a debugger and a step-by-step run?
those lines are half of your code.


> In the FileParser class, the values print correctly (5,7),
> but when I pass and print those same values,
> they are both 0.
you never pass the values
FileParser::findHW() writes local variables rowInt and colInt
`UserIO::Config()' reads uninitialised member variables of `fp' and writes to local variables h and w
`main()' reas uninitialised member variables of `user'
In findHW() at lines 62 and 66, you define local variables rowInt and colInt, assign values to them, and print them. But since they are local variables, they disappear when you exit findHW.

It looks like you want to store those in class members. Post the header files UserIO.h and FileParser.h. That should help shed some more light on your poblem so we can help.
Hello toth108,

You have posted the ".cpp" files, but not the "UserIO.h" and "FileParser.h" files. With out these there is no way to test your program to see how it runs.

Also the input file would be helpful.

A tip: After you try to open a file stream you follow with a while loop. the while condition can be shortened to just "(!inFile)". There is no need to creat a new string inside the while loop. "fileName" will work just fine.

Note: Calling a variable "newPath" is a bit misleading. It makes me think that you are expecting a path to the file when all you want is a file name.

In "UserIO::Config" you might want to change the prompt. Again it is mesleading asking for a path when all you want is a file name. I am think something like
"Enter the file name with extension of the map file you would like to use: "

You may also want to add some code to check it the extension is there and add it if necessary. Do not count on the user doing what they are told.

You are using "cin >> fileName" to input the name, but should that name have a space in it it will be a problem. The "std::getline(...)" is a better choice.

I will see what I can come up with, but with the missing files some of this is just a guess.

Hope that helps,

Andy
Thank you for all the helpful suggestions, I really appreciate it! Hopefully, these header files will reveal more of the issue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// FileParser.h 
#ifndef FileParser_H
#define FileParser_H
#include <fstream> 

using namespace std; 


class FileParser
{
    public: 
    void openFile(string filePath);
    int fpGetInt(string line); 
    FileParser();
    void findHW(string fileName);
    ifstream inFile;
    int maxSize; 
    int rowInt; 
    int colInt; 
};

#endif  


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
// UserIO.h
#ifndef UserIO_H
#define UserIO_H
#include <fstream>

using namespace std; 


class UserIO
{
    public: 
    int GetInt(); 
    double GetDouble(); 
    void Config(); 
    int BoundMode(); 
    string filePath; 
    int h; 
    int w; 
    double startPop;
};

#endif  

Last edited on
Inside UerIO::Config(), you can access class members h and w by just referring to them. If you say int h = GetInt(); you're defining a separate local variable that just happens to have the same name. So this should be h = GetInt(); instead.

That comment applies to lines 72,76,82,85. Also in FileParser lines 62 & 65.
Topic archived. No new replies allowed.