Cannot print out map items.

Started by
10 comments, last by Cha0sBG 13 years, 8 months ago
So i'm trying to make a config reader and it reads all sections , keys, values . When i try to put the data in a map<string, pair<string, string> > and print it out , the console gives an output: Segmentation fault.

the code:
SectionData::iterator coniter;    in.open( cpath_.c_str( ) );    if( in.fail( ) )        throw "Failed to open file [ " + cpath_ + " ]\n";        string Line, section, key, data;    if( in.is_open( ) )    {        while( !in.eof( ) ){                bool has_sections = false;        bool lineIsSection = false;        getline(in, Line);           /* Skip empty lines and lines begining with '#'            * To skip lines in the config file just put '#' in front of            * the line. that will make the handler skip the line            */	  if(Line.empty( ) || Line[0] == '#')		continue;              //remove new lines and partialy new lines               rebuild_string(Line, "\r");               rebuild_string(Line, "\n");              if(exist("[", Line) && exist("]", Line))              {                  std::cout << "Section found\n" << std::endl;                  has_sections = true;                  lineIsSection = true;              }else{                  lineIsSection = false;              }              if(has_sections && lineIsSection)               {                      SectionStart = find("[", Line );                      SectionEnd   = find("]", Line);                      section = Line.substr(SectionStart +1 , SectionEnd - SectionStart -1);                                                               continue;               }                       Split      = find("=", Line );             KeyStart   = find_first_not_empty(Line);             KeyEnd     = find_first_not_of("=", Line, KeyStart);             ValueStart = find_first_not_empty(Line, Split+1 );             ValueEnd   = Line.size( );                        key = Line.substr( KeyStart, KeyEnd - KeyStart );            data = Line.substr( ValueStart, ValueEnd - ValueStart);            //remove all empty spaces from the strings to prevent invalid results            section = rebuild_string(section, " ");            key = rebuild_string(key, " ");            data = rebuild_string(data, " ");                       SectionContents[section] = std::make_pair(key, data);                   }        SectionContents.begin();        while (coniter != SectionContents.end())        {            std::cout << "Key [ " << coniter->first << " ]\n";        coniter++;        }    }    //Close the file    in.close( );


Here is a cfg prototype
[section1]Key1 = 0xF36DKey2 = 0x1337Key3 = 0xFDA4Key4 = 0x87LD[section2]default=config.cfg



SectionContents is a typedef of my map type
and the rest of the values are defined in my class. Hope u could help out.
Advertisement
You don't initialise your iterator coniter anywhere. Above the output loop you have the line SectionContents.begin(); which doesn't do anything by itself.

I guess this should be

coniter = SectionContents.begin();

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Thanks, now it prints them, but if i could ask 1 more thing, it stores only 1 value per section. eg

[section1]Key10xF36D[section2]defaultconfig.cfg


my goal was to store all by they're sections .. if it's not too much to ask could u point out the bug :/ i don't seem to find it.
A map allows a key only once. You use the section as key. As soon as a new entry for a section is inserted the old one is gone.

You should either munge section and key in one string (doesn't feel too clean) or make a std::map<std::string,std::map<std::string,std::string> > (note the space between the ending brackets).

This allows to do this:

SectionContents[section][key] = data;

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Isn't the map<> a multi dimensional array ? Doesn't it allow a function like push back the vector's .pushback . The basic reason i used map is so i can have 1 section with multiple keys paired with the data assigned to them. The idea was given to me by pushedx , but since i have never used map it's a tough task but i will continue to try. Thanks for your help.
Quote:Original post by Endurion
A map allows a key only once. You use the section as key. As soon as a new entry for a section is inserted the old one is gone.

You should either munge section and key in one string (doesn't feel too clean) or make a std::map<std::string,std::map<std::string,std::string> > (note the space between the ending brackets).

This allows to do this:

SectionContents[section][key] = data;


Or simply use a multimap :)
Do not use .eof() to control your loop. It doesn't do what you want.

Quote:Original post by Cha0sBG
Isn't the map<> a multi dimensional array ?


No; it's an associative array.

Quote:Doesn't it allow a function like push back the vector's .pushback .


No, because .push_back means "put this at the end", and the contents of a map must be sorted, and the thing you're inserting might not logically belong at the end.

But having a .push_back does not make things multi-dimensional anyway.

Quote:The basic reason i used map is so i can have 1 section with multiple keys paired with the data assigned to them.


Yes; so you have section-contents that are a mapping from key to value, and then the whole file is represented with a mapping from section-name to section-contents. So you make a map of maps. No problem.

A multimap would work, but nesting the maps lets you get values by just indexing twice - by section-name and then by key. This is more likely to be what you want (as opposed to looking up a section-name, and then iterating through a bunch of string-pairs to find the data you want).
The .eof does the job of looping trough the contents of the config file. But for the map container ... i don't know i'll have to find some tutorials on multi-maps and figure it out on my own. I already asked way to much from you guys , and u have helped me a lot, for that i'm grateful.
Quote:Original post by Cha0sBG
The .eof does the job of looping trough the contents of the config file.

Not exactly. Zahlman's a smart guy, he knows what he is talking about and he would not have mentioned it were it not important.

std::istream::eof() is only set after a failed read attempt. This is so that the stream does not have to try "look-ahead" to see if the end has been reached. However, this also means that a naive loop-until-eof will read an extra, invalid element.

As Zahlman's link states, it is both more correct and easier (if a little less intuitive at first) to use the read condition itself as the loop condition:
while(getline(in, Line)) {   // ...}


Quote:
But for the map container ... i don't know i'll have to find some tutorials on multi-maps and figure it out on my own. I already asked way to much from you guys , and u have helped me a lot, for that i'm grateful.

SGI's site is usually a decent place to start for the standard containers: mutlimap
Well the issue with the multi-map is that i don't know if it's linux compatible , because it doesn't want to comple. Gives some not defined stuff .. And i'm sure it's in the <map> include and i've got it included so i don't know what the problem here is.

This topic is closed to new replies.

Advertisement