We are going to build up a cheap dictionary of one-to-one mappings from English words to their German translations, and store them in std::deque structures. The program will read such a dictionary from a file and one from standard input, and print one large merged dictionary on the standard output again.
- There are a lot of headers to include this time, and we declare that we use the std namespace:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <deque>
#include <tuple>
#include <string>
#include <fstream>
using namespace std;
- A dictionary entry should consist of a symmetric mapping from a string in one language to a string in another language:
using dict_entry = pair<string, string>;
- We are going to both print such pairs to the terminal and read them from user input, so we need to overload the << and >> operators:
namespace std {
ostream& operator<<(ostream &os, const dict_entry p)
{
return os << p.first << " " << p.second;
}
istream& operator>>(istream &is, dict_entry &p)
{
return is >> p.first >> p.second;
}
}
- A helper function that accepts any input stream object will help us in building a dictionary from it. It constructs std::deque of dictionary entry pairs, and they are all read from the input stream until it is empty. Before returning it, we sort it:
template <typename IS>
deque<dict_entry> from_instream(IS &&is)
{
deque<dict_entry> d {istream_iterator<dict_entry>{is}, {}};
sort(begin(d), end(d));
return d;
}
- We create two individual dictionary data structures from different input streams. One input stream is opened from the dict.txt file, which we assume to exist. It contains word pairs, line by line. The other stream is the standard input:
int main()
{
const auto dict1 (from_instream(ifstream{"dict.txt"}));
const auto dict2 (from_instream(cin));
- As the helper function, from_instream, has already sorted both the dictionaries for us, we can feed them directly into the std::merge algorithm. It accepts two input ranges via its begin/end iterator pairs, and one output. The output will be the user shell:
merge(begin(dict1), end(dict1),
begin(dict2), end(dict2),
ostream_iterator<dict_entry>{cout, "n"});
}
- We can compile the program now, but before running it, we should create the dict.txt file with some example content. Let's fill it with some English words and their translations to German:
car auto
cellphone handy
house haus
- Now, we can launch the program while piping some English-German translations into its standard input. The output is a merged and still sorted dictionary, which contains the translations of both the inputs. We could create a new dictionary file from that:
$ echo "table tisch fish fisch dog hund" | ./dictionary_merge
car auto
cellphone handy
dog hund
fish fisch
house haus
table tisch