سؤال

لدي مشكلة مع سلسلة في C++ تحتوي على عدة كلمات باللغة الإسبانية.هذا يعني أن لدي الكثير من الكلمات ذات العلامات والعلامات.أريد استبدالهم بنظرائهم الذين لم ينطقوا بلكنة.مثال:أريد استبدال هذه الكلمة:"هابيا" لهابيا.لقد حاولت استبداله مباشرة ولكن باستخدام طريقة استبدال فئة السلسلة ولكن لم أتمكن من تشغيل ذلك.

أنا أستخدم هذا الرمز:

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 كيفية استخدام واجهة برمجة التطبيقات.)

نصائح أخرى

أنا لا أتفق مع الإجابة "المعتمدة" حاليًا.السؤال منطقي تمامًا عند فهرسة النص.مثل البحث غير الحساس لحالة الأحرف، يعد البحث غير الحساس لللكنة فكرة جيدة."ساذج" يتطابق مع "ساذج" يتطابق مع "ساذج" يتطابق مع "ساذج" (أنت يفعل هل تعلم أن الحرف الكبير i هو İ باللغة التركية؟لهذا السبب تتجاهل اللهجات)

الآن، يتم التلميح إلى أفضل خوارزمية في الإجابة المعتمدة:استخدم NKD (التحليل) لتحليل الحروف المحركة إلى الحرف الأساسي وتشكيل منفصل، ثم قم بإزالة جميع العلامات.

ومع ذلك، ليس هناك فائدة تذكر في إعادة التكوين بعد ذلك.لقد قمت بإزالة معظم التسلسلات التي من شأنها أن تتغير، والتسلسلات الأخرى متطابقة لجميع المقاصد والأغراض على أي حال.ما الفرق بين æ في NKC و æ في 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/) مكتبة.

يحتوي على مكتبة regexp، والتي يمكنك استخدامها.بالإضافة إلى أنه يحتوي على مكتبة محددة تحتوي على بعض الوظائف لمعالجة السلسلة (وصلة) بما في ذلك استبدال.

حاول استخدام 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
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top