Frage

Ich habe ein Problem mit einem String in C ++, die mehrere Wörter in Spanisch hat. Das bedeutet, dass ich eine Menge von Wörtern mit Akzenten und Tilden haben. Ich möchte, dass sie für ihre nicht akzentuierten Pendants ersetzen. Beispiel: Ich möchte dieses Wort ersetzen: „había“ für habia. Ich versuchte es direkt zu ersetzen, sondern mit der Methode der String-Klasse ersetzen, aber ich konnte sie nicht bekommen zu arbeiten.

Ich verwende diesen Code:

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);
    }
}

Wo dictionary ist eine Karte wie folgt aus (mit mehr Einträge):

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") );

und toReplace Strings ist:

std::string toReplace="á-é-í-ó-ú-ñ-á-é-í-ó-ú-ñ";

Ich muss offensichtlich fehlt etwas. Ich kann es nicht herausgefunden. Gibt es eine Bibliothek, die ich verwenden kann?.

Danke,

War es hilfreich?

Lösung

Erstens ist dies eine wirklich schlechte Idee: Sie jemandes Sprache sind Mangeln von Buchstaben zu entfernen. Obwohl die zusätzlichen Punkte in Worten wie „naiv“, um Menschen überflüssig erscheinen, die nur Englisch sprechen, gibt es buchstäblich in der Welt Tausende von Schriftsystemen, in denen solche Unterschiede sehr wichtig sind. Das Schreiben von Software verstümmeln jemandes Rede, die Sie direkt auf der falschen Seite der Spannung zwischen der Verwendung von Computern stellt als Mittel in den Bereich des menschlichen Ausdrucks vs. Werkzeuge der Unterdrückung zu erweitern.

Was ist der Grund, Sie versuchen, dies zu tun? Ist etwas weiter unten auf der Linie auf den Akzenten ersticken? Viele Menschen würden gerne Ihnen helfen, dass zu lösen.

Das heißt, libicu kann dies für Sie tun. Öffnen Sie die Demo zu verwandeln; Kopieren Sie Ihren spanischen Text in die „Input“ Feld einfügen; Geben Sie

NFD; [:M:] remove; NFC

als „Verbindung 1“ und klicken Sie transformieren.

(Mit Hilfe von Folie 9 von Unicode-Transformationen in ICU . Slides 29-30 zeigen, wie die API zu verwenden.)

Andere Tipps

Ich bin nicht einverstanden mit der momentan „genehmigt“ Antwort. Die Frage ist durchaus sinnvoll, wenn Sie Text indizieren. Wie Groß- und Kleinschreibung Sucht, Akzent unempfindliche Suche ist eine gute Idee. „Naiv“ passt „Naïve“ passt „naive“ passt „naiver“ (Sie tun wissen, dass ein Groß i ist, ich auf Türkisch? Deshalb sollten Sie Akzente ignorieren)

Nun wird der beste Algorithmus auf zugelassene Antwort angedeutet: Die Verwendung NKD (Zersetzung) Buchstaben mit Akzenten in die Basisbuchstabe zu zersetzen und einem separaten Akzente, und dann alle Akzente entfernen.

Es gibt wenig Punkt in der Neuzusammensetzung danach, though. Sie entfernt die meisten Sequenzen, die ändern würde, und die anderen sind für alle Absichten und Zwecke ohnehin identisch. Was ist der Unterschied zwischen æ in NKC und æ in NKD?

Ich glaube, Sie auf jeden Fall in die Wurzel des Problems aussehen sollen. Das heißt, für eine Lösung, die Sie erlauben Zeichen in Unicode oder für die Benutzer-Gebietsschema codiert zu unterstützen.

aber sagen, dass Ihr Problem ist, dass Sie mit Multi-Zeichenketten zu tun hat. Es gibt std::wstring aber ich bin nicht sicher, ob ich das verwenden würde. Für eine Sache, sind breite Zeichen nicht dazu gedacht, mit variabler Breite Kodierungen zu handhaben. Dieses Loch geht tief, also werde ich es belassen.

Nun, wie für den Rest des Codes ist es fehleranfällig, weil Sie die Looping-Logik mit Übersetzungslogik mischen. Somit kann zumindest zwei Arten von Fehlern auftreten: Übersetzung Bugs und Looping Bugs. Setzen Sie die STL verwenden, es kann Ihnen helfen, eine Menge mit dem Looping Teil.

Das folgende ist eine grobe Lösung für Zeichen in einer Zeichenfolge zu ersetzen.

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;
}

Sie können die Boost prüfen wollen ( http://www.boost.org/ ) Bibliothek.

Es hat eine regexp-Bibliothek, die Sie nutzen könnten. Darüber hinaus hat es eine bestimmte Bibliothek, die einige Funktionen zur String-Manipulation hat ( Link ) einschließlich ersetzen.

Versuchen Sie std :: wstring statt std :: string. UTF-16 funktionieren soll (im Gegensatz zu ASCII Gegensatz).

Wenn Sie (wenn Sie Unix laufen lassen), schlage ich vor, mit der tr Einrichtung dafür: es ist maßgeschneidert für diesen Zweck. Denken Sie daran, kein Code == kein fehlerhafter Code. : -)

Edit: Sorry, du hast recht, tr scheint nicht zu funktionieren. Wie wäre es sed? Es ist eine ziemlich dumme Skript, das ich geschrieben habe, aber es funktioniert für mich.

#!/bin/sed -f
s/á/a/g;
s/é/e/g;
s/í/i/g;
s/ó/o/g;
s/ú/u/g;
s/ñ/n/g;

Ich kann nicht die ICU-Bibliotheken verknüpfen, aber ich denke immer noch, es ist die beste Lösung. Als ich brauche dieses Programm funktionsfähig zu sein, so bald wie möglich ich ein kleines Programm gemacht (die ich zu verbessern habe) und ich werde das verwenden. Vielen Dank für für Anregungen und Antworten.

Hier ist der Code, ich werde verwenden:

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);
    }
} 

Ich werde es mir beim nächsten Mal ändere mein Programm in zur Korrektur (in ca. 6 Wochen) drehen.

    /// <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
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top