Thread: Variable scopes; Vectors of struct's

  1. #1
    Me
    Join Date
    Jul 2006
    Posts
    71

    Variable scopes; Vectors of struct's

    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct room {
        int roomID;
    };
    
    void valueSet();
    
    int main() {
        vector<room> roomRef;
        valueSet();
        int curRoom = 0;
    
        cout << roomRef[1].roomID;
    
        return 0;
    }
    
    void valueSet() {
        room Exterior;
            Exterior.roomID = 0;
            roomRef.push_back(Exterior);
        room Room1;
            Room1.roomID = 1;
            roomRef.push_back(Room1);
        room Room2;
            Room2.roomID = 2;
            roomRef.push_back(Room2);
        room Room3;
            Room3.roomID = 3;
            roomRef.push_back(Room3);
        room Room4;
            Room4.roomID = 4;
            roomRef.push_back(Room4);
    }
    In that, I set the variable roomRef in main, but when I call the valueSet() function, it says the variable is uninitialized. I've had this problem before and never really been sure how to resolve it. I tried making the function return a vector<room>, but I imagine that's not the best way to do it. Any help's appreciated. Thanks.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The std::vector<room> named roomRef is local to your main() function. Consequently, it does not exist in your valueSet() function. One way to handle this is to pass roomRef by reference to valueSet(), e.g.,
    Code:
    void valueSet(std::vector<room>& roomRef);
    
    int main() {
        vector<room> roomRef;
        valueSet(roomRef);
        // ...
    }
    
    void valueSet(std::vector<room>& roomRef) {
        room Exterior;
        Exterior.roomID = 0;
        roomRef.push_back(Exterior);
        // ...
    }
    Incidentally, you do not actually need to create Room1, Room2, Room3, etc. You can just reuse Exterior, perhaps by renaming it to something more generic. Or, you can turn your C-like struct into a more object based class and provide a constructor that takes a roomID, then just write:
    Code:
    void setRooms(std::vector<room>& roomRef) {
        // Set room exterior. (Perhaps could combine with for loop below, depends on your requirements.)
        roomRef.push_back(room(0));
    
        // Set remaining rooms.
        for (int i = 1; i <= 4; ++i) {
            roomRef.push_back(room(i));
        }
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Me
    Join Date
    Jul 2006
    Posts
    71
    Ah, I see. I didn't realize you could initialize an object and push it into a vector at the same time. I decided to use classes; however, how would I refer to individual variables in that class that are private?

    I'm using this:
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    class room {
        private:
            int roomID;
            string roomDesc;
        public:
            room(int, string);
            ~room();
    
            void descOut();
    };
    
    room::room(int roomID, string roomDesc) {
        roomID = roomID;
        roomDesc = roomDesc;
    }
    
    room::~room() {
    }
    
    void room::descOut() {
        cout << roomDesc;
    }
    
    void valueSet(vector<room>& roomRef);
    
    int main() {
        vector<room> roomRef;
        valueSet(roomRef);
        int curRoom = 0;
    
        cout << roomRef[0].descOut;
    
        return 0;
    }
    
    void valueSet(vector<room>& roomRef) {
        roomRef.push_back(room(0, "You are outside.")); // Exterior
        roomRef.push_back(room(1, "You are in room 1.")); // Room 1
        roomRef.push_back(room(2, "You are in room 2.")); // Room 2
        roomRef.push_back(room(3, "You are in room 3.")); // Room 3
    }

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by relyt_123 View Post
    Ah, I see. I didn't realize you could initialize an object and push it into a vector at the same time. I decided to use classes; however, how would I refer to individual variables in that class that are private?
    Expose member functions that returns that information (recommended) or make those variables public (not recommended).

    Quote Originally Posted by relyt_123 View Post
    I'm using this:
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    class room {
        private:
            int roomID;
            string roomDesc;
        public:
            room(int, string);
            ~room();
    
            void descOut();
    };
    
    room::room(int roomID, string roomDesc) {
        roomID = roomID;
        roomDesc = roomDesc;
    }
    
    room::~room() {
    }
    
    void room::descOut() {
        cout << roomDesc;
    }
    
    void valueSet(vector<room>& roomRef);
    
    int main() {
        vector<room> roomRef;
        valueSet(roomRef);
        int curRoom = 0;
    
        cout << roomRef[0].descOut();
    
        return 0;
    }
    
    void valueSet(vector<room>& roomRef) {
        roomRef.push_back(room(0, "You are outside.")); // Exterior
        roomRef.push_back(room(1, "You are in room 1.")); // Room 1
        roomRef.push_back(room(2, "You are in room 2.")); // Room 2
        roomRef.push_back(room(3, "You are in room 3.")); // Room 3
    }
    A subtle bug above. To call a function, don't forget (). In some compilers, you'll get the address of the function instead of calling it (though this is not part of the standard, but VC++ 2003 and earlier gives you the address instead).
    Also, headers should always be on top of the file and in a header of its own.

  5. #5
    Me
    Join Date
    Jul 2006
    Posts
    71
    Quote Originally Posted by Elysia View Post
    A subtle bug above. To call a function, don't forget (). In some compilers, you'll get the address of the function instead of calling it (though this is not part of the standard, but VC++ 2003 and earlier gives you the address instead).
    Ah, yes. That would affect it. However, it still throws the same error, and it won't compile.

    Code:
    Line 37 (cout << roomRef[0].descOut();
    
    error: no match for 'operator<<' in 'std::cout'
    Quote Originally Posted by Elysia View Post
    Also, headers should always be on top of the file and in a header of its own.
    Are mine not?

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by relyt_123 View Post
    Ah, yes. That would affect it. However, it still throws the same error, and it won't compile.

    Code:
    Line 37 (cout << roomRef[0].descOut();
    
    error: no match for 'operator<<' in 'std::cout'
    That's because descOut returns void.

    Are mine not?
    No. valueSet is declared just above main. Class declaration and definition is also within the same file.

  7. #7
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Code:
    room::room(int roomID, string roomDesc) {
        roomID = roomID;
        roomDesc = roomDesc;
    }
    Are you sure it works like that? Doesn't look right to me (assigning roomID and roomDesc to the temporary variables themselves, as opposed to the two variables in the class), but I am by no means an expert, so wait for someone else to confirm first.

    Perhaps you should use "this"?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by cyberfish View Post
    Code:
    room::room(int roomID, string roomDesc) {
        roomID = roomID;
        roomDesc = roomDesc;
    }
    Are you sure it works like that? Doesn't look right to me (assigning roomID and roomDesc to the temporary variables themselves, as opposed to the two variables in the class), but I am by no means an expert, so wait for someone else to confirm first.

    Perhaps you should use "this"?
    Hmm. That's quite right. Local variable always hide those at a deeper level.
    You can always use this->roomID = roomID or room::roomID = roomID.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Code:
    room::room(int rID, string rDesc) : roomID(rID), roomDesc(rDesc) {
    }
    While you're fixing that, might as well use the initializer list, as you should do for all member variable initialization.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question about printing a variable???
    By Hoser83 in forum C++ Programming
    Replies: 2
    Last Post: 03-31-2006, 01:57 PM
  2. How accurate is the following...
    By emeyer in forum C Programming
    Replies: 22
    Last Post: 12-07-2005, 12:07 PM
  3. Points, vectors, matrices
    By subnet_rx in forum Game Programming
    Replies: 17
    Last Post: 01-11-2002, 02:29 PM
  4. Need help
    By awkeller in forum C Programming
    Replies: 2
    Last Post: 12-09-2001, 03:02 PM
  5. Searching structs...
    By Sebastiani in forum C Programming
    Replies: 1
    Last Post: 08-25-2001, 12:38 PM