0

I am writing a program that reads a file and puts the contents into a map. The contents of the file are something like: A 1 B 3 C 3 D 2 etc.. basically its just the letters of the alphabet and their scrabble values. I got the contents of the file into the map and it works but I am trying to call the map from a string variable that is given a value before. This is the code I have right now so you can see.

#include <algorithm>
#include <fstream>
#include <iostream>
#include <set>
#include <string>
#include <vector>
#include <unordered_map>

int main() {
  std::vector<std::string> scrabble;
  {
    std::ifstream scrabble_words("/srv/datasets/scrabble-hybrid");
    for (std::string word; std::getline(scrabble_words, word);) {
      scrabble.push_back(word);
    }
  }
  int word_count = 0;
  std::string word;
  for (word; std::cin >> word;) {
    std::for_each(word.begin(), word.end(), [](char& c) { c = ::toupper(c); });
    if (std::find(scrabble.begin(), scrabble.end(), word) != scrabble.end()) {
      word_count++;
    }
  }
  std::unordered_map<std::string, int> points;
  std::string letter;
  std::ifstream in_file("/srv/datasets/scrabble-letter-values");
  for (int worth; in_file >> letter >> worth;) {
    points[letter] = worth;
  }
  std::cout << points[word[1]] << '\n';

I am trying to access the contents of the map through the characters in the variable that is set before:

std::cout << points[word[1]] << '\n';

but when I try to call it like this I get pages of error messages that I can't understand and I can't figure out how to get this to work. I am pretty sure it is because the type of word[1] is different from the type of letter but I don't know how to get around this.

user438383
  • 5,716
  • 8
  • 28
  • 43
  • 1
    `word[1]` is a `char`, but you have a `std::unordered_map <***std::string***, int>`. This means that the index operator for your unordered_map will only takes operands of type `std::string`. If you really mean to access the key-value pair with key `word[1]`, you'll have to convert it to a string first. – Telescope Oct 03 '21 at 03:30
  • Always read the very first error - you can basically ignore the rest. I always use `-fmax-errors=2` for `gcc` and `-ferror-limit=2` for `clang` (if you put max of 1 you miss out on the handy `note:` after the first error). – Elliott Oct 03 '21 at 03:30
  • 1
    If you prepare a [minimal complete example](https://stackoverflow.com/help/minimal-reproducible-example), the problem will be much easier to see, understand and fix. – Beta Oct 03 '21 at 03:31
  • Man, I read this question totally wrong. – user4581301 Oct 03 '21 at 03:31
  • Try converting `word[1]`, which is a `char`, to a `std::string`. See [this link](https://stackoverflow.com/questions/17201590/c-convert-from-1-char-to-string) for a few ways on how to do this. – Telescope Oct 03 '21 at 03:39

1 Answers1

2

Each entry in an (unordered) map is a std::pair so you access them like this, also in your case making a map of character instead of strings makes sense.

#include <cassert>
#include <iostream>
#include <sstream>
#include <unordered_map>

//-----------------------------------------------------------------------------

auto load_scores()
{
    std::unordered_map<char, int> scores;
    std::istringstream in_file("A 1 B 1 E 1 H 2");

    char letter{}; // <== not string but char!
    int score{};
    while (in_file >> letter >> score)
    {
        // insert gives error when inserting duplicates
        scores.insert({ letter, score });
    }

    // get points for 'H' without the risk of inserting extra data if 'H' 
    // wasn't there
    auto h_score = scores.at('H');
    assert(h_score == 2);

    // get score for 'E'
    auto e_score = scores['E'];
    assert(e_score == 1);

    return scores;
}

//-----------------------------------------------------------------------------

void show_scores_as_pairs(const std::unordered_map<char, int>& scores)
{
    // iterate over all entries in the unordered_map
    // a map holds key value pairs in std::pair.
    // so you need .first and .second to access your data
    for (const auto& entry : scores)
    {
        std::cout << "letter : '" << entry.first << "' has score : " << entry.second << "\n";
    }

    std::cout << std::endl;
}

//-----------------------------------------------------------------------------

void show_scores_as_structured_bindings(const std::unordered_map<char, int>& scores)
{
    // or you can use structured bindings for improved readability
    // https://en.cppreference.com/w/cpp/language/structured_binding
    for (const auto& [letter, score] : scores)
    {
        std::cout << "letter : '" << letter << "' has score : " << score << "\n";
    }

    std::cout << std::endl;
}

//-----------------------------------------------------------------------------

int main()
{
    auto scores = load_scores();
    show_scores_as_pairs(scores);
    show_scores_as_structured_bindings(scores);
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19