1

Hi I have been racking my head over trying to make my iterator pointer find the specified key for the map stl container. The following project is for my parser excercise where we are given a file and the point is to parse through it and read each line by line. The file is supposed to be in the project folder to be read. The file has the following text

[settings]

;this is the settings section

fullscreen = true

gamepad = false

windowWidth = 800

windowHeight = 600

[levels]

numLevels = 3

Level1 = file1.lvl

Level2= file2.lvl

Level3=file3.lvl

[player]

name = Student

speed = 5.0

[enemy]

name ="Zombie"

speed = 1.0

and we are supposed to make a Mapkey that's a combination of section (which is the text in brackets) and "|" and key (that is the text before the =), the value is the text after the equals sign.

I have code that works up until I try to use the find function to find the Mapkey specified. Can someone help??

#include <iostream>
#include <fstream> 
#include <string>
#include <map>
#include <algorithm>
using namespace std;

std::map<std::string, std::string> m_mapPairs;



int main()
    {
        string strLine;
        fstream myFile;


        myFile.open("New Text Document.txt"); //name of the file to be read
        if (myFile.is_open())
        {
            static string section = " ";
            string key = " ";
            string value= " ";
            while (!myFile.eof())
            {

                    getline(myFile, strLine);
                    if (strLine.find("[") !=-1) 
                    {
                        int index1 = strLine.find_first_of("[");    //finds it in a line, if it does it puts it in index 1 if it doesnt it doesnt bother
                        int index2 = strLine.find_first_of("]");//finds it in a line, if it does it puts it in index 2 if it doesnt it doesnt bother
                         section = strLine.substr(index1 + 1, index2 - 1);
                         section = section + "|";

                    }
                    if (strLine.find("=") != -1)
                    {
                        int index1 = strLine.find("");
                        int index2 = strLine.find("=");
                        key = strLine.substr(index1, index2 );

                    }
                    if (strLine.find("=")!=-1 )
                    {
                        int index1 = strLine.find("="); //finds it in a line, if it does it puts it in index 1 if it doesnt it doesnt bother
                        value = strLine.substr(index1+1 , 11);

                    }

                    if (strLine.find(";") > -1)
                    {
                        int index1 = strLine.find(";"); //finds it in a line, if it does it puts it in index 1 if it doesnt it doesnt bother
                        string ivalue = strLine.substr(index1 + 1, 11);

                    }
                    if (key != "") {

                        std::string Thekey = section + key;
                        m_mapPairs.insert(std::pair<std::string, std::string>(Thekey, value));
                    }
            }


            std::map<std::string, std::string>::iterator iter;      //iterating through all the keys
            iter = m_mapPairs.begin();
            while (iter != m_mapPairs.end())
            {


                std::cout << iter->first << "\'s value is ";
                std::cout << iter->second << std::endl;
                iter++;

            }



            iter = m_mapPairs.find("settings|windowWidth");     //trying to find this key in the map but cant find it

            if (iter != m_mapPairs.end())
            {
                std::cout << "found: " << std::endl;
                return true;
            }
            else
            {
                return false;
            }


            myFile.close();
        }



        int a;
        std::cin >> a;
        return (0);
    }

I will be grateful for any help. Thanks

Jodocus
  • 6,404
  • 1
  • 22
  • 38
  • Unrelated to your problem, but please read [Why is iostream::eof inside a loop condition considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – Some programmer dude Apr 09 '18 at 12:55
  • Not the problem but `static string section = " ";` can just be `string section;` – NathanOliver Apr 09 '18 at 12:56
  • More related to your problem, can you please try to show us a smaller part of the input file, then show the expected and actual output of your program (using the smaller input set)? And you have tried [to debug your program](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)? – Some programmer dude Apr 09 '18 at 12:57
  • 1
    It looks like the problem is you are leaving trialing spaces at the end of the string you create. Step through your code with a debugger to confirm. If you are you will need to write a trim function or change how you parse the line. – NathanOliver Apr 09 '18 at 12:58
  • @Someprogrammerdude Hey its supposed to look exactly like the stuff on jejos console. – Enoch Thomas Apr 10 '18 at 20:45
  • Please take some time to read [the help pages](http://stackoverflow.com/help), and [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask). What "it" is supposed to look like should be in your question. As text (not as an image). – Some programmer dude Apr 10 '18 at 20:52

2 Answers2

0

I don't know what exactly was the problem. However, I have changed the way it parse the words and now its working. Following is the output:

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>

int main()
{
    std::map<std::string, std::string> m_mapPairs;
    std::string strLine;
    std::fstream myFile;
    myFile.open("New Text Document.txt"); //name of the file to be read

    if (myFile.is_open())
    {
        std::string section; section.clear();
        std::string key;     key.clear();
        std::string value;   value.clear();
        while (!myFile.eof())
        {
            getline(myFile, strLine);

            if (strLine[0] == '[' && strLine[strLine.size() - 1] == ']')
            {
                section.clear();
                int index2 = strLine.find_first_of("]");
                section = strLine.substr(1, index2 - 1);
                section += "|";
                continue;
            }
            if (strLine[0] == ';') continue;

            std::string tempStore; tempStore.clear();
            for (size_t i = 0; i < strLine.size(); ++i)
            {
                if (strLine[i] != ' ' && strLine[i] != '=')
                    tempStore += strLine[i];
                if (strLine[i] == ' ' && strLine[i + 1] == '=')
                {
                    key = section + tempStore;
                    tempStore.clear();
                }
                if (i + 1 == strLine.size())
                    value = tempStore;
            }

            if (key.size() != 0 && value.size() != 0)
            {
                m_mapPairs[key] = value;
                key.clear();
                value.clear();
            }
        }
        myFile.close();
    }

    if (m_mapPairs.size() != 0)
        for (const auto& it : m_mapPairs)
            std::cout << it.first << " 's Value: \t" << it.second << std::endl;

    std::cout << std::endl;

    if(m_mapPairs.find("settings|windowWidth") != m_mapPairs.end())
        std::cout << "found! " << std::endl;
    else
        std::cout << "Not found! " << std::endl;

    std::cin.get();
}

One thing you could do is, move your debugger part after you saved all keys and values to map. i.e. after closing the file.

UPDATE:

I did debugged your code; followings are the result or logical problems in your while (!myFile.eof()){....}

  1. Your code do not combine section + key before inserting in to the map. Because your condition to insert to map is weak( if (key != "") is weak). This result to insert some wrong keys to be inserted with "" values. Therefore instead of that, use this: if (key.size() != 0 && value.size() != 0) like I made in my implementation.

  2. The parsing section in the both if (strLine.find("=") != -1), have a bug, that they save key and values to the map as follows:

    "settings|fullscreen " " true" -->> In your code(with space)

    "settings|fullscreen" "true" -->> Actually needed

This happens for all your inputs. Here is the image view. As long as you do not change the code inside while (!myFile.eof()){....} as follows, you can not look for the key iter = m_mapPairs.find("settings|windowWidth");.

Here is the fixed solution:

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

std::map<std::string, std::string> m_mapPairs;
int main()
{
    string strLine;
    fstream myFile;


    myFile.open("New Text Document.txt"); //name of the file to be read
    if (myFile.is_open())
    {
        static string section = "";
        string key = "";
        string value = "";

        while (!myFile.eof())
        {
            getline(myFile, strLine);
            if (strLine.find("[") != -1)
            {
                int index1 = strLine.find_first_of("[");   
                int index2 = strLine.find_first_of("]");
                section = strLine.substr(index1 + 1, index2 - 1);
                section = section + "|";
            }
            if (strLine.find("=") != -1)
            {
                int index1 = strLine.find("");
                int index2 = strLine.find("=");
                //change in following line
                key = strLine.substr(index1, index2-1);
            }
            if (strLine.find("=") != -1)
            {
                int index1 = strLine.find("=");
                //change in following line
                value = strLine.substr(index1 + 2, strLine.size()-1);
            }
            if (strLine.find(";") > -1)
            {
                int index1 = strLine.find(";"); 
                string ivalue = strLine.substr(index1 + 1, 11);
            }
            //change in following line
            if (key.size() != 0 && value.size() != 0)
            {
                std::string Thekey = section + key;
                m_mapPairs.insert(std::pair<std::string, std::string>(Thekey, value));
            }
        }
        myFile.close();
    }

    std::map<std::string, std::string>::iterator iter;      //iterating through all the keys
    iter = m_mapPairs.begin();
    while (iter != m_mapPairs.end())
    {
        std::cout << iter->first << "\t Value: ";
        std::cout << iter->second << std::endl;
        iter++;
    }

    iter = m_mapPairs.find("settings|windowWidth");     //trying to find this key in the map but cant find it

    if (iter != m_mapPairs.end())
    {
        std::cout << "found ! " << std::endl;
    }
    else
    {
        std::cout << "NOT found: " << std::endl;
    }

    std::cin.get();//return (0);
}

Hope this was helpful.

JeJo
  • 20,530
  • 5
  • 29
  • 68
  • Jejo yeah i looked at your code. But i need to implement it using my code. I still dont know whats wrong with mine. However I will take a look at it. – Enoch Thomas Apr 09 '18 at 21:35
  • @EnochThomas: In your code was the parsing part working properly? If so, consider changing after from the example given above. I have got a lot of warnings due to comparison between unsigned int and -1, when I tested your code. That's why I changed a bit. – JeJo Apr 09 '18 at 21:40
  • hey jejo, ive tried doing everything you have suggested me to do, but I didnt change any of the stuff in the while (!myFile.eof()){....}. Cuz I dont want to change that part, but after doing all that you have asked me to do I still find myself with the same problem. – Enoch Thomas Apr 10 '18 at 20:42
  • how do u fix the code for the value to get zombie without the ""?? – Enoch Thomas Apr 13 '18 at 05:44
  • Cuz if you run the code what happens is zombie comes up as zombie". Which is not what i want. I want it without the "" – Enoch Thomas Apr 13 '18 at 21:23
0

Your map "m_mapPairs" contains space at the end of the key "settings|windowWidth ". However, the key that you are passing to find does not contain a space at the end. That's why find is not successful.

-->m_mapPairs.find("settings|windowWidth").

Amit Rastogi
  • 714
  • 1
  • 8
  • 21
  • did you check using --> iter = m_mapPairs.find("settings|windowWidth "); //note that key passed to find contains a space at the end – Amit Rastogi Apr 11 '18 at 02:57