С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 41, средняя оценка - 4.95
Danvern
40 / 39 / 3
Регистрация: 22.06.2010
Сообщений: 415
Записей в блоге: 1
#1

Перевод символа в Юникод - C++

24.06.2011, 12:05. Просмотров 5384. Ответов 31
Метки нет (Все метки)

Подскажите пожалуйста как закодировать например вот такую строку
привет
что бы она стала такой?
%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
Википедии увидел такой алгоритм:
1)Переводим символ в Юникод.
2)затем разделяем каждый байт знаком процента
подскажите как сделать первый пункт?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.06.2011, 12:05
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Перевод символа в Юникод (C++):

Вывод юникод символа в консоль - C++
Здравствуйте. Подскажите пожалуйста как вывести юникод символ в консоль, например этот символ "U+2658".

Перевод символа в число - C++
У меня такой вопрос. Необходимо прочитать из файла "input.txt" строку типа "D1", означающая координату на шахматной доске. Нужно первый...

Перевод символа в нижний регистр - C++
Привет всем)) у меня такой вопрос: почему функция tolower() возвращает не символ в нижнем регистре, а какие-то цифры (наверное код буквы)....

Перевод символа в число и обратно. - C++
Здравствуйте! Как перевести число в символ, и ,наоборот, как перевести символ в число? То есть по ASCII 'A'==65, как можно это...

Перевод символа в верхний регистр - C++
код символа , который я ввожу в командой строке, отличается от кода символа в переменной rlow #include <iostream> #include...

Перевод символа в ASCII и запись в массив - C++
Добрый день! Задача: пользователь вводить строку символов, далее символы переводятся в ASCII в бинарном коде и записываются в массив...

31
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,431
Завершенные тесты: 1
05.07.2011, 19:46 #16
Цитата Сообщение от Danvern Посмотреть сообщение
вы про это
не только:

Цитата Сообщение от Danvern Посмотреть сообщение
char temp[6];
Цитата Сообщение от Danvern Посмотреть сообщение
char * result = new char[strlen(s) * 6 + 1];
Цитата Сообщение от Danvern Посмотреть сообщение
memset(result,0,strlen(s) * 6 + 1);
Цитата Сообщение от Danvern Посмотреть сообщение
hos = sw[i] >> 6;
los = (hos << 6) ^ sw[i];
почему 6? как связаны эти куски? это одно понятие? что если необходимо будет изменить это значение.

Цитата Сообщение от Danvern Посмотреть сообщение
if((int)sw[i] >= 128 && (int)sw[i] <= 2047)
что это за значения ?
0
Danvern
40 / 39 / 3
Регистрация: 22.06.2010
Сообщений: 415
Записей в блоге: 1
05.07.2011, 20:17  [ТС] #17
это все вики педии написано

Цитата Сообщение от schdub Посмотреть сообщение
почему 6? как связаны эти куски? это одно понятие? что если необходимо будет изменить это значение.
потому что каждая буква например "п" в url кодировке "%D0%BF" собственно в массиве должно быть в 6 раз больше места чем в начальном.
Цитата Сообщение от schdub Посмотреть сообщение
что это за значения ?
вот из википедии
0x00000080 — 0x000007FF (128 - 2047) 110xxxxx 10xxxxxx кириллица, расширенная латиница, арабский, армянский, греческий, еврейский и коптский алфавит; сирийское письмо, тана, нко; МФА; некоторые знаки препинания
Добавлено через 24 минуты
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <stdio.h>
using namespace std;
 
int main()
{
    setlocale(0,"");
    system("cls");
 
    char s[] = "hello Word";
    char illegalChar[] = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
    bool whatIllegal = false;
    char temp[6];
    int hos , los ,lenStr = strlen(s);
    long int sym;
    char * result = new char[lenStr * 6 + 1];
    wchar_t * sw = new wchar_t[lenStr + 1];
 
    memset(result,0,lenStr * 6  + 1);
    memset(sw,0,lenStr + 1);
 
    mbstowcs(sw,s,lenStr);
 
    for(int i = 0;i < (int)strlen(s);i++)
    {
        
        if((int)sw[i] <= 127)
        {
            memset(temp,0,sizeof(temp));
            for(int k = 0;k < sizeof(illegalChar);k++)
            {
                if(illegalChar[k] == sw[i])
                {
                    whatIllegal = true;
                    break;
                }
            }
 
            lenStr = strlen(result);
 
            if(!whatIllegal)
            {
                sprintf(temp,"%X",(int)sw[i]);
                result[lenStr] = '%';
                result[lenStr + 1] = temp[0];
                result[lenStr + 2] = temp[1];
            }
            else
            {
                result[lenStr] = sw[i];
                whatIllegal = false;
            }
        }
 
        if((int)sw[i] >= 128 && (int)sw[i] <= 2047)
        {
            hos = sw[i] >> 6;
            los = (hos << 6) ^ sw[i];
            sym = ( ( ( ( ( 6 << 5 ) ^ hos ) << 2 ) ^ 2 ) << 6 ) ^ los;
 
            memset(temp,0,sizeof(temp));
 
            sprintf(temp,"%X",sym);
 
            lenStr = strlen(result);
            result[lenStr] = '%';
            result[lenStr + 1] = temp[0];
            result[lenStr + 2] = temp[1];
            result[lenStr + 3] = '%';
            result[lenStr + 4] = temp[2];
            result[lenStr + 5] = temp[3];
        }
    }
    cout << result << endl;
 
    delete[] sw;
    delete[] result;
 
    getchar();
    return 0;
}
0
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,431
Завершенные тесты: 1
05.07.2011, 21:18 #18
на будущее:
Цитата Сообщение от Danvern Посмотреть сообщение
C
1
memset(sw,0,lenStr + 1);
скорее всего неверно. обратите внимание на третий аргумент (должен быть указан размер в байтах). но т.к.:
Цитата Сообщение от Danvern Посмотреть сообщение
C
1
wchar_t * sw = new wchar_t[lenStr + 1];
lenStr - количество символов во входной строке, каждый символ которой равен 1 байту, но sizeof(wchar_t) == 2 байтам
таким образом нужно:
Цитата Сообщение от Danvern Посмотреть сообщение
C
1
memset(sw,0, sizeof(*sw) * (lenStr + 1));
0
grizlik78
Эксперт С++
1972 / 1465 / 122
Регистрация: 29.05.2011
Сообщений: 3,033
05.07.2011, 21:57 #19
Цитата Сообщение от schdub Посмотреть сообщение
но sizeof(wchar_t) == 2 байтам
Главное на это не закладываться (чего, впрочем, в рекомендуемом примере и нет), так как у меня, например, sizeof(wchar_t) == 4
0
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,431
Завершенные тесты: 1
05.07.2011, 23:47 #20
Цитата Сообщение от Danvern Посмотреть сообщение
C
1
for(int i = 0;i < (int)strlen(s);i++)
вопрос на засыпку, как Вы думаете сколько раз будет вызвана функция strlen() ?

Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
int counter()
{
    static int r = 0;
    std::cout << r++ << std::endl;
    return 10;
}
 
int main()
{
    for (int i = 0; i < counter(); ++i)
    {
        ;
    }
    system("pause");
    return 0;
}
Добавлено через 1 минуту
Цитата Сообщение от grizlik78 Посмотреть сообщение
так как у меня, например, sizeof(wchar_t) == 4
grizlik78, естественно, я говорил о своем компиляторе
1
Danvern
40 / 39 / 3
Регистрация: 22.06.2010
Сообщений: 415
Записей в блоге: 1
06.07.2011, 06:28  [ТС] #21
странно у меня wchat_t == 2

Добавлено через 12 минут
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <stdio.h>
using namespace std;
 
int main()
{
    setlocale(0,"");
    system("cls");
 
    char s[] = "hello Word";
    char illegalChar[] = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
    const int illegalCharFor = sizeof(illegalChar);
    bool whatIllegal = false;
    char temp[6];
    int hos , los ,lenStr = strlen(s);
    long int sym;
    const int lenStrFor = lenStr;
    char * result = new char[lenStr * 6 + 1];
    wchar_t * sw = new wchar_t[lenStr + 1];
 
    memset(result,0,lenStr * 6  + 1);
    memset(sw,0,sizeof(wchar_t) * lenStr + 1);
 
    mbstowcs(sw,s,lenStr);
 
    for(int i = 0;i < lenStrFor;i++)
    {
        
        if((int)sw[i] <= 127)
        {
            memset(temp,0,sizeof(temp));
            for(int k = 0;k < illegalCharFor;k++)
            {
                if(illegalChar[k] == sw[i])
                {
                    whatIllegal = true;
                    break;
                }
            }
 
            lenStr = strlen(result);
 
            if(!whatIllegal)
            {
                sprintf(temp,"%X",(int)sw[i]);
                result[lenStr] = '%';
                result[lenStr + 1] = temp[0];
                result[lenStr + 2] = temp[1];
            }
            else
            {
                result[lenStr] = sw[i];
                whatIllegal = false;
            }
        }
 
        if((int)sw[i] >= 128 && (int)sw[i] <= 2047)
        {
            hos = sw[i] >> 6;
            los = (hos << 6) ^ sw[i];
            sym = ( ( ( ( ( 6 << 5 ) ^ hos ) << 2 ) ^ 2 ) << 6 ) ^ los;
 
            memset(temp,0,sizeof(temp));
 
            sprintf(temp,"%X",sym);
 
            lenStr = strlen(result);
            result[lenStr] = '%';
            result[lenStr + 1] = temp[0];
            result[lenStr + 2] = temp[1];
            result[lenStr + 3] = '%';
            result[lenStr + 4] = temp[2];
            result[lenStr + 5] = temp[3];
        }
    }
 
    cout << result << endl;
 
    delete[] sw;
    delete[] result;
 
    getchar();
    return 0;
}
0
grizlik78
Эксперт С++
1972 / 1465 / 122
Регистрация: 29.05.2011
Сообщений: 3,033
06.07.2011, 09:26 #22
Цитата Сообщение от Danvern Посмотреть сообщение
странно у меня wchat_t == 2
Чего странного-то?
0
Danvern
40 / 39 / 3
Регистрация: 22.06.2010
Сообщений: 415
Записей в блоге: 1
06.07.2011, 10:15  [ТС] #23
ну если подумать то ни чего))
0
Torument
0 / 0 / 1
Регистрация: 13.03.2014
Сообщений: 16
19.03.2014, 10:40 #24
А есть обратная функция (UrlDecode), для работы с кириллицей?

Добавлено через 9 часов 54 минуты
есть вот такой код:
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
inline int ishex(int x)
{
    return  (x >= '0' && x <= '9')  ||
        (x >= 'a' && x <= 'f')  ||
        (x >= 'A' && x <= 'F');
}
 
int decodeUrl(const char *s, char *dec)
{
    char *o;
    const char *end = s + strlen(s);
    int c;
 
    for (o = dec; s <= end; o++) {
        c = *s++;
        if (c == '+') c = ' ';
        else if (c == '%' && (  !ishex(*s++)    ||
                    !ishex(*s++)    ||
                    !sscanf(s - 2, "%2x", &c)))
            return -1;
 
        if (dec) *o = c;
    }
 
    return o - dec;
}
С кириллицей он не работает, так как обрататывает по 2 hex символа. А кириллица кодируется 4-мя знаками (если не считать %).
Как грамотно переделать код чтобы он различал где брать 2 пары символов для одной буквы, а где пару например пробел - %20 или знак равно - %3D?
0
korvin_
1940 / 1425 / 226
Регистрация: 28.04.2012
Сообщений: 5,095
19.03.2014, 11:36 #25
Если речь про UTF-8, то вот так.
0
Torument
0 / 0 / 1
Регистрация: 13.03.2014
Сообщений: 16
19.03.2014, 11:50 #26
Надо из hex перевести в UTF-8. Основная задача распознать в каком случае брать одну пару символов, а когда 2 пары (русские буквы)

есть таблица http://web-developer.name/urlcode/ где есть все символы

я бы, конечно мог сделать что-то в роде (не с++):
C#
1
2
3
string s= "-%d0%90%d0%a4-"
s = s.replace("%d0%90", "А");
s = s.replace("%d0%90", "Ф");
и получить s=-АФ-

Но хочется сделать по нормальному.
0
grizlik78
Эксперт С++
1972 / 1465 / 122
Регистрация: 29.05.2011
Сообщений: 3,033
19.03.2014, 11:57 #27
Цитата Сообщение от Torument Посмотреть сообщение
Надо из hex перевести в UTF-8.
UTF-8 это байт-ориентированная кодировка, поэтому если задача стоит именно как процитировано, то никаких пар символов распознавать не надо. Переводить надо именно побайтно. Другое дело, если вопрос стоит как декодированную последовательность байтов перевести из UTF-8 в какую-нибудь однобайтовую кодировку (типа cp1251), но это другая задача и здесь есть много разных средств. Я бы использовал libiconv, наверное. Кажется в WinAPI тоже что-то было.
0
Torument
0 / 0 / 1
Регистрация: 13.03.2014
Сообщений: 16
19.03.2014, 12:09 #28
задача собственно стоит в переводе из строки:
%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%3D
в строку "Привет="

Тут каждый кириллический (далее буду писать русский) символ состоит из пары шестнадцатиричных чисел, а = состоит из 1го шестнадцатиричного числа (hex) %3D.

Как брать не по парам, я не понимаю.

Добавлено через 5 минут
Код, который я приводил вместо П (%d0%9F) пишет Ð (это %d0) и Ÿ (это %9F), то есть П, вместо П. Так как по одному hex-числу
0
grizlik78
Эксперт С++
1972 / 1465 / 122
Регистрация: 29.05.2011
Сообщений: 3,033
19.03.2014, 12:15 #29
Это говорит от том, что код работает правильно.
Вот, тот же самый код, только законченный.
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
#include <iostream>
#include <cstdio>
#include <cstring>
 
inline int ishex(int x)
{
    return  (x >= '0' && x <= '9')  ||
        (x >= 'a' && x <= 'f')  ||
        (x >= 'A' && x <= 'F');
}
 
int decodeUrl(const char *s, char *dec)
{
    char *o;
    const char *end = s + strlen(s);
    int c;
 
    for (o = dec; s <= end; o++) {
        c = *s++;
        if (c == '+') c = ' ';
        else if (c == '%' && (  !ishex(*s++)    ||
                    !ishex(*s++)    ||
                    !sscanf(s - 2, "%2x", &c)))
            return -1;
 
        if (dec) *o = c;
    }
 
    return o - dec;
}
 
int main()
{
    char const *str = "%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%3D";
    char dec_str[256];
    decodeUrl(str, dec_str);
    std::cout << str << std::endl;
    std::cout << dec_str << std::endl;
}
Его вывод:
Код
$ ./hello 
%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%3D
Привет=
У меня linux и локаль UTF-8, поэтому всё выводится правильно. В Windows перед выводом надо перекодировать строку либо в cp1251, либо в cp866, в зависимости от того, куда производится вывод. Но это задача именно перекодировки из utf-8 в другую.
1
Torument
0 / 0 / 1
Регистрация: 13.03.2014
Сообщений: 16
19.03.2014, 12:23 #30
Цитата Сообщение от grizlik78 Посмотреть сообщение
У меня linux и локаль UTF-8, поэтому всё выводится правильно. В Windows перед выводом надо перекодировать строку либо в cp1251, либо в cp866, в зависимости от того, куда производится вывод. Но это задача именно перекодировки из utf-8 в другую.
Если так, то это радует.
То есть перед самым выводом строку надо перевести из utf-8 или на этапе формирования строки?
0
19.03.2014, 12:23
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.03.2014, 12:23
Привет! Вот еще темы с ответами:

Юникод в Си++ - C++
Здравствуйте. int main(int argc, char *argv) { wstring s1 = L&quot;abracadabra&quot;; cout &lt;&lt; s1.size() &lt;&lt; endl; // 11 ...

Юникод. Шахматные символы - C++
Всем привет. Хочется написать консольные шахматы (цензура), но вот в чем загвоздка: как правильно ввести вот эти коды фигур в программный...

Юникод символ в консоли - C++
Здорова! Есть вопрос, от можно ли в консоли как то вывести юникод символы? Допустим есть код символа в юникод U+2660 и как мне его...

Юникод в двоичную систему - C++
Добрый день! Подскажите, как из файла прочитать знак (на русском языке), после чего напечатать на экране представление знака в двоичной...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.