Contents
Code
11.3.6 单词转换程序
map<string, string> buildMap(ifstream& map_file)
{
map<string, string> trans_map;
string key;
string value;
while (map_file >> key && getline(map_file, value))
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw runtime_error("no rule for " + key);
return trans_map;
}
const string& transform(const string& s, const map<string, string>& m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(ifstream& map_file, ifstream& input)
{
auto trans_map = buildMap(map_file);
string text;
while (getline(input, text))
{
istringstream strin(text);
string word;
bool firstword = true;
while (strin >> word)
{
if (firstword)
firstword = false;
else
cout << " ";
cout << transform(word, trans_map);
}
cout << endl;
}
}
int main()
{
ifstream frule("rule.txt");
ifstream fin("infile.txt");
word_transform(frule, fin);
return 0;
}
11.4 无序容器的哈希函数
在C++中,无序容器(如std::unordered_map
、std::unordered_set
等)使用哈希函数来将键(key)映射到容器中的位置。C++标准库提供了默认的哈希函数,但也允许用户自定义哈希函数。
默认情况下,C++标准库提供了一系列用于内置类型(如int
、double
、std::string
等)的哈希函数。对于自定义类型,用户可以提供自己的哈希函数。
以下是一个使用自定义哈希函数的示例:
// 自定义哈希函数
struct MyHash {
std::size_t operator()(const std::string& str) const {
std::size_t hash = 0;
for (char ch : str) {
hash = hash * 31 + ch; // 使用31作为乘子,这是一种常用的哈希算法
}
return hash;
}
};
int main() {
// 使用自定义哈希函数创建unordered_map
std::unordered_map<std::string, int, MyHash> myMap;
// 插入键值对
myMap["apple"] = 5;
myMap["banana"] = 3;
myMap["orange"] = 7;
// 访问值
std::cout << "Number of apples: " << myMap["apple"] << std::endl;
return 0;
}
在这个例子中,MyHash
是一个自定义的哈希函数对象,它重载了函数调用运算符operator()
来计算字符串的哈希值。然后,我们使用这个自定义的哈希函数类作为std::unordered_map
的第三个模板参数,以指定键类型为std::string
时要使用的哈希函数。
自定义哈希函数时,要确保哈希函数能够均匀地将不同的键映射到不同的位置,以提高无序容器的性能。
Homework
Test 11.3
int main()
{
map<string, size_t> word_count;
set<string> exclude = { "The", "But", "And", "Or", "An", "A", "the", "but", "and", "or", "an", "a" };
string word;
ifstream fin("infile.txt");
while (fin >> word)
{
if (exclude.find(word) == exclude.end())
++word_count[word];
}
//cout map contents
for (auto& w : word_count)
cout << w.first << " occurs " << w.second << (w.second > 1 ? " times" : " time") << endl;
return 0;
}
Test 11.4
int main()
{
map<string, size_t> word_count;
set<string> exclude = { "The", "But", "And", "Or", "An", "A", "the", "but", "and", "or", "an", "a" };
string word;
ifstream fin("infile.txt");
while (fin >> word)
{
//handle upper and punctuation
for (string::iterator beg = word.begin(); beg != word.end(); )
{
if (isupper(*beg))
{
*beg = tolower(*beg);
++beg;
}
else if (ispunct(*beg))
beg = word.erase(beg);
else
++beg;
}
if (exclude.find(word) == exclude.end())
++word_count[word];
}
//cout map contents
for (auto& w : word_count)
cout << w.first << " occurs " << w.second << (w.second > 1 ? " times" : " time") << endl;
return 0;
}
Test 11.7
void add_family(map<string, vector<string>>& fc, const string& family, const vector<string>& childs)
{
auto it = fc.find(family);
if (it == fc.end())
fc[family] = childs; //如果不在,创建family键
else
copy(childs.begin(), childs.end(), back_inserter(fc[family])); //如果在,追加新Childs
}
int main()
{
map<string, vector<string>> family_child;
add_family(family_child, "He", { "jian", "gan" });
add_family(family_child, "Mu", { "ou", "hua" });
add_family(family_child, "He", { "wen" });
for (auto& f : family_child)
cout << f.first << " ";
for (auto& s : family_child["He"])
cout << s << " ";
return 0;
}
Test 11.9
map<string, list<int>> word_row;
Test 11.11
bool compareIsbn(const my_sales_data& lhs, const my_sales_data& rhs)
{
return lhs.isbn() < rhs.isbn();
}
int main()
{
typedef bool (*pf)(const my_sales_data& lhs, const my_sales_data& rhs); //pf是指向bool (const my_sales_data& lhs, const my_sales_data& rhs)函数类型的指针
multiset<my_sales_data, pf> bookstore(compareIsbn);
return 0;
}
Test 11.12
int main()
{
vector<pair<string, int>> pvec;
ifstream fin("infile.txt");
string str;
int i;
while (fin >> str && fin >> i)
pvec.push_back(make_pair(str, i));
for (auto& p : pvec)
cout << p.first << " " << p.second << endl;
return 0;
}
Test 11.14
void add_family(map<string, vector<string>>& fc, const string& family, const vector<string>& childs)
{
auto it = fc.find(family);
if (it == fc.end())
fc[family] = childs; //如果不在,创建family键
else
copy(childs.begin(), childs.end(), back_inserter(fc[family])); //如果在,追加新Childs
}
int main()
{
map<string, vector<string>> family_child;
pair<string, string> cild_date;
add_family(family_child, "He", { "jian", "gan" });
add_family(family_child, "Mu", { "ou", "hua" });
add_family(family_child, "He", { "wen" });
vector<pair<string, string>> cdvec;
for (auto& f : family_child)
for (auto beg = f.second.begin(); beg != f.second.end(); ++beg)
cdvec.push_back(make_pair(*beg, *beg + "'s birthday"));
for (auto& cd : cdvec)
cout << cd.second << " ";
return 0;
}
Test 11.16
map<string, int> dict{ {"hello", 5}, {"world", 4} };
auto it = dict.begin();
it->second = 2;
cout << it->second << endl;
Test 11.19
typedef bool (*pf)(const my_sales_data& lhs, const my_sales_data& rhs); //pf是指向bool (const my_sales_data& lhs, const my_sales_data& rhs)函数类型的指针
multiset<my_sales_data, pf> bookstore(compareIsbn);
multiset<my_sales_data, pf>::iterator var = bookstore.begin();
Test 11.22
map<string, vector<int>> m;
pair<map<string, vector<int>>::iterator, bool> var = m.insert(make_pair("瓶子君", vector<int>{1, 5, 2}));
Test 11.23
multimap<string, string> family_childs;
family_childs.insert(make_pair("He", "jian"));
family_childs.insert(make_pair("He", "gan"));
family_childs.insert(make_pair("Mu", "ou"));
family_childs.insert(make_pair("Mu", "hua"));
for (auto& f : family_childs)
cout << f.first << " " << f.second << endl;
Test 11.31
void findele(multimap<string, string> &mm, const string &name)
{
auto it = mm.find(name);
if (it != mm.end())
{
it = mm.erase(it);
if (it->first == name)
it = mm.erase(it);
}
else
cout << "no element" << endl;
}
int main()
{
multimap<string, string> mm{
make_pair("Hou", "<stl源码剖析>"), make_pair("Hou", "<泛型思维>"), make_pair("Li", "<C++>"),
make_pair("Li", "<lulu>"), make_pair("Ji", "<引擎开发>")
};
findele(mm, "Li");
for (auto s : mm)
cout << s.first << " " << s.second << " ";
return 0;
}
Test 11.33
map<string, string> buildMap(ifstream& map_file)
{
map<string, string> trans_map;
string key;
string value;
while (map_file >> key && getline(map_file, value))
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw runtime_error("no rule for " + key);
return trans_map;
}
const string& transform(const string& s, const map<string, string>& m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(ifstream& map_file, ifstream& input)
{
auto trans_map = buildMap(map_file);
string text;
while (getline(input, text))
{
istringstream strin(text);
string word;
bool firstword = true;
while (strin >> word)
{
if (firstword)
firstword = false;
else
cout << " ";
cout << transform(word, trans_map);
}
cout << endl;
}
}
int main()
{
ifstream frule("rule.txt");
ifstream fin("infile.txt");
word_transform(frule, fin);
return 0;
}
Test 11.38
int main()
{
unordered_map<string, size_t> word_count;
set<string> exclude = { "The", "But", "And", "Or", "An", "A", "the", "but", "and", "or", "an", "a" };
string word;
ifstream fin("infile.txt");
while (fin >> word)
{
if (exclude.find(word) == exclude.end())
++word_count[word];
}
//cout map contents
for (const auto& w : word_count)
cout << w.first << " occurs " << w.second << (w.second > 1 ? " times" : " time") << endl;
return 0;
}
unordered_map<string, string> buildMap(ifstream& map_file)
{
unordered_map<string, string> trans_map;
string key;
string value;
while (map_file >> key && getline(map_file, value))
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw runtime_error("no rule for " + key);
return trans_map;
}
const string& transform(const string& s, const unordered_map<string, string>& m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(ifstream& map_file, ifstream& input)
{
auto trans_map = buildMap(map_file);
string text;
while (getline(input, text))
{
istringstream strin(text);
string word;
bool firstword = true;
while (strin >> word)
{
if (firstword)
firstword = false;
else
cout << " ";
cout << transform(word, trans_map);
}
cout << endl;
}
}
int main()
{
ifstream frule("rule.txt");
ifstream fin("infile.txt");
word_transform(frule, fin);
return 0;
}