Like Tree1Likes
  • 1 Post By ex-mortis

Reading from file stream using ifstream object and storing in a map

This is a discussion on Reading from file stream using ifstream object and storing in a map within the C++ Programming forums, part of the General Programming Boards category; Code: void loadGames(){ std::ifstream load("Gamelist.gl"); num_holder; title_holder; hours_holder; load.getline(num_holder, 1, ' '); load.getline(title_holder, 20, ' '); load.getline(hours_holder, 5); Games[num_holder].title = ...

  1. #1
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37

    Reading from file stream using ifstream object and storing in a map

    Code:
    void loadGames(){
        std::ifstream load("Gamelist.gl");
        num_holder;
        title_holder;
        hours_holder;
        load.getline(num_holder, 1, ' ');
        load.getline(title_holder, 20, ' ');
        load.getline(hours_holder, 5);
        Games[num_holder].title = title_holder;
        Games[num_holder].hoursPlayed = hours_holder;
    }
    I'm having some trouble getting this to work. At first I tried to read directly into an int, std::string and double with no luck so I tried reading into character arrays and converting them to ints and std::strings with even less luck. I think this is probably not a good way to go about this and there has to be a more efficient way. Can someone help please?

    P.S. Posting the complete code is unnecessary but here is the definition of the std::map container I'm placing the values in just in case:

    Code:
    struct Game{
        std::string title;
        double hoursPlayed;
    
    };
    
    typedef std::map<int, Game> gameMap;
    gameMap Games;
    Last edited by ex-mortis; 07-24-2012 at 10:39 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,414
    What are these statements?
    Code:
    num_holder;
    title_holder;
    hours_holder;
    Based on subsequent code, it looks like they are variables, but you didn't show their declarations, plus writing them like this results in code that has no net effect. You could very well have written:
    Code:
    ;
    ;
    ;
    Did you perhaps intend to declare (and hence define) the variables instead?
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,439
    What does the file itself look like?

    istream::getline - C++ Reference
    Code:
        num_holder;
        title_holder;
        hours_holder;
        load.getline(num_holder, 1, ' ');
        load.getline(title_holder, 20, ' ');
        load.getline(hours_holder, 5);
    What exactly are the first 3 lines doing?
    Are they declaring char arrays of a suitable size, or is this just down to your creative editing?

    Passing 1 to getline() makes no sense, as it stores (n-1) (ie, ZERO) characters.

    The problem with incremental parsing happens when the file is malformed, and you lose sync with what is in the file compared to what you expect.
    Say for example someone tries to enter a 25 character title_holder. The excess characters will get stored in hours_holder.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  4. #4
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by laserlight View Post
    What are these statements?
    Code:
    num_holder;
    title_holder;
    hours_holder;
    Based on subsequent code, it looks like they are variables, but you didn't show their declarations, plus writing them like this results in code that has no net effect. You could very well have written:
    Code:
    ;
    ;
    ;
    Did you perhaps intend to declare (and hence define) the variables instead?
    Like I said, I am not sure what types of variables to declare because I haven't found a method that works yet and so I omitted the declarations.


    Quote Originally Posted by Salem View Post
    What does the file itself look like?

    istream::getline - C++ Reference
    Code:
        num_holder;
        title_holder;
        hours_holder;
        load.getline(num_holder, 1, ' ');
        load.getline(title_holder, 20, ' ');
        load.getline(hours_holder, 5);
    What exactly are the first 3 lines doing?
    Are they declaring char arrays of a suitable size, or is this just down to your creative editing?

    Passing 1 to getline() makes no sense, as it stores (n-1) (ie, ZERO) characters.

    The problem with incremental parsing happens when the file is malformed, and you lose sync with what is in the file compared to what you expect.
    Say for example someone tries to enter a 25 character title_holder. The excess characters will get stored in hours_holder.
    Right now this code is completely meaningless and is only a general outline of what I want to do. I realize it doesn't work. Basically this is a simple program that stores the titles and number of hours played of videogames in the order they were added in a map. I have a function called saveGames that looks like this:

    Code:
    void saveGames(){
        std::ofstream save("Gamelist.gl");
        for(std::map<int, Game>::iterator ii=Games.begin(); ii!=Games.end(); ++ii){
            save << ii->first << " " << ii->second.title << " " << ii->second.hoursPlayed << std::endl;
        }
        save.close();
    }
    And the contents of Gamelist.gl are in this format: <number><whitespace><title (I have a function that replaces whitespaces with underscores)><whitespace><hours>. I want to read data with whitespaces as the delimiting character and store them in variables that I then assign to my map.

    I'm not exactly sure how to do that so I am really just asking what the best way to go about that is, not how to make the current code compile.

    P.S. That's weird. Not like anyone would try to enter a 25 character title (maybe a miscalculation, I will probably raise the max amount). Do you by any chance know how to avoid that or do you know a safer and more reliable way?

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,167
    Like I said, I am not sure what types of variables to declare because I haven't found a method that works yet and so I omitted the declarations.
    No. You did not say that. You said you had tried a couple of different things. It is natural for us to assume that what you posted is what you have written.

    This forum has some awesome skill in the form of its community, but we can't read minds.

    Please show us exactly what you are trying to do exactly as you are trying to do it or we can only speculate about what is going wrong.

    Soma

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,439
    If you're pretty sure that space is a good delimiter in your file when you generate it, then perhaps something like this.
    Code:
    #include<iostream>
    #include<fstream>
    #include<string>
    #include<sstream>
    using namespace std;
    int main()
    {
        string line;
        string one, two, three;
        ifstream load("Gamelist.gl");
        while ( getline(load,line) ) {
            istringstream is(line);
            if ( is >> one >> two >> three ) {
                cout << one << "," << two << "," << three << endl;
            }
        }
    }
    Everything is a std::string, so no messy char arrays where you have to guess the length is "good enough".

    Results
    Code:
    $ cat Gamelist.gl 
    1 hello world
    2 this_is_a_very_long_string and_this_is_pretty_long_as_well
    $ ./a.out 
    1,hello,world
    2,this_is_a_very_long_string,and_this_is_pretty_long_as_well
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by phantomotap View Post
    No. You did not say that. You said you had tried a couple of different things. It is natural for us to assume that what you posted is what you have written.

    This forum has some awesome skill in the form of its community, but we can't read minds.

    Please show us exactly what you are trying to do exactly as you are trying to do it or we can only speculate about what is going wrong.

    Soma
    Well, I'm sorry. "At first I tried to read directly into an int, std::string and double with no luck so I tried reading into character arrays and converting them to ints and std::strings with even less luck. I think this is probably not a good way to go about this and there has to be a more efficient way." seemed pretty straightforward to me. But I did say I don't have a clue how to go about it so I cannot show you exactly how I am trying to do it. I only included the code as a substitute for a long and potentially confusing explanation.

    EDIT:

    Quote Originally Posted by Salem View Post
    if ( is >> one >> two >> three ) {
    cout << one << "," << two << "," << three << endl;
    }
    [/code]
    My best guess is that this places the contents of is into one up until the first whitespace, two up until the next, and then three up until the next (end of file). Is that correct? If so, I think that would work perfectly.

    EDIT: Actually I overlooked something, since variables one and three need to be int and double respectively. Is there something similar to istringstream that applies to numbers?
    Last edited by ex-mortis; 07-24-2012 at 11:47 AM.

  8. #8
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Got it work just in case somebody else out there has a similar problem. This is the final loadGames() function:

    Code:
    void loadGames(){
        std::string line, num_holder, title_holder, hours_holder;
        std::ifstream load("Gamelist.gl");
        long int num;
        double hours;
        while (getline(load, line)) {
            std::istringstream iss(line);
            if ( iss >> num_holder >> title_holder >> hours_holder ) {
                num = strtol(num_holder.c_str(), NULL, 0);
                hours = strtod(hours_holder.c_str(), NULL);
            }
            std::replace(title_holder.begin(), title_holder.end(), '_', ' ');
            Games[num].title = std::string(title_holder);
            Games[num].hoursPlayed = hours;
        }
    }
    It works beautifully.
    Salem likes this.

  9. #9
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,428
    Why are you casting to std::string when it already is a std::string?
    Games[num].title = std::string(title_holder);
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,627
    Actually it is a constructor call, the copy constructor to be specific.

  11. #11
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by Elysia View Post
    Why are you casting to std::string when it already is a std::string?
    Games[num].title = std::string(title_holder);
    Nice spot. It's a little carry-over from my char array design that I forgot to fix actually. Although what it does at the moment isn't catastrophic having a copy is pretty much unnecessary. Thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Segfault in reading file stream
    By brobot in forum C Programming
    Replies: 5
    Last Post: 12-19-2011, 01:55 PM
  2. Problem reading from file stream
    By shmitson in forum C Programming
    Replies: 0
    Last Post: 04-05-2011, 04:37 PM
  3. Help - Reading a file and storing it as a 2d Array.
    By MetallicaX in forum C Programming
    Replies: 2
    Last Post: 03-08-2009, 07:33 PM
  4. reading file and storing to arrays
    By dayknight in forum C Programming
    Replies: 4
    Last Post: 04-27-2006, 05:17 AM
  5. File Reading and storing to 1 variable
    By Rare177 in forum C Programming
    Replies: 34
    Last Post: 07-13-2004, 12:58 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21