我有一个带有以下声明的函数:
void Add(string_view source, string_view target);
它应该做什么:它从 string_views 添加一对单词并保存它们以供以后使用:
我有一个限制,即每个字符串只能有 1 个副本。所以我的想法是将 string_views 保存到地图(map 和相反),这些 string_views 应该是单词的视图,保存在例如向量中。
所以
void Add(string_view source, string_view target)
的想法如下:
void Add(string_view source, string_view target){
- save source string and target string to the vector<string> words;
- create views from these words and save them into map<string_view source, string_view target>
- create views from these words and save them into map<string_view target, string_view source>
}
从我之前的帖子[https://stackoverflow.com/questions/78230725/translator-exercise-by-using-string-view-c/78230782#78230782][1]我明白,字符串(插入到函数中)是暂时的,超出范围后就会被销毁。
我的问题是:如何(有效)保存 string_view 中的字符串,以便稍后可以在它们上使用 string_views
编辑:作业
开发一个名为 Translator 的类,它允许保存双语单词对,然后使用已添加的单词对将单词从一种语言翻译为另一种语言:
class Translator {
public:
void Add(string_view source, string_view target);
string_view TranslateForward(string_view source) const;
string_view TranslateBackward(string_view target) const;;
private:
//
};
更具体地说,类型为
t
的对象 Translator
应支持以下操作:
使用默认构造函数创建。在这种情况下,翻译库是空的。
添加双语对:
t.Add(source, target)
。在此调用之后,假设语言 1 中的单词 source
对应于语言 2 中的单词 target
。传递给 Add
方法的字符串可能会在 t
对象之前被销毁。
从语言 1 到语言 2 的翻译:
t.TranslateForward(source)
。如果之前对某个字符串 t.Add(source_copy, target)
进行过调用 target
并且字符串 source_copy
等于 source
(或相同),则应返回 target
。如果没有这样的调用,它应该返回一个空字符串。如果有多个此类调用,则最后一个调用应返回 target
。
从语言 2 到语言 1 的翻译:
t.TranslateBackward(target)
。如果之前对某个字符串 t.Add(source, target_copy)
进行过调用 source
并且字符串 target_copy
等于 target
(或相同),则应返回 source
。如果没有这样的调用,它应该返回一个空字符串。如果有多个此类调用,则最后一个调用应返回 source
。
限制:
Translator
类实例中的存储次数不得超过一次。如果违反此限制,您将收到“超出内存限制”错误。编辑2:仅供记录,这不是大学作业,而是在线课程(如果很重要)。 [1]: 使用 string_view (c++) 进行翻译练习
仔细阅读约束条件。
每个字符串在 Translator 类实例中存储的次数不得超过一次。
您可以在
std::string
中使用 Translator
,并且因为传递给 Add
的字符串可能不会比 t
更长久,所以您必须如此。
我们将使用成对的向量,将每个字符串仅保存一次。由于需求没有指定复杂度要求,我们可以在每个方向上线性搜索。
class Translator {
public:
void Add(string_view source, string_view target);
string_view TranslateForward(string_view source) const;
string_view TranslateBackward(string_view target) const;
private:
void EraseIf(auto pred);
auto MatchesSource(string_view source) const;
auto MatchesTarget(string_view target) const;
std::vector<std::pair<std::string, std::string>> translations;
static const std::string empty;
};
const std::string Translator::empty;
void Translator::EraseIf(auto pred)
{
translations.erase(std::remove_if(translations.begin(), translations.end(), pred), translations.end());
}
auto Translator::MatchesSource(string_view source) const
{
return [source](auto & translation) { return translation.first == source; };
}
auto Translator::MatchesTarget(string_view target) const
{
return [target](auto & translation) { return translation.second == target; };
}
void Translator::Add(string_view source, string_view target)
{
// Ensure latest is the only translation by removing matches
EraseIf(MatchesSource(source));
EraseIf(MatchesTarget(target));
// Add the translation
translations.emplace_back(source, target);
}
string_view Translator::TranslateForward(string_view source) const
{
if (auto it = std::find_if(translations.begin(), translations.end(), MatchesSource(source)); it != translations.end())
{
return it->second;
}
return empty;
}
string_view Translator::TranslateBackward(string_view target) const
{
if (auto it = std::find_if(translations.begin(), translations.end(), MatchesTarget(target)); it != translations.end())
{
return it->first;
}
return empty;
}