Pergunta

Eu tenho um problema com uma corda em C ++ que tem várias palavras em espanhol. Isso significa que eu tenho um monte de palavras com acentos e tiles. Eu quero substituí-los por suas contrapartes não acentuados. Exemplo: Eu quero substituir esta palavra: "había" para habia. Eu tentei substituí-lo diretamente, mas com a substituir método da classe string, mas não consegui chegar a esse trabalho.

Eu estou usando este código:

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

Onde dictionary é um mapa como este (com mais entradas):

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

e toReplace é:

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

Eu, obviamente, deve estar faltando alguma coisa. Eu não posso descobrir isso. Existe alguma biblioteca eu posso usar?.

Obrigado,

Foi útil?

Solução

Em primeiro lugar, esta é uma péssima idéia: você está mutilando linguagem de alguém através da remoção de cartas. Embora os pontos extras em palavras como “ingênua” parecer supérfluo para as pessoas que só falam Inglês, existem literalmente milhares de sistemas no mundo em que tais distinções são muito importantes escrevendo. Escrever software para puts fala de alguém mutilar-lhe em cheio no lado errado da tensão entre o uso de computadores como forma de ampliar o domínio de ferramentas de expressão versus humanos da opressão.

O que é a razão que você está tentando fazer isso? É algo mais abaixo da linha engasgando com os acentos? Muitas pessoas gostariam de ajudá-lo a resolver isso.

Dito isso, libicu pode fazer isso por você. Abra a transformar demonstração ; copiar e colar o texto espanhol na caixa “Entrada”; digite

NFD; [:M:] remove; NFC

como “composto 1” e clique em transformar.

(Com a ajuda de slides 9 de Unicode transformações na UTI . Diapositivos 29-30 mostram como para usar a API.)

Outras dicas

Não concordo com a resposta atualmente "aprovado". A pergunta faz todo o sentido quando você está indexação de texto. Como a busca case-insensitive, pesquisa acento-insensitive é uma boa idéia. Jogos Jogos "ingênuo" "ingênuo" partidas "ingênuo" "ingênuo" (você do saber que uma maiúscula i é que eu em turco? É por isso que você ignorar acentos)

Agora, o melhor algoritmo é insinuado a resposta aprovada: Use NKD (decomposição) para decompor letras acentuadas na letra de base e um sotaque independente, e depois remover todos os acentos.

Há pouco ponto na recomposição depois, no entanto. Você removeu a maioria das sequências que iria mudar, e os outros são para todos os efeitos de qualquer maneira idêntica. Qual é a diferença entre Ae em NKC e AE em NKD?

Eu definitivamente acho que você deve olhar para a raiz do problema. Ou seja, olhar para uma solução que lhe permitirá suportar caracteres codificados em Unicode ou para a localidade do usuário.

Dito isto, o problema é que você está lidando com cordas de vários caracteres. Há std::wstring mas não estou certo de que eu usaria isso. Por um lado, caracteres largos não são destinadas a lidar com largura variável codificações. Este buraco vai fundo, então eu vou deixar por isso mesmo.

Agora, como para o resto do seu código, é propenso a erros, porque você mistura a lógica looping com a lógica de tradução. Assim, pelo menos dois tipos de erros pode ocorrer: erros de tradução e erros de looping. Não usar a STL, ele pode ajudá-lo muito com a parte de looping.

A seguir é uma solução aproximada para substituição de caracteres em uma string.

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

Você pode querer verificar o impulso ( http://www.boost.org/ ) biblioteca.

Ele tem uma biblioteca de expressão regular, que você poderia usar. Além disso, tem uma biblioteca específica que tem algumas funções para a manipulação de cadeia ( link ), incluindo substituir.

Tente usar std :: wstring em vez de std :: string. UTF-16 deve funcionar (ao contrário de ASCII).

Se você pode (se você estiver executando Unix), eu sugiro usar o tr facilidade para isso: de custom-built para esta finalidade. Lembre-se, nenhum código == nenhum código de buggy. : -)

Edit: Desculpe, você está certo, tr não parece trabalho. Como cerca de sed? É um roteiro muito estúpido que eu escrevi, mas funciona para mim.

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

Eu não podia ligar as bibliotecas de UTI, mas eu ainda acho que é a melhor solução. Como eu precisa deste programa para ser funcional assim que possível eu fiz um pequeno programa (que eu tenho que melhorar) e eu vou usar isso. Obrigado a todos por sugestões e respostas.

Aqui está o código que eu vou usar:

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

Eu vou mudar isso da próxima vez eu tenho que virar meu programa na para correção (em cerca de 6 semanas).

    /// <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
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top