如何删除的口音和波浪在C++std::string
-
02-07-2019 - |
题
我有一个问题与一串C++其中有几个单词在西班牙语。这意味着,我有很多话的口音和波浪线.我想取代他们为他们不饰的同行。例如:我想代替这个词:"había"对于英国国家美发及美容业管理局.我试图取代它直接,但有替代方法的串类但我不能,要工作。
我使用这个代码:
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
是像这样的地图(用更多的条目):
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="á-é-í-ó-ú-ñ-á-é-í-ó-ú-ñ";
显然我必须丢失的东西。我想不出来。是否有任何图书馆我可以使用吗?.
谢谢,
解决方案
首先,这是一个很坏的想法:你在重整有人的语言通过删除的字母。尽管额外的点的话,如"天真"似乎是多余的人仅说英语,字面上有成千上万的书写系统的世界中,这种区分是非常重要的。写作软件以伤害个人的语音让你完全错误的一边之间的紧张使用计算机作为可以扩大的领域的人表达对工具的压迫。
是什么原因,你就想这样做吗?是什么进一步的路线窒息的口音?许多人想要帮你解决。
这就是说,libicu可以为你做这个。打开的 转换演示;复制和粘贴到你的西班牙文本进入"输入"箱;输入
NFD; [:M:] remove; NFC
作为"1的化合物",并点击变换。
(的帮助下滑9 Unicode将在伊斯兰法院联盟.幻灯片29日至30日展示如何使用的。)
其他提示
我不同意目前“已批准”的情况。回答。在索引文本时,这个问题非常有意义。与不区分大小写的搜索一样,重音不敏感搜索是个好主意。 &QUOT; NA&#239;&已经QUOT;匹配“Na&#239; ve”匹配“天真”匹配“NA&#304; VE” (你做知道大写字母i是&#304;土耳其语?这就是你忽略重音的原因)
现在,最好的算法暗示了批准的答案:使用NKD(分解)将重音字母分解为基本字母和单独的重音,然后删除所有重音。
但是,之后的重组很少有点意义。您删除了大多数会改变的序列,而其他序列无论如何都是相同的。是什么&#230;在NKC和&#230;在NKD?我绝对认为你应该研究问题的根源。也就是说,寻找一种解决方案,允许您支持以Unicode或用户的语言环境编码的字符。
话虽这么说,你的问题是你正在处理多字符串。有 std :: wstring
,但我不确定我是否会使用它。首先,宽字符并不意味着处理可变宽度编码。这个洞深入,所以我会留下它。
现在,对于其余的代码,它很容易出错,因为您将循环逻辑与转换逻辑混合在一起。因此,至少会出现两种错误:转换错误和循环错误。使用STL,它可以为循环部分提供很多帮助。
以下是替换字符串中字符的粗略解决方案。
<强>的main.cpp 强>:
#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;
}
<强> translate_characters.h 强>:
#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.cpp 强>:
#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;
}
您可能需要查看提升功能( http://www.boost.org/ )库。
它有一个正则表达式库,您可以使用它。 此外,它还有一个特定的库,它具有一些字符串操作功能(链接)包括替换。
尝试使用std :: wstring而不是std :: string。 UTF-16应该工作(而不是ASCII)。
如果可以(如果你正在运行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;
我无法链接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周),我会更改它。
/// <summary>
///
/// Replace any accent and foreign character by their ASCII equivalent.
/// In other words, convert a string to an ASCII-complient string.
///
/// This also get rid of special hidden character, like EOF, NUL, TAB and other '\0', except \n\r
///
/// Tests with accents and foreign characters:
/// Before: "äæǽaeöœoeüueÄAeÜUeÖOeÀÁÂÃÄÅǺĀĂĄǍΑΆẢẠẦẪẨẬẰẮẴẲẶАAàáâãåǻāăąǎªαάảạầấẫẩậằắẵẳặаaБBбbÇĆĈĊČCçćĉċčcДDдdÐĎĐΔDjðďđδdjÈÉÊËĒĔĖĘĚΕΈẼẺẸỀẾỄỂỆЕЭEèéêëēĕėęěέεẽẻẹềếễểệеэeФFфfĜĞĠĢΓГҐGĝğġģγгґgĤĦHĥħhÌÍÎÏĨĪĬǏĮİΗΉΊΙΪỈỊИЫIìíîïĩīĭǐįıηήίιϊỉịиыїiĴJĵjĶΚКKķκкkĹĻĽĿŁΛЛLĺļľŀłλлlМMмmÑŃŅŇΝНNñńņňʼnνнnÒÓÔÕŌŎǑŐƠØǾΟΌΩΏỎỌỒỐỖỔỘỜỚỠỞỢОOòóôõōŏǒőơøǿºοόωώỏọồốỗổộờớỡởợоoПPпpŔŖŘΡРRŕŗřρрrŚŜŞȘŠΣСSśŝşșšſσςсsȚŢŤŦτТTțţťŧтtÙÚÛŨŪŬŮŰŲƯǓǕǗǙǛŨỦỤỪỨỮỬỰУUùúûũūŭůűųưǔǖǘǚǜυύϋủụừứữửựуuÝŸŶΥΎΫỲỸỶỴЙYýÿŷỳỹỷỵйyВVвvŴWŵwŹŻŽΖЗZźżžζзzÆǼAEßssIJIJijijŒOEƒf'ξksπpβvμmψpsЁYoёyoЄYeєyeЇYiЖZhжzhХKhхkhЦTsцtsЧChчchШShшshЩShchщshchЪъЬьЮYuюyuЯYaяya"
/// After: "aaeooeuueAAeUUeOOeAAAAAAAAAAAAAAAAAAAAAAAaaaaaaaaaaaaaaaaaaaaaaaBbCCCCCCccccccDdDDjddjEEEEEEEEEEEEEEEEEEeeeeeeeeeeeeeeeeeeFfGGGGGgggggHHhhIIIIIIIIIIIIIiiiiiiiiiiiiJJjjKKkkLLLLllllMmNNNNNnnnnnOOOOOOOOOOOOOOOOOOOOOOooooooooooooooooooooooPpRRRRrrrrSSSSSSssssssTTTTttttUUUUUUUUUUUUUUUUUUUUUUUUuuuuuuuuuuuuuuuuuuuuuuuYYYYYYYYyyyyyyyyVvWWwwZZZZzzzzAEssIJijOEf'kspvmpsYoyoYeyeYiZhzhKhkhTstsChchShshShchshchYuyuYaya"
///
/// Tests with invalid 'special hidden characters':
/// Before: "\0\0\000\0000Bj��rk�\'\"\\\0\a\b\f\n\r\t\v\u0020���oacu\'\\\'te�"
/// After: "00000Bjrk'\"\\\n\r oacu'\\'te"
///
/// </summary>
private string Normalize(string StringToClean)
{
string normalizedString = StringToClean.Normalize(NormalizationForm.FormD);
StringBuilder Buffer = new StringBuilder(StringToClean.Length);
for (int i = 0; i < normalizedString.Length; i++)
{
if (CharUnicodeInfo.GetUnicodeCategory(normalizedString[i]) != UnicodeCategory.NonSpacingMark)
{
Buffer.Append(normalizedString[i]);
}
}
string PreAsciiCompliant = Buffer.ToString().Normalize(NormalizationForm.FormC);
StringBuilder AsciiComplient = new StringBuilder(PreAsciiCompliant.Length);
foreach (char character in PreAsciiCompliant)
{
//Reject all special characters except \n\r (Carriage-Return and Line-Feed).
//Get rid of special hidden character, like EOF, NUL, TAB and other '\0'
if (((int)character >= 32 && (int)character < 127) || ((int)character == 10 || (int)character == 13))
{
AsciiComplient.Append(character);
}
}
return AsciiComplient.ToString().Trim(); // Remove spaces at start and end of string if any
}