문제

스페인어로 여러 단어가있는 C ++의 문자열에 문제가 있습니다. 이것은 악센트와 틸트가있는 단어가 많다는 것을 의미합니다. 나는 그들을 악센트가없는 대응 물로 교체하고 싶습니다. 예 : 나는이 단어를 대체하고 싶습니다 : 하비아를위한 "Había". 직접 교체하려고 시도했지만 String 클래스의 교체 방법으로 교체했지만 작동하지 못했습니다.

이 코드를 사용하고 있습니다.

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의 도움으로 유니 코드는 ICU로 변환됩니다. 슬라이드 29-30 API 사용 방법을 보여줍니다.)

다른 팁

나는 현재 "승인 된"답변에 동의하지 않습니다. 텍스트를 색인화 할 때이 질문은 완벽하게 의미가 있습니다. 사례에 민감하지 않은 검색과 마찬가지로 악센트에 민감한 검색이 좋은 생각입니다. "Naïve"일치 "Naïve"는 "Naive"와 일치합니다. 하다 대문자 I가 터키어로 이주한다는 것을 알고 있습니까? 그것이 당신이 악센트를 무시하는 이유입니다)

이제 최상의 알고리즘은 승인 된 답변에 암시됩니다. NKD (분해)를 사용하여 악센트 된 문자를 기본 문자와 분리 된 악센트로 분해 한 다음 모든 악센트를 제거하십시오.

그러나 그 후 재구성에는 거의 요점이 없습니다. 당신은 변화 할 대부분의 시퀀스를 제거했으며, 다른 시퀀스는 어쨌든 모든 의도와 목적을위한 것입니다. NKC에서 Æ와 NKD의 Æ의 차이점은 무엇입니까?

나는 당신이 문제의 근본을 조사해야한다고 생각합니다. 즉, 유니 코드 또는 사용자의 로케일에 인코딩 된 문자를 지원할 수있는 솔루션을 찾으십시오.

즉, 당신의 문제는 당신이 다중 문자열을 다루고 있다는 것입니다. 거기 있습니다 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/) 도서관.

REGEXP 라이브러리가있어 사용할 수 있습니다. 또한 문자열 조작에 대한 일부 기능이있는 특정 라이브러리가 있습니다 (링크) 교체를 포함하여.

std :: string 대신 std :: wstring을 사용해보십시오. 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
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top