I have a basic function that checks if the word is a key. The problem is my try catch block is always catching a out_of_range exception, even when the key exists. This problem only occurrs in my isExclusion function. If I check outside the isExclusion function with a static string then at will not throw the exception.
Also, is there a better or more effecient way to check if the key exists? I would rather not have to iterate through the list of keys.
#ifndef TITLES_H_
#define TITLES_H_
#include <algorithm>
#include <string>
#include <vector>
#include <map>
static std::map<std::string, int> exclusions;
static std::vector<std::string> titles;
bool isExclusion(std::string word);
#endif
#include "titles.h"
#include <iostream>
bool isExclusion(std::string word)
{
try
{
exclusions.at(word);
}
catch (std::out_of_range e)
{
return false;
}
return true;
}
#include <iostream>
#include "titles.h"
int main()
{
exclusions["is"] = 1;
exclusions["the"] = 1;
exclusions["of"] = 1;
exclusions["and"] = 1;
exclusions["a"] = 1;
exclusions["but"] = 1;
exclusions["as"] = 1;
titles.push_back("Descent of Man");
titles.push_back("The Ascent of Man");
titles.push_back("The Old Man and The Sea");
titles.push_back("A Portrait of the Artist As a Young Man");
titles.push_back("A Man is a Man but Bubblesort IS A DOG");
std::sort(titles.begin(), titles.end());
try
{
exclusions.at("the");
}
catch(std::out_of_range e)
{
std::cout << "Not found\n";
}
std::cout << "Exclusion?: " << isExclusion("hello") << std::endl;
std::cout << "Exclusion?: " << isExclusion("the") << std::endl;
for(auto i = titles.begin(); i != titles.end(); i++)
{
std::cout << *i << "\n";
}
return 0;
}
static std::map<std::string, int> exclusions;
exclusions is defined static. static globals are limited in scope to their respective compilation unit. This way it is possible to reuse names in several compilation units.
You include this line per #include "titles.h" in both compilation units. Thereby you actually create two maps with the same name, each one limited to its compilation unit.
These lines in main
exclusions["is"] = 1;
exclusions["the"] = 1;
exclusions["of"] = 1;
exclusions["and"] = 1;
exclusions["a"] = 1;
exclusions["but"] = 1;
exclusions["as"] = 1;
therefore operate on a different map than the function
bool isExclusion(std::string word)
{
try
{
exclusions.at(word);
}
catch (std::out_of_range e)
{
return false;
}
return true;
}
in the other unit. exclusions in the second unit actually is always empty.
You need to remove the static keyword and move the definition to one of the units (best main). To also use the variable in the other unit you have to declare it there as extern:
extern std::map<std::string, int> exclusions;
However it would be much better to not use global variables at all and pass references of the map and word vector to the function instead. Also make them const references while you are at it. (The function does not modify them.)
bool isExclusion(const std::map<std::string, int>& exclusions, const std::string& word)
Your problem is with this line:
static std::map<std::string, int> exclusions;
By defining this variable to be static, you are creating two separate maps in two separate translation units. main() is using one map and titles.cpp is using the other. Instead, declare the variable like this:
extern std::map<std::string, int> exclusions;
. . . and then add this line into your titles.cpp file:
std::map<std::string, int> exclusions;
This will cause the global variable to be visible to all translation units, and there will only be one actual map.
Generally it is a bad idea to use the static keyword in a header file (except within a struct or class to declare class variables). There are a few exceptions, but they are the esoteric scenarios that library writers usually worry about.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With