Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
1 / 1 / 3
Регистрация: 03.04.2016
Сообщений: 51

Обработка utf-8

07.01.2018, 20:07. Показов 4127. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Для разминки черепа решил освоить работу с unicode в С
Для общего развития написал функцию split().
Но при проверке работоспособности столкнулся с проблемами.
В некоторых случаях программа завершается с ошибкой.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
#include <string.h>
 
int split(const wchar_t *string, wchar_t delemiter, wchar_t **result);
 
int main(void)
{
    setlocale(LC_CTYPE, "");
    wchar_t *hello = L"надо передавать АДРЕС данного";
    wchar_t delemiter = L' ';
    wchar_t **result;
    int count = 0;
    wprintf(L"%ls\n", hello);
    result = (wchar_t**)malloc(sizeof(wchar_t));
    count = split(hello, delemiter, result);
    wprintf(L"Деление строки по: '%lc'\n", delemiter);
    wprintf(L"Количество - %ld\n", count);
    for (int i = 0; i < count; i++) {
        wprintf(L"%ls\n", result[i]);
    }
    return 0;
}
 
int split(const wchar_t *string, wchar_t delemiter, wchar_t **result) {
    int count = 0;
    int position = 0;
    int old_position = 0;
    size_t lenght;
    wchar_t *ch;
    int i = 0;
    int j = 0;
    ch = wcschr(string+old_position, delemiter);
    if (ch != NULL) {
        do {
            position = ch-string;
            lenght = position - old_position;
            result[i] = (wchar_t*)malloc(lenght * sizeof(wchar_t)+1);
            wmemcpy(result[i], string+old_position, lenght);
            old_position = position + 1;
            count++;
            i++;
        } while((ch = wcschr(string+old_position, delemiter)) != NULL);
        position = wcslen(string)+1;
        lenght = position-1 - old_position;
        result[i] = (wchar_t*)malloc(lenght * sizeof(wchar_t)+1);
        result[i] = string+old_position;
        count++;
        i++;
    }
    else {
        result[0] = (char*)malloc(wcslen(string) * sizeof(char)+1);
        memcpy(result[0], string, wcslen(string));
    }
    return count;
}
Миниатюры
Обработка utf-8   Обработка utf-8   Обработка utf-8  

Обработка utf-8   Обработка utf-8  
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
07.01.2018, 20:07
Ответы с готовыми решениями:

getBytes('UTF-16') даёт UTF-16LE или UTF-16BE?
Добрый день! Делаю J2ME-клиента к некому серверу, исходников которого у меня нет, но есть работающий клиент на C#. Выяснилось, что C#...

<globalization fileEncoding='utf-8' requestEncoding='utf-8' responseEncoding='utf-8' />
Если в коде пишу строку скажем Response.Write ('Вася дурак') - все срабатывает нормально, а если в &lt;body&gt;&lt;h1&gt;Вася...

Конвертация из ASCII в UTF-32 или UTF-8 в UTF-32
Собсно сабж.

31
23 / 5 / 1
Регистрация: 05.01.2017
Сообщений: 58
07.01.2018, 23:04
Код. отвратителен.

Говорю это, не для того чтоб обидеть. Просто никогда так не пиши! Главное в коде, чтоб ты сам его понимал. Но! тут непонятно с первого взгляда что происходит.

1) Яб отказался от указателей на указатели. Это усложняет код.
2)
result[i] = (wchar_t*)malloc(lenght * sizeof(wchar_t)+1);
result[i] = string+old_position;


?
0
56 / 93 / 10
Регистрация: 20.03.2017
Сообщений: 550
07.01.2018, 23:10
Смысл этого телодвижения? Терминал сам должен поддерживать юникод.

Добавлено через 2 минуты
Хотя... .
Убунтоводы же.
Пишите, чё нет то.
0
23 / 5 / 1
Регистрация: 05.01.2017
Сообщений: 58
07.01.2018, 23:12
Смысл есть. т.к. я надеюсь, человек это делает, не для просмотра данных в терминале.
А зачем это ему именно нужно, вопрос десятый.
0
56 / 93 / 10
Регистрация: 20.03.2017
Сообщений: 550
07.01.2018, 23:19
rosten, Должно выполняться как минимум 2 условия. Должен быть включён модуль NLC UTF8 и терминал должен поддерживать utf8. Я не в курсе что там за терминал у убунты, глючный наверна какой-то. В первую очередь надо поставить нормальный терминал.
0
23 / 5 / 1
Регистрация: 05.01.2017
Сообщений: 58
07.01.2018, 23:26
В первую очередь, нужно ошибку в коде исправить.
Забудьте о терминале.


(напридумывали себе что-то. Модуль какой-то(до сего момента, я о такой фигне и не подозревал). Терминал должен, там что-то поддерживать.....нет. Никому он ничего не должен.)
Вопрос, был конкретный. О работе с utf-8.
Ответ дан.
0
1263 / 977 / 384
Регистрация: 02.09.2012
Сообщений: 3,020
08.01.2018, 02:30
Лучший ответ Сообщение было отмечено Duuly как решение

Решение

Duuly,
в split нужно упорядочить код. сделайте две части кода:
1) поиск позиций разделителей во временный массив; в результате станет точно понятно, на сколько подстрок разделяется исходная строка; позиции разделителей запоминать во временном массиве, который можно выделить динамически, его длина будет не больше, чем всего строк в исходной строке; так что, можно выделить память под позиции размером wcslen(string)
2) заполнение result; заводить result в самой функции split, перед ее вызовом убрать; далее по циклу позиций создавать строки и заполнять уже конкретные result[i]
сейчас у вас все в кучу смешано, код не разобрать; правильно заметили, выглядит ужасно.
не понятно как оно вообще работает в отдельных случаях
1
1 / 1 / 3
Регистрация: 03.04.2016
Сообщений: 51
08.01.2018, 21:28  [ТС]
терминал здесь точно не при чем.
Цитата Сообщение от grgdvo Посмотреть сообщение
правильно заметили, выглядит ужасно.
Выглядит он ужасно из за постоянных переделок и поиска проблемы.
Цитата Сообщение от grgdvo Посмотреть сообщение
поиск позиций разделителей во временный массив
Была такая реализация, но что то не пошло. Заметил такую вещь, в некоторых случаях (реализациях)
функция совсем перестает отрабатывать, но при этом ошибок и падений программы нет.

Добавлено через 1 минуту
Цитата Сообщение от rosten Посмотреть сообщение
result[i] = (wchar_t*)malloc(lenght * sizeof(wchar_t)+1);
Это указатели на строки.
Цитата Сообщение от rosten Посмотреть сообщение
result[i] = string+old_position;
Проверка строки с последней позиции, а не сначала.

Добавлено через 14 часов 10 минут
На свежую голову вот что накодил:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
#include <string.h>
 
int split(const wchar_t *string, wchar_t delemiter, wchar_t **result);
 
int main(void)
{
    setlocale(LC_CTYPE, "");
    wchar_t *hello = L"Была такая реализация но что то не пошло";
    wchar_t delemiter = L' ';
    wchar_t **result;
    int count = 0;
    result = (wchar_t**)malloc(sizeof(wchar_t));
    wprintf(L"%ls\n", hello);
    count = split(hello, delemiter, result);
    wprintf(L"Деление строки по: '%lc'\n", delemiter);
    wprintf(L"Количество - %ld\n", count);
    for (int i = 0; i < count; i++) {
        wprintf(L"%ls\n", result[i]);
    }
    return 0;
}
 
int split(const wchar_t *string, wchar_t delemiter, wchar_t **result) {
    size_t len_string = wcslen(string);
    size_t len_substr = 0;
    int count = 1;
    int positions[wcslen(string) + 1];
    positions[0] = -1;
    for (int i = 0; i < wcslen(string); i++) {
        if (string[i] == delemiter) {
            positions[count++] = i;
        }
    }
    positions[count] = len_string;
    for (int i = 0; i < count; i++) {
        result[i] = (wchar_t*)malloc((positions[i+1] - positions[i]) * sizeof(wchar_t)+1);
        len_substr = ((len_string - positions[i]) - (len_string - positions[i+1])) - 1;
        result[i] = wmemcpy(result[i], string+(positions[i] + 1), len_substr);
    }
    return count;
}
Ошибок не обнаружил, пока что.
0
1263 / 977 / 384
Регистрация: 02.09.2012
Сообщений: 3,020
08.01.2018, 23:38
Цитата Сообщение от Duuly Посмотреть сообщение
Ошибок не обнаружил, пока что
Цитата Сообщение от Duuly Посмотреть сообщение
result = (wchar_t**)malloc(sizeof(wchar_t));
Ошибка здесь. Вы выделяете слишком мало памяти для массива строк. Вам просто везет, что программа не падает. Но факт, что в цикле по count вы выходите за границы выделенной области.

Ну и для каждого malloc нет его парного free. Для данной конкретной программы это не ошибка, память будет и так отчищена, но потенциально это тоже ошибка.
1
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
09.01.2018, 00:17
Duuly, зачем вам wchar_t для utf8?
0
1 / 1 / 3
Регистрация: 03.04.2016
Сообщений: 51
09.01.2018, 08:57  [ТС]
Цитата Сообщение от grgdvo Посмотреть сообщение
result = (wchar_t**)malloc(sizeof(wchar_t));
Да, согласен, хотя не падает.
Цитата Сообщение от grgdvo Посмотреть сообщение
для каждого malloc нет его парного free.
В финальной версии это есть))
Цитата Сообщение от alex white Посмотреть сообщение
зачем вам wchar_t для utf8?
А какие есть альтернативы?
0
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
09.01.2018, 15:57
Duuly, utf-8 ascii-совместимая кодировка с переменной длиной символа (от 1 до 4). Причем первый байт однозначно определяет длину. Пройтись по символам таким образом проблемой не будет. А вот как передать разделитель и с чем сравнивать - тут уже посложнее, чтобы не заниматься сравнением маленьких строк, можно использовать целочисленные code points.
1
1 / 1 / 3
Регистрация: 03.04.2016
Сообщений: 51
09.01.2018, 20:09  [ТС]
Спасибо, попробую.
0
 Аватар для Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
10.01.2018, 20:44
Цитата Сообщение от alex white Посмотреть сообщение
utf-8 ascii-совместимая кодировка с переменной длиной символа (от 1 до 4).
Не от 1 до 4, а от 1 до 6. А 4 - это длина UNICODE кода, в UTF-32.
Правильно, курсанты...
90 градусов - это прямой угол.
А вода кипит, всё таки, при 100 градусов.
0
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
10.01.2018, 20:50
Olej, https://tools.ietf.org/html/rfc3629#section-3. Проверяйте информацию перед тем как самоуверенно тыкать.
2
 Аватар для Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
10.01.2018, 21:02
Цитата Сообщение от Duuly Посмотреть сообщение
Здравствуйте. Для разминки черепа решил освоить работу с unicode в С
Вот здесь лежит целая книжка "Языковая локализация C/C++" (больше 100 стр. формата A4).
А рядом ещё и "Регулярные выражения C/C++" - с учётом локализации.
Там детально расписано использование многобайтных кодировок (UTF-8), многобайтных функций mb*(), широких символов (wchar_t, wstring), ... и т.д.

P.S. только поспешите, пока здешний модератор не потёр ссылки!

Добавлено через 2 минуты
Цитата Сообщение от alex white Посмотреть сообщение
Проверяйте информацию перед тем как самоуверенно тыкать.
А мне не надо проверять то, что я давно и твёрдо знаю.
А по вашей дремучей ссылке 2003г. - полное дерьмо написано (по состоянию на 2017г.)

Добавлено через 9 минут
Цитата Сообщение от Olej Посмотреть сообщение
А по вашей дремучей ссылке 2003г. - полное дерьмо написано (по состоянию на 2017г.)
Изначально кодировка UTF-8 допускала использование до шести байтов для кодирования одного символа, однако в ноябре 2003 года стандарт RFC 3629 запретил использование пятого и шестого байтов, а диапазон кодируемых символов был ограничен символом U+10FFFF. Это было сделано для обеспечения совместимости с UTF-16.
Это было "улучшение" чисто в угоду Windows и бездарному UTF-16, но в Plan 9 (для которой первоначально разрабатывался UTF-8) и в UNIX-like это "улучшение" никто не стал принимать близко к сердцу.
(это точно та же история, что и с бездарным переопределением потоков в C++14 ... опять же в угоду Windows, но никто в этом вопросе не собирается отходить от POSIX-определений)
2
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
10.01.2018, 21:02
Olej,
А мне не надо проверять то, что я давно и твёрдо знаю
Очень жаль, верный шаг к собственной деградации. Впрочем, мне вас не жалко. Юникод сейчас содержит 136к символов, два дополнительных байта в utf-8 просто не нужны.
0
Почетный модератор
 Аватар для Humanoid
11553 / 4348 / 452
Регистрация: 12.06.2008
Сообщений: 12,453
11.01.2018, 09:42
Цитата Сообщение от Olej Посмотреть сообщение
А по вашей дремучей ссылке 2003г. - полное дерьмо написано (по состоянию на 2017г.)
Это стандарт. Если вы знаете более новый стандарт, то поделитесь, пожалуйста.
Хотя, я тоже где-то встречал UTF-8 из более чем 4 байт. Наверное, это для теоретического предела юникода.
0
 Аватар для Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
11.01.2018, 11:24
Цитата Сообщение от Duuly Посмотреть сообщение
А какие есть альтернативы?
Давайте с самого начала:
1. В современных дистрибутивах Linux всё представляется в кодировке UTF-8: текстовые файлы, текстовые строки, настройки текстовых редакторов и т.д. и т.п. (так же, как это имеет место в ОС Plan 9 или современных языках Python или Go). Когда вы набиваете свой программный код C/C++ в своём любимом текстовом редакторе (IDE), то вы уже вводите все символьные константы (в кавычках) в кодировке UTF-8 ... даже если вы набираете строку "xyz" из примера из K&R 79г. издания.
В этом вы можете убедиться, выполнив:
C++
1
2
char mama[] = "мама мыла раму";
printf( "%d , %d\n", strlen( mama ), sizeof( mama ) );
... и с удивлением обнаружив что ...

2. Вы можете, конечно, перенастроить свой любимый текстовый редактор (IDE), указав ему в кодировке какой-то идиотизм ... типа CP-866 или CP-1251 (большинство редакторов такое позволяют). И компилятор благополучно сожрёт это, но на этапе выполнения вы будете иметь большие хлопоты ... а если кто будет позже работать с этим вашим кодом, то поминать вас будет такими словами ... что в гробу вас будет крутить как пропеллер.
Такое может допускаться только для очень специальных целей.

3. До тех пор, пока вас не касается внутреннее содержимое строки (контент), вы можете с UTF-8 строками делать достаточно многие вещи не заморачиваясь с их внутренним представлением (strcpy(), strcat() и др.) ... если аккуратно и хорошо понимая что делаете. А вот такие вещи, например, как strlen() или strtok() (с контентом строки) - не прокатят.

4. А wchar_t (или wstring в C++) - это широкие локализованные строки, в Linux это всегда UTF-32, 32-бит на любой символ, в том числе и на ASCII - это "чистое" представление UNICODE символа. Это никакого отношения к мультибайтному представлению UTF-8 не имеет.

5. А для взаимных преобразований между мультибайтными символами/строками UTF-8 и широкими символами/строками UTF-32 есть целая группа функций в стандартной (C99) библиотеке C, вида mb*(): mblen(), mbtowc(), mbstowcs(), wcstombs() и т.д. На всё это добро есть обстоятельные man-ы.
А ковырятся во внутреннем побайтном представлении UTF-8 символов - это последнее дело ... это всё равно. что вместо printf() или ncurses - писать непосредственно в область видеопамяти (во времена MS-DOS были такие умельцы).

Я это всё написал потому, что в названии темы вы пишете про UTF-8, а в примерах возитесь с UTF-32 ... как-то всё до кучи.

Добавлено через 8 минут
Цитата Сообщение от Humanoid Посмотреть сообщение
Это стандарт. Если вы знаете более новый стандарт, то поделитесь, пожалуйста.
Это "не совсем" стандарт - это Request for Comments: предложения для комментирования, рабочее предложение...
Иногда они (RFC) используются разработчиками как "почти стандарт" (особенно в области сетевых технологий).
Но данный RFC как-раз несколько отличается от того, как и для чего UTF-8 реализовали Кен Томпсон и Роб Пайк в 1992г. (предполагаю, что всем здесь присутствующим эти фамилии говорят о многом).

Добавлено через 11 минут
Цитата Сообщение от Humanoid Посмотреть сообщение
Это стандарт.
А если уж говорить точно про стандарты, то это ISO/IEC 10646.2 (версия 2) и ISO/IEC 10646 (версия 3), которая ожидается в этом, 2018-м году.
Стандарт консорциума UNICODE.
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
11.01.2018, 19:44
Цитата Сообщение от Olej Посмотреть сообщение
... и с удивлением обнаружив что ...
... русские символы занимают по 2 байта. А латинские 1 байт, и цифры, и знаки препинания тоже. И что, это для кого-то новость? Какое отношение это имеет к 6-байтным символам?
Просто приведите пример 5- или 6-байтного UNICODE символа.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.01.2018, 19:44
Помогаю со студенческими работами здесь

XmlSerializer.Serialize() как поменять кодировку с UTF-16 на UTF-8
Задача серилизовать объект в string, но с кодировкой UTF-8. подзадача - как представить строку как Stream? // VALIDATE ...

Изменить кодировку из utf-8 без bom в просто utf-8
формируется xls фаил в коде прописано response.setContexType(&quot;application/vnd.ms-excel;charset=UTF-8&quot; в эксел документе отображается...

Как создать рабочий XML в UTF-8? У меня исправно создаётся Windows-1251, но с UTF-8 проблема
Доброго дня, форумчане. Подскажите, что делать, чтобы создавался и открывался без ошибок XML-файл? Сейчас у меня такой код и если...

Разные кодировки файлов (ASCII, UTF-8, UTF-16)
Привет всем! Нужно написать программу поиска файлов, содержащих заданную строку. Т.е. пользователь выбирает начальный каталог, задаёт...

Преобразование Unicode (UTF-16) в UTF-8 и обратно
Здравствуйте. Признаюсь, снова нужна подмога профессионалов. :help: Перейду к проблеме: Есть файл my_list.dic в кодировке Unicode (а не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru