Eu tenho a seguinte tarefa
Desenvolva uma classe chamada Tradutor que permite salvar pares de palavras bilíngues e depois traduzir palavras de um idioma para outro usando os pares já adicionados:
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:
//
};
Mais especificamente, um objeto t
do tipo Translator
deve suportar as seguintes ações:
Criação usando o construtor padrão. Neste caso, a base de tradução está vazia.
Adicionando um par bilíngue:
t.Add(source, target)
. Após esta chamada, assume-se que a palavrasource
na linguagem 1 corresponde à palavratarget
na linguagem 2. As strings passadas para oAdd
método podem ser destruídas antes dot
objeto.Tradução da língua 1 para a língua 2:
t.TranslateForward(source)
. Se houve uma chamada anteriort.Add(source_copy, target)
para alguma stringtarget
e uma stringsource_copy
igualsource
(ou sendo igual), ela deverá retornartarget
. Se não houvesse tal chamada, ela deveria retornar uma string vazia. Se houvesse várias dessas chamadas, ele deveria retornartarget
para a última.Tradução da língua 2 para a língua 1:
t.TranslateBackward(target)
. Se houve uma chamada anteriort.Add(source, target_copy)
para alguma stringsource
e uma stringtarget_copy
igualtarget
(ou sendo igual), ela deverá retornarsource
. Se não houvesse tal chamada, ela deveria retornar uma string vazia. Se houvesse várias dessas chamadas, ele deveria retornarsource
para a última.
Restrições:
- Cada string deve ser armazenada na
Translator
instância da classe no máximo uma vez. Se esta restrição for violada, você receberá um erro "Limite de memória excedido".
Basicamente, tentei a seguinte ideia simples:
#include <string_view>
#include <string>
#include <map>
using namespace std;
class Translator {
public:
void Add(string_view source, string_view target){
forward[source] = target;
backward[target] = source;
};
string_view TranslateForward(string_view source) const{
if(forward.count(source) == 0){
return string_view("");
}
return forward.at(source);
};
string_view TranslateBackward(string_view target) const{
if(backward.count(target) == 0){
return string_view("");
}
return backward.at(target);
};
private:
map<string_view,string_view> forward;
map<string_view,string_view> backward;
};
Eu testei com casos simples:
int main(){
Translator translator;
translator.Add(string("okno"), string("window"));
translator.Add(string("stol"), string("table"));
}
E funciona bem. Mas no teste oculto eu consegui TranslateForward() returned wrong data for temporary string (Time used: 1.78/5.00, preprocess time used: 0/None, memory used: 155656192/268435456.)
. Parece que perdi alguns casos extremos.
Do que sinto falta (em geral também)?
A chave do erro é "string temporária". Por que você armazena string_views nos mapas? Onde a string real está armazenada? E se a string do chamador terminar sua vida útil?
std::string_view
é apenas uma visão. Ele não possui os dados. Ele permite visualizar os dados de algum outro objeto. Se esse outro objeto deixar de existir, você não poderá mais visualizá-lo.Mesmo no seu exemplo, a string real são temporárias que deixam de existir após a expressão completa:
Armazene strings no mapa em vez de apenas visualizações.