正确从 string_view 复制临时字符串 (C++ 17)

问题描述 投票:0回答:1

我有一个带有以下声明的函数:

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
应支持以下操作:

  1. 使用默认构造函数创建。在这种情况下,翻译库是空的。

  2. 添加双语对:

    t.Add(source, target)
    。在此调用之后,假设语言 1 中的单词
    source
    对应于语言 2 中的单词
    target
    。传递给
    Add
    方法的字符串可能会在
    t
    对象之前被销毁。

  3. 从语言 1 到语言 2 的翻译:

    t.TranslateForward(source)
    。如果之前对某个字符串
    t.Add(source_copy, target)
    进行过调用
    target
    并且字符串
    source_copy
    等于
    source
    (或相同),则应返回
    target
    。如果没有这样的调用,它应该返回一个空字符串。如果有多个此类调用,则最后一个调用应返回
    target

  4. 从语言 2 到语言 1 的翻译:

    t.TranslateBackward(target)
    。如果之前对某个字符串
    t.Add(source, target_copy)
    进行过调用
    source
    并且字符串
    target_copy
    等于
    target
    (或相同),则应返回
    source
    。如果没有这样的调用,它应该返回一个空字符串。如果有多个此类调用,则最后一个调用应返回
    source

限制:

  • 每个字符串在
    Translator
    类实例中的存储次数不得超过一次。如果违反此限制,您将收到“超出内存限制”错误。

编辑2:仅供记录,这不是大学作业,而是在线课程(如果很重要)。 [1]: 使用 string_view (c++) 进行翻译练习

c++ string c++17
1个回答
0
投票

仔细阅读约束条件。

每个字符串在 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.