Jump to content
  • Advertisement
Sign in to follow this  
Cha0sBG

Cannot print out map items.

This topic is 2956 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 = 0xF36D
Key2 = 0x1337
Key3 = 0xFDA4
Key4 = 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.

Share this post


Link to post
Share on other sites
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();

Share this post


Link to post
Share on other sites
Thanks, now it prints them, but if i could ask 1 more thing, it stores only 1 value per section. eg


[section1]
Key1
0xF36D

[section2]
default
config.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.

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!