Проверьте, является ли строка половинной или полной шириной в С#

Приложение C# в японской ОС Windows - Представление латиницы как полноширинных символов

Я сослался на принятый ответ в приведенной выше ссылке и использую приведенный ниже код для преобразования японской строки из полной ширины в половину ширины, но он возвращает ту же строку полной ширины без преобразования.

string userInput = "チヨチヨチチヨチヨチ";
string result = userInput.Normalize(NormalizationForm.FormKC);

Ожидаемый результат в половину ширины: チヨチヨチチヨチヨチ Фактический вывод: チヨチヨチチヨチヨチ (полная ширина)

Однако, несмотря на то, что приведенный выше код должен преобразовывать строку полной ширины в строку половинной ширины, когда я передаю строку половинной ширины (チヨチヨチチヨチヨチ) приведенному выше коду, он преобразует ее в форму полной ширины (チヨチヨチチヨチヨチ) .

Что я здесь делаю неправильно?

В любом случае я не хочу, чтобы приведенный выше код выполнялся, если моя строка уже имеет половинную ширину.

Как я могу проверить, является ли строка половинной или полной шириной?


person rocketpicks    schedule 22.07.2019    source источник
comment
Вы можете попробовать что-то вроде этого: System.Text.Encoding.GetEncoding(encodingName).GetByteCount(str)   -  person Nilay Vishwakarma    schedule 22.07.2019
comment
Я предполагаю, что вы хотите преобразовать свою строку в обычные символы ASCII. В этом случае порт Unidecode для C# доступен здесь: github.com/thecoderok/Unidecode.NET< /а>   -  person Massimo Di Saggio    schedule 22.07.2019
comment
Можете ли вы объяснить, что означает полная ширина и половинная ширина?   -  person Mostafa Vatanpour    schedule 22.07.2019
comment
@Mostafa This is full width.Это половина ширины.   -  person Llama    schedule 22.07.2019
comment
Полуширина выглядит следующим образом: 1 、2、3、4、5 ...a、b、c (полуширина стоит 1 байт). Если мы изменим полуширину на полную 1 、2、3、4、5 ...a、b、c → 1、2、3、4、5...a、b、c (стоимость полной ширины 2 байта)   -  person VAT    schedule 22.07.2019
comment
Я проверил ваш код, и он не преобразует половину ширины в полную ширину. Я тестировал с использованием .net framework 4.0 и .net core. Можете ли вы поделиться кодом, который показывает проблему?   -  person Mostafa Vatanpour    schedule 22.07.2019
comment
Я снова протестировал ваш обновленный вопрос, но он работает правильно и не преобразует половину ширины в полную ширину. Я думаю, что в вашем коде есть еще одна проблема, например, вы не назначаете результат в новой строке. Строка неизменна и не изменяется. Поделитесь своим тестовым кодом, пожалуйста.   -  person Mostafa Vatanpour    schedule 22.07.2019
comment
@Mostafa это, похоже, воспроизводит результаты OP.   -  person Llama    schedule 22.07.2019
comment
@John, нормализованная форма - チヨチヨチ. Я поделился кодом здесь: rextester.com/ERSR23716 . Вы можете видеть, что это не обратное преобразование.   -  person Mostafa Vatanpour    schedule 22.07.2019
comment
@Mostafa Да, кажется, ты прав.   -  person Llama    schedule 22.07.2019
comment
Кажется, что метод Normalize не всегда преобразует полную ширину в половину ширины. Иногда он преобразует половину ширины в полную ширину. Я думаю, что для этого есть стандарт, который следует изучить. Но лучше работать со стандартами.   -  person Mostafa Vatanpour    schedule 22.07.2019
comment
@Mostafa и Джон, я ценю вашу помощь. Я изменил вопрос, добавив больше деталей, так что это будет полезно для кого-то. Спасибо.   -  person rocketpicks    schedule 22.07.2019
comment
Я изменил свой ответ.   -  person Mostafa Vatanpour    schedule 22.07.2019
comment
Почему вы не принимаете мой ответ?   -  person Mostafa Vatanpour    schedule 01.08.2019
comment
@MostafaVatanpour Ваш ответ помог понять, почему мой код не преобразуется в половинную ширину, но он не ответил на главный вопрос, заданный в соответствии с заголовком. Как проверить, является ли строка половинной или полной шириной?   -  person rocketpicks    schedule 15.08.2019
comment
Я изменил свой ответ в соответствии с вашим комментарием.   -  person Mostafa Vatanpour    schedule 15.08.2019


Ответы (1)


Согласно этому документу, метод нормализации работает должным образом. Он должен преобразовывать символы в стандартные символы, чтобы можно было правильно применить двоичное сравнение.

Но если вам нужно пользовательское преобразование, которое всегда преобразует полную ширину в половинную, вы можете создать Словарь для сопоставления символов полной ширины с символами половинной ширины. Эта ссылка может быть полезна при создании этой карты.

Если вы хотите убедиться, что строка имеет половинную ширину, то, если она содержит какой-либо символ полной ширины, она будет отклонена. Создайте строку из всех символов полной ширины (латинских и японских), затем найдите все символы проверяемой строки в строке символов полной ширины.

Для этой цели я написал метод isHalfWidthString, а также добавил метод преобразования полной ширины в половину ширины. Я подумал, что это может быть полезно:

    public class FullWidthCharactersHandler
    {
        static Dictionary<char, char> fullWidth2halfWidthDic;
        static FullWidthCharactersHandler()
        {
            fullWidth2halfWidthDic = new Dictionary<char, char>();
            string fullWidthChars = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンッァィゥェォャュョ゙゚ー0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
            string halfWidthChars = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンッァィゥェォャュョ゙゚ー0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
            for (int i = 0; i < fullWidthChars.Length; i++)
            {
                fullWidth2halfWidthDic.Add(fullWidthChars[i], halfWidthChars[i]);
            }
        }

        public static bool isHalfWidthString(string toTestString)
        {
            bool isHalfWidth = true;
            foreach (char ch in toTestString)
            {
                if (fullWidth2halfWidthDic.ContainsKey(ch))
                {
                    isHalfWidth = false;
                    break;
                }
            }
            return isHalfWidth;
        }

        public static string convertFullWidthToHalfWidth(string theString)
        {
            StringBuilder sbResult = new StringBuilder(theString);
            for (int i = 0; i < theString.Length; i++)
            {
                if (fullWidth2halfWidthDic.ContainsKey(theString[i]))
                {
                    sbResult[i] = fullWidth2halfWidthDic[theString[i]];
                }
            }
            return sbResult.ToString();
        }
    }

Для проверки используйте эту ссылку.

Я обновил код, чтобы использовать Dictionary для повышения производительности.

person Mostafa Vatanpour    schedule 22.07.2019
comment
Я пытаюсь использовать японский иероглиф. Я обновил вопрос, используя образец ввода. - person rocketpicks; 22.07.2019
comment
строка - плохая идея для этой цели. Вместо этого используйте std::set или std::unordered_set - person phuclv; 15.08.2019
comment
@MostafaVatanpour в C# у вас все еще есть HashSet, SortedSet и многие другие - person phuclv; 15.08.2019
comment
@phuclv да, вы правы, использование хеш-таблицы - лучшая идея и более производительная, но для этого требуется больше строк кода. Я изменил код. Спасибо. - person Mostafa Vatanpour; 15.08.2019
comment
@everyone Одобрил этот ответ, так как это единственное решение (с использованием словаря), которое работало для преобразования Каны половинной ширины в Кану полной ширины или наоборот. Я реализовал с помощью Dictionary‹string, string›, потому что форма половинной ширины некоторых символов Кана полной ширины содержит Dakuten (゙) и Handakuten (゚) — это 2 символа. например Полная ширина ヷ Половина ширины ヷ - person rocketpicks; 13.02.2020