Monday 24 June 2024

Learn C++ by Example: Chapter 7

I have been sharing some details about my latest book "Learn C++ by Example", and gave an overview of chapter 6 last time.



You can buy my book directly here: http://mng.bz/AdAQ - or just go look at the table of contents. You can also buy it from Amazon: https://amzn.to/4dMJ0aG 

Chapter 7 is mainly about std::map and has a short section on loading a file. We build a game of "answer smash" which gives two clues to words that contain common letters at the start of one and end of the other. This means they can be overlapped. For example, a vector is a “sequential container supporting dynamic resizing,” and a torch could be defined as a “lit stick carried in one’s hand,” so smashing together the words vector and torch
[vector]  [torch] ->  [vec][tor][ch] -> vectorch
gives the answer vectorch.

Now, as you  probably know, std::map has been in C++ for a long time. In fact, C++11 introduced an unordered map, so why spend a chapter looking back rather than forwards? A reminder about some basics, like what the operator[] does (hint - it's not const and might do two things) are useful, and we'll explore a std::unordered_map in the next chapter. 

Using a map still helps us learn some new features. Many operations use a std::pair<const Key, T>, which can mean your code has 
it->first 
or 
it->second 
dotted around. Since C++17, we can use structured bindings to bind such pairs directly using more helpful names, for example:
for (const auto & [key, value] : dictionary)

We can bind to std::tuple and more besides. We can bind to arrays and even a structure’s non-static members too. For example, given

struct DataObject { int x{ 0 }; double y{ 1.23 }; };

we can write

DataObject data {};

auto [x, y] = data;

The chapter briefly looks at std::string_view, as a potentially more efficient way to concatenate strings. You need to be careful with lifetimes if you use this though. CppReference says 
It is the programmer's responsibility to ensure that std::string_view does not outlive the pointed-to character array


The chapter also includes a brief overview of big-O (order) notation, to help us think through potential inefficiencies, and this helps as a basis for unordered (hash based) lookup table in the next chapter. 

We also use a std::multimap, to allow duplicate values per key.  This allows us to load a dictionary from a file. There are several free dictionaries on the internet. Take your pick, but be warned my book only handles ASCII - other character sets would need a whole book, or at least a dedicated chapter or two! Loading a file doesn't need much work, once you've got the hang of streams. An input file stream is called std::ifstream, We can open a file, using its name, which may need to be fully pathed:

std::ifstream infile{ filename };

and use the stream in a Boolean context to see whether it is open:

if (infile)

// all good

The stream closes as it goes out of scope, which is sensible. 

To make a proper game, we need some randomness, so use std::sample to sample a few words. The challenging part is picking overlapping words.

So, some questions for you
  1. If we use operator[] for a std::map, say dictionary["word"], what are the two things that might happen?
  2. Can you remember how to find all the values for a given key in a std::multimap? (Clue: look up lower and upper bound)
  3. Have a go at finding words that can overlap a given word. (Maybe find a free dictionary so you can look up the words, and pick one at random to start with). 


No comments:

Post a Comment