How do I use a std::map to change a vector of strings into another vector of characters?

163 Views Asked by At

I am am trying to make a decoder where you input the words comprising the NATO phonetic alphabet, and have it eventually spit out the translated sentences, only the actual "switcher" is not made.

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

int main() {
    map<char, string> NATOMap = { {' ',"-"}, {'a', "alfa"}, {'b', "bravo"}, {'c', "charlie"}, {'d', "delta"}, {'e', "echo"}, {'f', "foxtrot"}, {'g',"golf"}, {'h',"hotel"}, {'i',"india"}, {'j', "juliett"}, {'k', "kilo"}, {'l', "lima"}, {'m',"mike"}, {'n', "november"}, {'o', "oscar"}, {'p', "papa"}, {'q',"quebec"}, {'r', "romeo"}, {'s',"sierra"}, {'t', "tango"}, {'u', "uniform"}, {'v',"victor"}, {'w',"whiskey"}, {'x',"xray"}, {'y',"yankee"}, {'z', "zulu"} };
    
    //this input comes from a file, placed here for easier testing
    string Dinpustring = "hotel echo lima lima oscar - whiskey oscar romeo lima delta";
    
    //split text
    string temp;
    stringstream ss(Dinpustring);
    vector<string> inputDxt;
    while (getline(ss, temp, ' ')) {
        inputDxt.push_back(temp);
    }
    //spit out text (testing purpouses)
    cout << "text get:\n";
    for (int i = 0; i < inputDxt.size(); i++) {
        cout << inputDxt[i] << endl;
    }
    
    //switcher(probably contains loops)??
    
    
    //not necessary for here, only to show where its supposed to end up
        fstream Doutfile3;
    Doutfile3.open("Dencoded.txt", ios::out, ios::trunc);
    if (outfile3.is_open()) {
        outfile3 << outputDxt;
    }
    outfile3.close();
    return 0;
}

I have not previously worked with maps before, I barely got acquainted with vectors somewhat, so I have no idea where to at least start from; the rest of the code I have tested and know to work.

3

There are 3 best solutions below

10
Jan Schultke On BEST ANSWER

Your map is the wrong way around. If your input is made of NATO words, it should be map<string, char>. The first template argument is the key, i.e. what you look up, and the second argument is the value, i.e. the value associated with the looked-up key.

Since order doesn't matter here, you could use unordered_map just as well as map.

// make this global
const std::unordered_map<std::string, char> NATOMap = {
    {"-", ' '}, {"alfa", 'a'}, {"bravo", 'b'}, /* ... */
};

Also, you should use ss >> temp, not getline(ss, temp, ' ') to read each word. getline does not handle multiple consecutive spaces nicely and gives you empty strings in such cases.

Then:

// C++11
std::string decode(const std::vector<std::string>& words) {
    std::string result;
    for (const auto& word : words) {
        auto it = NATOmap.find(word);
        // If the word wasn't found, we push a '?' character.
        // You could also throw an exception in this case.
        result.push_back(it == NATOmap.end() ? '?' : it->second);
    }
    return result;
}

// C++23
std::string decode(std::span<const std::string> words) {
    return {std::from_range, words | std::views::transform([](const auto& word) {
        auto it = NATOmap.find(word);
        return it == NATOmap.end() ? '?' : it->second;
    })};
}

std::vector<std::string> inputDxt; // vector containing all input words
// fill inputDxt ...
std::cout << decode(inputDxt) << '\n';
0
fern17 On

A std::map is a data structure that sets a relationship between two things: a key and a value. In your example, the keys (char) 'a', 'b', etc. The corresponding values (string) for these keys are "alfa", "bravo", etc. (respectively).

To obtain the value associated to a key, you should do: NATOMap['a'] (would return "alfa").

In your case, you need the inverse mapping, i.e.: given a value, obtain the associated key. If this is really all you need to do, I suggest to invert your map and define it as: { {"alfa", 'a'}, {"bravo", 'b' }, etc. Then, you can do: NATOMap["alfa"] to obtain 'a'.

2
n. m. could be an AI On

For completeness' sake, there is no need to use std::map to decode the NATO phonetic alphabet speak. The first character of the long name is the character that the long name encodes, so just output that.

Here is how one could do that:

std::string natoWord;
while (std::cin >> natoWord) {
  if (natoWord == "-") 
    std::cout << " ";
  else 
    std::cout << natoWord[0];
}