Domanda

Ho un problema con una stringa in C ++ che contiene diverse parole in spagnolo. Ciò significa che ho molte parole con accenti e tilde. Voglio sostituirli con le loro controparti non accentate. Esempio: voglio sostituire questa parola: " hab & # 237; a " per l'habia. Ho provato a sostituirlo direttamente ma con il metodo di sostituzione della classe stringa ma non sono riuscito a farlo funzionare.

Sto usando questo codice:

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

Dove dizionario è una mappa come questa (con più voci):

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

e toReplace sono:

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

Ovviamente mi manca qualcosa. Non riesco a capirlo. C'è qualche biblioteca che posso usare ?.

Grazie,

È stato utile?

Soluzione

Innanzitutto, questa è una pessima idea: stai manipolando il linguaggio di qualcuno rimuovendo le lettere. Sebbene i punti extra in parole come & # 8220; na & # 239; ve & # 8221; sembrano superflue per le persone che parlano solo inglese, ci sono letteralmente migliaia di sistemi di scrittura nel mondo in cui tali distinzioni sono molto importanti. Scrivere software per mutilare il discorso di qualcuno ti mette esattamente dalla parte sbagliata della tensione tra l'uso dei computer come mezzo per ampliare il regno dell'espressione umana rispetto agli strumenti dell'oppressione.

Qual è il motivo per cui stai cercando di farlo? C'è qualcosa di più lungo nella linea che soffoca sugli accenti? Molte persone vorrebbero aiutarti a risolverlo.

Detto questo, libicu può farlo per te. Apri la trasforma la demo ; copia e incolla il testo in spagnolo in & # 8220; Input & # 8221; scatola; immettere

NFD; [:M:] remove; NFC

come & # 8220; Composto 1 & # 8221; e fai clic su trasforma.

(Con l'aiuto della diapositiva 9 di Trasformazioni Unicode in ICU . Le diapositive 29-30 mostrano come per utilizzare l'API.)

Altri suggerimenti

Non sono d'accordo con l'attuale "approvato" risposta. La domanda ha perfettamente senso quando si sta indicizzando il testo. Come la ricerca senza distinzione tra maiuscole e minuscole, la ricerca senza distinzione tra accenti è una buona idea. & Quot; naive " corrisponde a "Naïve" corrisponde a "ingenuo" corrisponde a " NAIVE " ( sai che un maiuscolo è in turco? Ecco perché ignori gli accenti)

Ora, l'algoritmo migliore è suggerito dalla risposta approvata: utilizzare NKD (decomposizione) per scomporre le lettere accentate nella lettera base e un accento separato, quindi rimuovere tutti gli accenti.

In seguito, tuttavia, la ricomposizione ha poco senso. Hai rimosso la maggior parte delle sequenze che sarebbero cambiate, e le altre sono comunque identiche a tutti gli effetti. Qual è la differenza tra æ in NKC e æ in NKD?

Penso sicuramente che dovresti esaminare la radice del problema. Ossia, cerca una soluzione che ti permetta di supportare caratteri codificati in Unicode o per le impostazioni locali dell'utente.

Detto questo, il tuo problema è che hai a che fare con stringhe multi-carattere. C'è std :: wstring ma non sono sicuro che lo userei. Per prima cosa, i caratteri ampi non sono pensati per gestire codifiche a larghezza variabile. Questo buco è profondo, quindi lo lascerò a quello.

Ora, come per il resto del codice, è soggetto a errori perché mescoli la logica di loop con la logica di traduzione. Pertanto, possono verificarsi almeno due tipi di bug: bug di traduzione e bug in loop. Usa lo STL, può aiutarti molto con la parte del loop.

Di seguito è riportata una soluzione approssimativa per la sostituzione di caratteri in una stringa.

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

Potresti voler dare un'occhiata al boost ( http://www.boost.org/ ) biblioteca.

Ha una libreria regexp, che puoi usare. Inoltre ha una libreria specifica che ha alcune funzioni per la manipolazione delle stringhe ( link ) incluso rimpiazzare.

Prova a usare std :: wstring invece di std :: string. UTF-16 dovrebbe funzionare (al contrario di ASCII).

Se puoi (se stai utilizzando Unix), ti suggerisco di usare tr per questo: è costruito su misura per questo scopo. Ricorda, nessun codice == nessun codice errato. : -)

Modifica: mi dispiace, hai ragione, tr non sembra funzionare. Che ne dici di sed ? È una sceneggiatura piuttosto stupida che ho scritto, ma funziona per me.

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

Non sono riuscito a collegare le librerie di terapia intensiva, ma penso ancora che sia la soluzione migliore. Poiché ho bisogno che questo programma sia funzionale al più presto, ho fatto un piccolo programma (che devo migliorare) e lo userò. Grazie a tutti per suggerimenti e risposte.

Ecco il codice che userò:

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

Lo cambierò la prossima volta che dovrò consegnare il mio programma per la correzione (tra circa 6 settimane).

    /// <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
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top