Using map to make sentences

Article directory

1 Concept

1.1 map

Associated container:

  • 1 will sort key values from small to large (internal implementation: red black tree);
  • 2 if the string is mapped to an integer, string must be used instead of char array;
  • Using iterator, we can find the key value and the mapped value at the same time;
  • 4 stored key value pair, unique key value.

1.2 pair

Header file: < utility >
As a simplified version of map, it often replaces binary structure and constructor.

Internal implementation of data structure:

struct pair{
	typeName1 first;
	typeName2 second;

You can compare (= =, >, > =, <, < =,! =). First, take the size of first as the standard, and then judge second only when the first is equal.

For a mapping table with key type K and value type V, the associated pair type is pair < const K, V >. The key is a constant, so the key value of the element cannot be modified, and if it is not a constant, we may modify it.

2 map usage example

2.1 problem description

Use mapping table to write a program that describes a statement structure (or syntax) and can generate random statements that match this description.

For example: can describe an English sentence as a noun and a verb or a combination of a noun or verb and an object.

For example, the following is the result of the program:

2.2 way of thinking

  • 1 read grammar
    • The expression rules of grammar are;
      • Vector < string > rule; indicates the type of rule (such as verb and noun)
      • Vector < rule > rule_collection; indicates the type of rule collection; (for example, the syntax specification at the beginning of < sentence >)
      • Map < string, rule_collection > grammar; indicates the type of mapping table; (for example, < V > corresponds to bits, jumps, < sentence > corresponds to the < nm > < V > < p >)
    • Take the first type of each statement as the key, and the string after it as the mapped value
  • 2 generate statement
    • Find a rule corresponding to < sentence >, then construct the output in sections, and output the contents of different rules and rules.
  • 3 select random elements

##2.3 implementation code

//Sentence making
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <cctype>
#include <stdexcept>
#include <cstdlib>

using std::cin; using std::cout;
using std::endl;
using std::map; using std::string;
using std::vector; using std::istream;
using std::logic_error;
using std::domain_error;

typedef vector<string> Rule;
typedef vector<Rule> Rule_collection;
typedef map<string, Rule_collection> Grammar;

//Yes blank area is true
bool space(char c){
    return isspace(c);
//Not blank area is true
bool not_space(char c){
    return  !isspace(c);

vector<string> split(const string& str){
    typedef string::const_iterator iter;
    vector<string> ret;
    iter i = str.begin();
    while(i != str.end()){
        //Ignore preceding blanks
        i = find_if(i, str.end(), not_space);
        //Find the end of the next word
        iter j = find_if(i , str.end(), space);
        //Characters copied in [I, J]
        if(i != str.end()){
            ret.push_back(string(i, j));
        i = j;
    return  ret;

Grammar read_grammar(istream& in){
    Grammar ret;
    string line;
    while(getline(in, line)){
        //Split input into single words
        vector<string> entry = split(line);

            //Use types to store associated rules
            ret[entry[0]].push_back(Rule(entry.begin()+1, entry.end()));
    return ret;

bool backeted(const string& s){
    return  s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';

int nrand(int n){
    if(n <= 0 || n > RAND_MAX){
        throw domain_error("Argument to nrand is out of range");
    const int bucket_size = RAND_MAX / n;
    int r;

        r = rand()/bucket_size;
    }while(r >= n);

    return r;


void gen_aux(const Grammar& g, const string& word, vector<string>& ret){
        //Locate the corresponding word rule
        Grammar::const_iterator it = g.find(word);
        if(it == g.end()){
            throw logic_error("empty rule");
        //Get possible rules
        const Rule_collection& c = it->second;//Enter vector < vector < string > >
        //Randomly select a rule from the rule set
        const Rule& r = c[nrand(c.size())];//To vector < string >

        for (Rule::const_iterator i = r.begin(); i != r.end(); ++i) {
            gen_aux(g, *i, ret);

vector<string> gen_sentence(const Grammar& g){
    vector<string> ret;
    //Expand the string passed by the second parameter
    //Find the string in the grammar (statement structure) of the first parameter and put its output in the third parameter
    gen_aux(g, "<sentence>", ret);
    return ret;

int main(int argc, char const *argv[]){
    vector<string> sentence = gen_sentence((read_grammar(cin)));

    vector<string>::const_iterator it = sentence.begin();
        cout << *it;
    while(it != sentence.end()){
        cout <<" " <<*it;
    cout << endl;
    return  0;
<sentence> the <nm> <v> <p>
<n> cat
<n> dog
<n> table
<nm> <n>
<nm> <a> <nm>
<a> large
<a> brown
<a> absurd
<v> sits
<v> jumps
<p> on te stairs
<p> under the sky
<p> wherever it wants
455 original articles published, 54 praised, 50000 visitors+
Private letter follow

Posted by Riparian on Tue, 10 Mar 2020 23:58:26 -0700