如何在C ++ std :: string中删除重音符号和波浪号
我在C ++中有一个字符串有问题,该字符串在西班牙语中有几个单词。这意味着我有很多带有重音和波浪号的单词。我想用他们的口音不佳的人代替他们。示例:我想用单词" haba"代替habia。我尝试直接替换它,但是使用字符串类的replace方法,但是无法正常工作。
我正在使用此代码:
for (it= dictionary.begin(); it != dictionary.end(); it++) { strMine=(it->first); found=toReplace.find_first_of(strMine); while (found!=std::string::npos) { strAux=(it->second); toReplace.erase(found,strMine.length()); toReplace.insert(found,strAux); found=toReplace.find_first_of(strMine,found+1); } }
其中"字典"是这样的地图(包含更多条目):
dictionary.insert ( std::pair<std::string,std::string>("á","a") ); dictionary.insert ( std::pair<std::string,std::string>("é","e") ); dictionary.insert ( std::pair<std::string,std::string>("í","i") ); dictionary.insert ( std::pair<std::string,std::string>("ó","o") ); dictionary.insert ( std::pair<std::string,std::string>("ú","u") ); dictionary.insert ( std::pair<std::string,std::string>("?","n") );
和toReplace
字符串是:
std::string toReplace="á-é-í-ó-ú-?-á-é-í-ó-ú-?";
我显然一定想念一些东西。我不知道。
我可以使用任何图书馆吗?
谢谢,
解决方案
如果可以的话(如果我们正在运行Unix),我建议为此使用tr
工具:它是为此目的定制的。请记住,没有代码==没有错误代码。 :-)
编辑:对不起,我们是对的,tr
似乎不起作用。 sed呢?这是我写的一个非常愚蠢的脚本,但是对我有用。
#!/bin/sed -f s/á/a/g; s/é/e/g; s/í/i/g; s/ó/o/g; s/ú/u/g; s/?/n/g;
我们可能想查看boost(http://www.boost.org/)库。
它具有一个regexp库,我们可以使用它。
此外,它还有一个特定的库,该库具有一些用于字符串操作(链接)的功能,包括替换。
我使用的是unix,我忘了提了,但是我这样运行tr
$ tr aeiou
ue-uo-uu-uu-uu
它不能按预期工作。我认为这与unicode和字符串类有关。
首先,这是一个非常糟糕的主意:我们通过删除字母来破坏某人的语言。尽管像天真这样的单词中的多余点似乎对只会说英语的人来说是多余的,但实际上在世界上有成千上万种书写系统中,这种区别非常重要。编写软件以残害某人的言语,使我们完全陷入使用计算机作为扩大人类表达与压迫工具领域之间的紧张关系的错误方面。
我们尝试这样做的原因是什么?口音上还有其他令人窒息的东西吗?许多人都希望解决这个问题。
NFD; [:M:] remove; NFC
就是说,libicu可以为我们做到这一点。打开转换演示;复制西班牙文并将其粘贴到"输入"框中;进入
作为化合物1,然后单击变换。
(在ICU中的Unicode转换的幻灯片9的帮助下。幻灯片29-30显示了如何使用API。)
问题是我正在开发应在5天内上大学的应用程序。这是一个程序,它将为HTML页面中的标签内的文本建立索引(我也不能使用apache lucene创建索引)。但是,我不会为所有单词建立索引,必须使用词干删除所有停用词,并将所有文本都转换为小写。根据老师的要求,我们必须消除口音和波浪号。
希望这可以使事情变得更清晰。
礼炮
尝试使用std :: wstring代替std :: string。 UTF-16应该可以工作(相对于ASCII)。
我绝对认为我们应该研究问题的根源。也就是说,寻找一种解决方案,该解决方案将允许我们支持以Unicode编码的字符或者用户的语言环境。
话虽如此,问题是我们正在处理多字符字符串。有std :: wstring
但我不确定我会用那个。一方面,宽字符并不意味着要处理可变宽度的编码。这个孔很深,所以我将其留在那儿。
现在,对于其余的代码,它很容易出错,因为我们将循环逻辑与转换逻辑混合在一起。因此,至少会发生两种错误:翻译错误和循环错误。一定要使用STL,它可以在循环部分为我们提供很多帮助。
以下是替换字符串中字符的粗略解决方案。
#include <iostream> #include <string> #include <iterator> #include <algorithm> #include "translate_characters.h" using namespace std; int main() { string text; cin.unsetf(ios::skipws); transform(istream_iterator<char>(cin), istream_iterator<char>(), inserter(text, text.end()), translate_characters()); cout << text << endl; return 0; }
main.cpp:
#ifndef TRANSLATE_CHARACTERS_H #define TRANSLATE_CHARACTERS_H #include <functional> #include <map> class translate_characters : public std::unary_function<const char,char> { public: translate_characters(); char operator()(const char c); private: std::map<char, char> characters_map; }; #endif // TRANSLATE_CHARACTERS_H
translate_characters.h:
#include "translate_characters.h" using namespace std; translate_characters::translate_characters() { characters_map.insert(make_pair('e', 'a')); } char translate_characters::operator()(const char c) { map<char, char>::const_iterator translation_pos(characters_map.find(c)); if( translation_pos == characters_map.end() ) return c; return translation_pos->second; }
translate_characters.cpp:
我无法链接ICU库,但我仍然认为这是最好的解决方案。因为我需要这个程序尽快运行,所以我做了一个小程序(我必须改进),我将使用它。谢谢大家的建议和解答。
for (it= dictionary.begin(); it != dictionary.end(); it++) { strMine=(it->first); found=toReplace.find(strMine); while (found != std::string::npos) { strAux=(it->second); toReplace.erase(found,2); toReplace.insert(found,strAux); found=toReplace.find(strMine,found+1); } }
这是我要使用的代码:
下次我必须上交程序进行更正时(大约6周内),我将对其进行更改。
我不同意当前的"批准"答案。在为文本建立索引时,这个问题很有意义。与不区分大小写的搜索一样,不区分重音的搜索也是一个好主意。 " na?ve"匹配" Na?ve"匹配" naive"匹配" NA?VE"(我们知道土耳其语中的i是大写吗?这就是为什么我们忽略重音符号的原因)
现在,最好的算法将提示为已批准的答案:使用NKD(分解)将重音字母分解为基本字母和单独的重音,然后删除所有重音。
段落数量不匹配