Dictionary app using WIn32 I'm creating a dictionary app using Win32 API. I stored the word meaning in a file called dictionary.dic in the following format:

Word  Meaning
A     The first letter
B     The second letter
... and so on

As my window is created, I load the dictionary file into the std::map object using this code:
std::map&lt;wstring, wstring&gt; dict;
...
std::wifstream stream(L&quot;dictionary.dic&quot;);
std::wstring temp, fileContent = L&quot;&quot;;
while (std::getline(stream, temp)) {
    fileContent += temp;
    fileContent.push_back(L'\n');
}
std::vector&lt;wstring&gt; lines = split(fileContent, L'\n');
for (std::wstring line : lines) {
    std::vector&lt;wstring&gt; word = split(line, L'\t');
    dict.insert(dict.end(), make_pair(word[0], word[1]));
}

And when the user search the word, I'm using this code to display the meaning:
std::wstring enteredWord;
map&lt;wstring, wstring&gt;::iterator mi;
mi = dict.find(toLower(enteredWord));
if (mi != dict.end()) {
    //display meaning
}
else {
    //word not found
}

I used these functions to convert text to lowercase and split text:
I'm using this function to split the text:
std::vector&lt;std::wstring&gt; &amp;split(const std::wstring &amp;s, WCHAR delim, std::vector&lt;std::wstring&gt; &amp;elems) {
    std::wstringstream ss(s);
    std::wstring item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector&lt;std::wstring&gt; split(const std::wstring &amp;s, WCHAR delim) {
    std::vector&lt;std::wstring&gt; elems;
    split(s, delim, elems);
    return elems;
}

std::wstring toLower(std::wstring val) {
    std::wstring temp = val;
    std::transform(temp.begin(), temp.end(), temp.begin(), tolower);
    return temp;
}

Is there a more efficient way to create a dictionary in Win32 / C++?
Is there a more efficient way to create a dictionary in win32 / c++.


Yes :-)

Let's look at the code:

Reading the file


// Read a file line by line.
while (std::getline(stream, temp)) {

    // Build one long........ string in memory.
    fileContent += temp;
    fileContent.push_back(L'\n');
}

// Then you split the long...... line you just built
// back into a vector of lines (using the '\n' you just inserted)
// to mark the line boundries.
std::vector&lt;wstring&gt; lines = split(fileContent, L'\n');



Issues


So you are basically doing the same work twice.
You are building a string in the most inefficient way possible.
Because you did not reserve space you are reallocating that string again and again and again. Each reallocation requires the whole string to be copied.


Why not read the lines directly into the vector?

 std::vector&lt;wstring&gt; lines;
 std::wstring line;

 while(std::getline(stream, line)) {
     lines.push_back(line);
 }


We can even do better than that with a tiny bit of work.

 // Define a class that represents a line.
 // Then define the input operator so it knows how to read itself.
 // Then define a conversion operator so it can be converted into a string.

 class Line
 {
     std::wstring   data;
     friend std::istream&amp; operator&gt;&gt;(std::istream&amp; str, Line&amp; value)
     {
         return std::getline(str, value.data);
     }
     operator std::wstring&amp;() const
     {
         return data;
     }
};
using LineStreamIter = std::istream_iterator&lt;Line&gt;;
// now you can declare your vector and load it in a single line.
std::vector&lt;std::wstring&gt;  lines(LineStreamIter(source), LineStreamIter());


Moving on to loading the map:


for (std::wstring line : lines) {
    std::vector&lt;wstring&gt; word = split(line, L'\t');
    dict.insert(dict.end(), make_pair(word[0], word[1]));
}



So basically you are saving your map as two strings separated by the first tab onto a single line. I assume there are no '\n' characters in the meaning, otherwise your encoding is going to break.

But again this is ineffecient as you build a vector in place then use that to build the dictionary. Why not just build the dictionary directly from the file.

std::map&lt;std::wstring, std::wstring&gt; dict;

std::wstring word;
std::wstring meaning;

while(std::getline(source, word, '\t') &amp;&amp; std::getline(source, meaning))
{
    dict.emplace_back(std::piecewise_construct, word, meaning);
} 


Note: std::getline() allows you specify a third argument that defines the line terminator (by default this is '\n'). By setting this to tab '\t' you can read up-to (but not including) the tab and extract the word first then extract the meaning separately.

I would take this a step further and define a dictionary class with a specific interface then use std::map internally. This has several advantages.


You can replace std::map with std::vector later as suggested by @ilmale
You can write the load/save functions in a self contained way.


Here is an outline:

class Dict
{
    class DictFileElement
    {
        std::pair&lt;std::wstring, std::wstring&gt;   value;
        frined std::istream&amp; operator&gt;&gt;(std::istream&amp; s, DictFileElement&amp; value);
        frined std::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, DictFileElement const&amp; value);
    };

    std::map&lt;std::wstring, std::wstring&gt;  data;
    public:
        Dict(std::string fileName);
        std::wstring getMeaning(std::wstring const&amp; word);
};
// I leave the implementation to you .
// Should be easy given all the code I wrote above.