Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Определение длины строки std::string на русском 
:(
    Опции темы
Proger10
Дата 31.5.2013, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Проблема возникает вот здесь:
Код

std::string str = "hello";
str.length() // 5

std::string str = "привет";
str.length() // 12

std::string str = "привет1";
str.length() // 13


Не очень понимаю каким образом считать количество букв. Оно мне считает количество байт видимо?

Компилятор: GCC, MacOS, кодировка: Unicode у нас(

Это сообщение отредактировал(а) Proger10 - 31.5.2013, 15:53
PM MAIL   Вверх
Proger10
Дата 31.5.2013, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Использование wchar_t решает проблему:
Код

const wchar_t wtext[] = L"привет1" ;
wcslen( wtext ); // 7


А что обозначает буква "L" перед строкой? smile

Какие беды можно ожидать от такого решения при компиляции под разными операционками?

Это сообщение отредактировал(а) Proger10 - 31.5.2013, 16:27
PM MAIL   Вверх
bsa
Дата 31.5.2013, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Proger10 @  31.5.2013,  17:16 Найти цитируемый пост)
А что обозначает буква "L" перед строкой?

то что строка юникодовая (точнее, в расширенной кодировке).
С русским языком опять могут возникнуть проблемы, при компиляции программ в Windows. Рекомендую отказаться от использования кириллицы в тексте программы, а вместо этого читать из файла русификации (читай про gettext).
PM   Вверх
Proger10
Дата 31.5.2013, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



bsa 
По поводу кириллицы в коде - конечно, у меня такого не будет, это я для теста сейчас пробую. А есть ли возможность работать с кириллицей (во внешних текстовых файлах) без gettext? Насколько я понял, это сторонняя библиотека, хотелось бы как можно меньше зависимостей с собой тащить.

Мой проект: анализатор русскоязычного текста. Кодировка текстовых файлов: UTF-8. Есть ли возможность как-то стандартными средствами С++ поднимать этот текст и работать с ним (сортировать текст по алфавиту, искать вхождения букв, замерять длину текстовых подстрок), независимо от предпочтений операционки?)
PM MAIL   Вверх
Proger10
Дата 31.5.2013, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



В википедии: http://ru.wikipedia.org/wiki/%D0%A8%D0%B8%...%B2%D0%BE%D0%BB
на эту тему написано:

Тип wchar_t предназначен для хранения широких символов в том виде, в котором их понимают конкретные компиляторы, и это может не соответствовать Юникоду».

Получается, что я не могу, через wchar_t организовать работу по получению инфы (кириличной) из текстовых файлов, обработки её, записи обратной для разных операционных систем?
PM MAIL   Вверх
bsa
Дата 31.5.2013, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



если ты не хочешь тянуть сторонние библиотеки (iconv, например), то придется написать перекодировщик utf8 -> wide-string, wide-string -> utf8.
PM   Вверх
Proger10
Дата 31.5.2013, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Спасибо! Наверное это наиболее удобный способ работы с UTF-8 кодировкой. UTF-8 можно хранить и в std::string, но с этим классом работать менее удобно, нежели с wstring. А в конечном итоге, всё равно, и то, и другое, перекодировать в UTF-8 прийдётся.

Добавлено через 11 минут и 32 секунды
Ещё прочёл, что 
Код

setlocale(LC_ALL,"")

может решить проблему и превратить wstring в нормальный UTF-8, а не UTF-16/32. Сработает ли такое для винды или там никакие LC_ALL не сработают?
PM MAIL   Вверх
Proger10
Дата 31.5.2013, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Весь день убил на поиски решений относительно этой темы. Жуть просто. Не пойму, чем С++ такой выдающийся, что в нём не встроили работу с UTF-8 кодировками, в то время как другие ЯП работают влёт? Или неанглоязычники такие неудачники? Или создатели языка и вовсе не знают, что помимо английского языка бывают ещё там какие-то. Но самое интересно и от прогеров С++ тоже никаких решений на эту тему не удалось найти.

Как я понимаю, решения два:
- использовать для хранения UTF-8 класс std::string - и иметь гемор с посимвольным доступом и анализом текста в таком формате
- использовать класс std::wstring и иметь гемор с конвертацией в UTF-8 и обратно. Писать самостоятельно такое очень нехочется - изобретая такой велосипед ошибиться можно, заколебаешься потом использовать такой софт

Не пойму, как все работают с UTF-8 в С++? Неужели используя только внешние дополнительные библиотеки? Но цеплять отдельную внешнюю (Qt, GLib, GetText, Boost) только для посимвольного доступа... как-то крутова-то очень :(

Добавлено через 9 минут и 37 секунд
Почему мне необходимы как можно максимально-стандартизированное решение, так потому, что я не уверен, что внешняя библиотека сможет скомпилиться на тех жутких платформах, на которых я буду собирать проект с этой библиотекой. Пример таких платформ: Windows Phone и другие в таком духе. И встать в лужу из-за строк... сами понимаете... посему и нужно максимально-переносимое решение, которое только возможно.

Это сообщение отредактировал(а) Proger10 - 31.5.2013, 21:50
PM MAIL   Вверх
mes
Дата 31.5.2013, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Proger10 @  31.5.2013,  20:48 Найти цитируемый пост)
Не пойму, как все работают с UTF-8 в С++? 

просто больсчинству не приходится считать кол-во русских букв..


--------------------
PM MAIL WWW   Вверх
Proger10
Дата 31.5.2013, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(mes @ 31.5.2013,  22:11)
Цитата(Proger10 @  31.5.2013,  20:48 Найти цитируемый пост)
Не пойму, как все работают с UTF-8 в С++? 

просто больсчинству не приходится считать кол-во русских букв..

Подсчитать-то как раз не проблема smile

Код

    int len = 0;
    while ( *chr ) {
        
        // Count all first-bytes (the ones that don't match 10xxxxxx)
        len += ( *chr++ & 0xc0 ) != 0x80;
        
    }


Проблема с посимвольным доступом к std::string в которой UTF-8...
PM MAIL   Вверх
Proger10
Дата 1.6.2013, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Хотя, так если подумать, если я буду конвертить в wstring, то для отображений и для дальнейшей работы с другими библиотеками, мне всё равно нужен std::string, а насколько понимаю сконвертить wstring -> string - это ещё один гемор на голову) Чёрт, с какими же мне типами данных работать-то, если мне нужно делать простейший синтаксический анализатор русского текста, хранящийся в UTF-8?

Если получать буду в std::string - вроде хорошо. Но загвоздку пока вижу такую: как мне в другую переменную std::string присвоить третий символ из первой строки?)

Т.е. грубо говоря что-то типа:
Код

std::string str1 = "123, привет, мир!";
std::string str2 = ...... str1.at( 2 ) .... 


но ведь в str1 у меня вообще чёрти что, не фиксированный размер символов. Как их доставать, как понимать сколько занимает очередной символ и что там за символ? По сути, я знаю, что там у меня данные в формате UTF-8. Но чёрт.. чё с ними дальше-то делать  smile 


Это сообщение отредактировал(а) Proger10 - 1.6.2013, 00:41
PM MAIL   Вверх
Proger10
Дата 1.6.2013, 01:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



В общем, решил я попробовать справиться с работой UTF-8 + std::string, надеюсь Вы мне поможете с ответами на мои тупейшие вопросы, покуда в С++ я совсем не шарю smile

Сейчас я читаю спецификацию Unicode и представление UTF-8 в ней. Пытаюсь вывести строку UTF-8 и посмотреть с чем я дело имею:
Код

std::string str = "123абв";
for ( int i = 0; i < str.length(); i++ ) {
    std::cout << i << ": " << str.at( i ) << std::endl;    
}

//вывод:
0: 1
1: 2
2: 3
3: \320
4: \260
5: \320
6: \261
7: \320
8: \262


В принципе, всё верно. Значения байт ниже 128 представляются ими же в ASCII кодах, то бишь это значения: 1, 2, 3, всё верно. Дальше они "видимо" ( smile)) ) старше 127, соответственно представляются последовательностью двух байт каждое. Ок. Но что за формат чисел такой: \320, \260, это какая система счисления вообще? smile))
PM MAIL   Вверх
mes
Дата 1.6.2013, 01:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Proger10 @  1.6.2013,  00:30 Найти цитируемый пост)
 << str.at( i )

int(str.at( i )) покажет код символа


--------------------
PM MAIL WWW   Вверх
Proger10
Дата 1.6.2013, 02:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Спасибо!
Немного ещё продвинулся)
Получаю код символа в unsigned char и сравниваю со значением 128. Вроде пока всё правильно отображает smile

Код

std::string str = "123абв";
std::string status;

for ( int i = 0; i < str.length(); i++ ) {
    
    unsigned char ch = str.at( i );
    if ( ch < 128 ) {
        status = "lower";
    } else {
        status = "higher";    
    }
    
    std::cout << i << ": " << str.at( i ) << " " << int( str.at( i ) ) << " " << int( ch ) << " " << status << std::endl;
    
}

/*
Вывод:
0: 1 49 49 lower
1: 2 50 50 lower
2: 3 51 51 lower
3: \320 -48 208 higher
4: \260 -80 176 higher
5: \320 -48 208 higher
6: \261 -79 177 higher
7: \320 -48 208 higher
8: \262 -78 178 higher
*/


Теперь надо подумать зачем я это получил  smile Далее заглядываем в спецификацию UTF-8....

Цитата

Unicode UTF-8:
0x00000000 — 0x0000007F: 0xxxxxxx
0x00000080 — 0x000007FF: 110xxxxx 10xxxxxx
0x00000800 — 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
0x00010000 — 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

И видим, что если символ попадает от 0 до 127 включительно - то он однобайтовый, если от 128 до 2047 - то он двухбайтовый и т.д. Но вот тут-то сразу и возникает вопрос - а откуда у меня-то окажутся числа больше 255, они же невозможны в unsigned char. Соответственно, использовать другой тип данных вместо unsigned char? А какой? unsigned int? Тогда у меня совершенно дикие числа идут в вывод:

Цитата

вывод при: unsigned int ch = str.at( i );

0: 1 49 49 lower
1: 2 50 50 lower
2: 3 51 51 lower
3: \320 -48 4294967248 higher
4: \260 -80 4294967216 higher
5: \320 -48 4294967248 higher
6: \261 -79 4294967217 higher
7: \320 -48 4294967248 higher
8: \262 -78 4294967218 higher


Как же здесь быть? По-моему что-то я уже напутал и относительно диапазонов UTF-8 там что-то другое имелось ввиду..) По чему же мы определяем вхождения в те диапазоны UTF-8, по очередному символу или по чему-то другому?

Это сообщение отредактировал(а) Proger10 - 1.6.2013, 02:37
PM MAIL   Вверх
mes
Дата 1.6.2013, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Proger10 @  1.6.2013,  01:29 Найти цитируемый пост)
Как же здесь быть? По-моему что-то я уже напутал и относительно диапазонов UTF-8 там что-то другое имелось ввиду..) По чему же мы определяем вхождения в те диапазоны UTF-8, по очередному символу или по чему-то другому?

под напильник (для длины из 3х символов)
Код

#include <iostream>

int main()
{
  std::string s = "hallo привет";
  
  for (size_t i=0; i<s.size(); )
  {
    size_t ln=0;

    if ((unsigned char)(s[i])>0x7F) ++ln;
    else
    if ((unsigned char)(s[i+1])>0x07) ++ln;
    else  ++ln;

    std::cout << s.substr(i, ln) << std::endl; 

    i+=ln;
 }
}


Добавлено @ 12:17
Цитата

h
a
l
l
o
 
п
р
и
в
е
т


Это сообщение отредактировал(а) mes - 1.6.2013, 14:30


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0564 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.