Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.65/26: Рейтинг темы: голосов - 26, средняя оценка - 4.65
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677

Utf-8. И снова кодировки

28.10.2014, 19:30. Показов 5645. Ответов 51
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Подскажите как конвертировать всё введённое с клавиатуры в utf-8.
Т.е. консоль запускается в какой-то стране Мира, там пользуют некий язык. Нужно определить текущую кодировку консоли и переконвертировать в utf-8...как? Виндось. Нужна функция вида:
C++
1
2
3
4
5
6
void gets_utf8(char*BUF)
{
      gets(BUF);
//определяем текущую кодировку, конвертируем в utf-8 и результат заносим в тот же массив, вместо исходных данных
//всё, мы молодцы. После завершения функции в переданном массиве содержится введённый текст в utf-8
}
Если можно, прямо результат, а не ссылки на чтиво, ибо чтиво я почитал и там как-то размыто для разных кодировок.
Надеюсь не слишком трудно будет жахнуть работающую реализацию подобной штуки. Спасибо.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.10.2014, 19:30
Ответы с готовыми решениями:

Перевод из кодировки UTF - 8 в ANSI
Всем привет! Пишу прогу на линухе, результаты работы вывожу в html файл. Так вот когда открываю файл для прочтения с помощью браузера там...

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

В чём отличия кодировки ms dos от кодировки ms windows?
Всем привет, подскажите в чём отличия кодировки ms dos от кодировки ms windows?

51
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
29.10.2014, 19:53
Студворк — интернет-сервис помощи студентам
Можно не учитывать Windows 95, там вообще много чего не будет работать.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2014, 20:23  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
кодировать UTF16->UTF8 всяко удобнее (и переносимее), чем из локальной кодировки
Т.е. избавиться от первого перекодирования?..логично, мне подходит. А утановить utf-16 через locale, SetConsolCP или в настройках проекта где-то? Вопрос наверняка тупой, но мозг уже не хочет думать совершенно.

Добавлено через 1 минуту
Или просто использовать w_ варианты ввода? Или всё вместе?
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
30.10.2014, 00:53
Цитата Сообщение от Retyrn0 Посмотреть сообщение
А утановить utf-16 через locale, SetConsolCP или в настройках проекта где-то? Вопрос наверняка тупой, но мозг уже не хочет думать совершенно.
utf-16 - это родная кодировка windows. Если речь о VS, то максимум что надо сделать - это выставить в свойствах проекта использование юникода (будут по-умолчанию использоваться эти самые W-версии api). Больше ничего не нужно. SetConsoleCP тоже не нужен, если пользоваться буфером для ostream/istream из той темы. WriteConsole\ReadConsole уже отдают текст в UTF-16.
Ну или можно перевести консоль в режим UTF16 (нормально работает только в VS):
C++
1
_setmode(_fileno(stdout), _O_U16TEXT);
1
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 12:36  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
utf-16 - это родная кодировка windows. Если речь о VS, то максимум что надо сделать - это выставить в свойствах проекта использование юникода (будут по-умолчанию использоваться эти самые W-версии api). Больше ничего не нужно. SetConsoleCP тоже не нужен, если пользоваться буфером для ostream/istream из той темы. WriteConsole\ReadConsole уже отдают текст в UTF-16.
Ну или можно перевести консоль в режим UTF16 (нормально работает только в VS): Код C++1
_setmode(_fileno(stdout), _O_U16TEXT);
Огромное спасибо за сохранённое время. Обязательно попробую описанный метод и напишу будущим ищущим результат. Завтра.

Добавлено через 11 часов 40 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Больше ничего не нужно.
В настройках проекта значение уникода стоит(она там и стояло по-умолчанию вроде). Делаю такую вешчь:

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 <conio.h>
 
#define buf_len             1024
 
using namespace std;
 
void gets_utf8(char*buf)
{
    wchar_t tbuf[buf_len];
    wcin.getline(tbuf,buf_len-1);
    WideCharToMultiByte(CP_UTF8,0,tbuf,-1,buf,buf_len,NULL,NULL);
}
 
int main()
{
    char BUF[8192];
    puts("This database has no equal in the universe, because I wrote it great frome you.\n");
 
    bool run=true;
    while(run)
    {
        gets_utf8((char*)BUF);
 
        switch((char)BUF[0])
        {
        case NULL:puts("Enter something...");
            break;
 
                      //много касов, которые не влияют на собственно тему
 
        default:
            puts("Error Command.\n");
            break;
        }
    }
 
    return 0;
}
Так вот...один из касов перенаправляет в функцию, которая записывает BUF в файл. Файл нотпадом открывается, как утф8 - порядок, но не английский текст абракадабрится.

Цитата Сообщение от DrOffset Посмотреть сообщение
_setmode(_fileno(stdout), _O_U16TEXT);
А изоткуда эта функция? А-то идентифиер из нот фаунд.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
30.10.2014, 12:43
Там вроде какой-то префикс в файле должен быть, чтобы он распознавался как utf8.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 13:03  [ТС]
Цитата Сообщение от nmcf Посмотреть сообщение
Там вроде какой-то префикс в файле должен быть, чтобы он распознавался как utf8.
Это с BOM типа? Тогда нет, проблема не в этом. Нотпад порядочно определяет и без него, что это утф8. И в первом вариатне всё происходило так же, но русский отображался норм.

Добавлено через 6 минут
Вот это " à¨¢¥â" у меня "привет"...
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
30.10.2014, 13:34
Цитата Сообщение от Retyrn0 Посмотреть сообщение
Делаю такую вешчь
Может быть конечно это явно и не прозвучало, но имелось в виду, что в случае utf16 мы вообще отказываемся от char. Тему, на которую я ссылку давал, смотрел? char появится только в момент сетевой передачи, когда нужен непосредственный utf8.

Добавлено через 17 минут
Цитата Сообщение от Retyrn0 Посмотреть сообщение
Так вот...один из касов перенаправляет в функцию, которая записывает BUF в файл. Файл нотпадом открывается, как утф8 - порядок, но не английский текст абракадабрится.
Не заметил сперва этой фразы. Пример, по-моему, вообще не в кассу Запутал только.
Короче ошибка твоя в том, что у тебя файл в UTF-8, а читаешь ты его как UTF-16 (в wchar_t). Естественно после этого результат нечитаемый. Если ты хочешь читать файл (с помощью streams) в utf8 и перекодировать его в utf16 на лету, то использовать нужно один из стандартных классов отсюда.
Или написать свой с использованием MultiByteToWideChar.
Если сам не сможешь, могу потом показать как. Мы на работе виндов не держим, поэтому только веччером.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 14:00  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
когда нужен непосредственный utf8
Для простоты понимания моей задачи:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <iostream>
#include <windows.h>
 
#define wstr_size   1024
 
using namespace std;
 
void main()
{
    FILE*file=fopen("DB.db","wb");
    wchar_t wstr[wstr_size];
    wcin.getline(wstr,wstr_size-1);
 
    char buf[wstr_size];
    WideCharToMultiByte(CP_UTF8,0,wstr,-1,buf,wstr_size,NULL,NULL);
    fwrite(buf,strlen(buf),1,file);
 
    fclose(file);
}
Мне нужно практически сразу это сохранить в файл - мне сразу нужен утф8. Пусть она в оперативной памяти как угодно хранится, но именно конвертация почему-то не срабатывает нормально =/
Результат программы выше - я ввожу привет, открываю файл - крокозябы =(

Добавлено через 4 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
файл в UTF-8, а читаешь ты его как UTF-16
Я его пока не читаю) Мне нужно введённую строку сохранить в файл в utf-8. Это я смог с горем пополам, только в файле не то, что я печатал с клавы) Что-то не правильно конвертируется?

Добавлено через 2 минуты
Прошу поправить что не так в коде выше, а дальше я вроде сам смогу осилить куда и что. Надеюсь упростил задачу до предела, чтобы людям не пришлось вникать в не нужные вещи и тратить своё время зря)

Добавлено через 1 минуту
Я грешу на
C++
1
wcin.getline();
Может широкий текст нужно по-другому с клавы читать?
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
30.10.2014, 14:17
Лучший ответ Сообщение было отмечено Retyrn0 как решение

Решение

Цитата Сообщение от Retyrn0 Посмотреть сообщение
wcin.getline(wstr,wstr_size-1);
Это не будет правильно работать без
Цитата Сообщение от Retyrn0 Посмотреть сообщение
_setmode(_fileno(stdin), _O_U16TEXT);
либо нужно использовать мой буфер из той темы. Тогда _setmode будет не нужен. Справка по _setmode.
Остальные способы (codecvt и т.п.) заставить работать wcin включают в себя перекодировку на лету, чего мы пытаемся избежать.

То, что ты вводишь в консоли конвертируется либо в DOS кодировку, либо в одну из локальных кодировок (если была выставлена SetConsoleCP, например). Естественно wcin уже получает не юникод. Чтобы он это не делал, нужно либо сменить режим (через setmode), либо сразу читать юникод через API, (W)ReadConsole.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 14:22  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
сразу читать юникод через API, (W)ReadConsole
Мне нравится эта идея) Сейчас гляну как этим правильно воспользоваться и жизнь наладится)

Добавлено через 2 минуты
ПОжалуй на данный момент это лучший ответ - я начинаю понимать почему всё так запутано и сложно(на первый взгляд) - это потому что разработчики хотели упростить работу потенциальным программистам
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
30.10.2014, 14:59
Цитата Сообщение от Retyrn0 Посмотреть сообщение
Мне нравится эта идея)
Мне не понятно почему ты упорно не хочешь прочитать ту тему Я же там уже все реализовал. Бери и пользуйся...

Цитата Сообщение от Retyrn0 Посмотреть сообщение
это потому что разработчики хотели упростить работу потенциальным программистам
Это историческое наследие давит.
Сначала винда не была юникодная, и были пляски с локальными кодировками. Потом она стала юникодная, но пляски остались, потому что тонны софта уже написаны для них. Поэтому нужна эта магия с define _UNICODE и W\A версиями API. Чтобы старый код собирался в новых системах.
Конкретно с консолью все еще хуже, консоли нужна была поддержка DOS-приложений, поэтому там по-умолчанию DOS-кодировка (в случае русской винды - это 866).
Теперь внимание: винда стала юникодной изнутри, но требования эти никуда не делись. Итог - постоянные перекодировки. Поэтому новый софт надо писать забыв и про ANSI версии API и про DOS-консоль, чтобы их избежать.

А еще, очень многие просто не понимают что есть что. Поэтому в добавок к объективным сложностям добавляют еще какие-то свои.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 15:09  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
А еще, очень многие просто не понимают что есть что.
Я когда начал разбираться с кодировками вообще подвис. Хотя сейчас понимаю, что не всё так плохо, как показалось. Вот что получилось. Если что не так, прошу прощения, но оно работает!!!)

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
#include <stdio.h>
#include <iostream>
#include <windows.h>
 
#define wstr_size   16384
 
using namespace std;
 
void main()
{
    FILE*file=fopen("DB.das","wb");
    wchar_t wstr[wstr_size];
    DWORD counter=0;
    while(counter==0)
    {
        ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),wstr,wstr_size,&counter,NULL);
        counter-=2;
    }
    wstr[counter]=0;//удаляем ентер
 
    char buf[wstr_size];
    WideCharToMultiByte(CP_UTF8,0,wstr,(counter-2)*2,buf,wstr_size,NULL,NULL);
    fwrite(buf,strlen(buf),1,file);
 
    fclose(file);
}
Огромное спасибище DrOffset-у. По-настоящему выручил!
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
30.10.2014, 15:46
wcin.getline(wstr,wstr_size-1);
Это не будет правильно работать без
_setmode(_fileno(stdin), _O_U16TEXT);
Почему не будет-то?
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 15:54  [ТС]
Цитата Сообщение от nmcf Посмотреть сообщение
Почему не будет-то?
У меня не работало. Почему...вероятно зачем-то конвертирует в кодировку, на которую настроен поток. ХЗ. Не работает, а <Читать консоль> работает.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
30.10.2014, 17:17
Если достаточно вводить только русский и английский, то всё работает без _setmode(). Вот чтение строки и запись в файл utf8 c BOM:
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
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <locale> 
#include <codecvt> 
 
using namespace std;
 
int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t s[100];
    wcin.imbue(locale("rus_rus.866"));
    wcout.imbue(locale("rus_rus.866"));
    wcout << "s: ";
    wcin.getline(s, 100);
 
    locale loc (locale(), new codecvt_utf8<wchar_t, 0x10ffffUL, codecvt_mode::generate_header>);
    wofstream wofs(L"d:\\res.txt");
    wofs.imbue(loc);
    wofs << s;
    wofs.close();
 
    system("pause");
    return 0;
}
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
30.10.2014, 17:28  [ТС]
Цитата Сообщение от nmcf Посмотреть сообщение
Если достаточно вводить только русский и английский
Цитата Сообщение от Retyrn0 Посмотреть сообщение
Т.е. консоль запускается в какой-то стране Мира, там пользуют некий язык..
Русского и английского не достаточно. На самом деле тогда вообще пропал бы смысл использовать уникод)
Но решение тоже интересное, находил в нете такое.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
30.10.2014, 18:13
Цитата Сообщение от nmcf Посмотреть сообщение
Если достаточно вводить только русский и английский, то всё работает без _setmode().
Хитрый какой. С перекодировкой из 866-то
Вся суть использования _setmode - это сделать без перекодировки.

Добавлено через 1 минуту
Если внимательно прочитать мои сообщения, то можно заметить, что я об этом говорил.

Добавлено через 6 минут
Цитата Сообщение от nmcf Посмотреть сообщение
Почему не будет-то?
Потому, что поток перекодирует данные введенные с консоли в соответствии с настройкой локали.
Если локаль по каким-либо причинам отличается от ANSI-кодировки консоли, то кодирование будет неверным и в wchar_t нам вернется ерунда. У ТС как раз это самое и произошло.
Ясное дело, что твой пример работает. Ты выставил локаль равную кодировке консоли по-умолчанию. Перекодирование 866->UTF16 прошло успешно, поэтому все нормально. Но, во-первых, вжесткую завязываться на конкретную локаль - это неправильно (безотносительно задачи ТС). Во-вторых тут лишняя перекодировка, которой могло бы и не быть.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
30.10.2014, 18:30
Тем не менее wcin.getline() работает без _setmode(). Я говорил об этом.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
30.10.2014, 18:38
Цитата Сообщение от nmcf Посмотреть сообщение
Тем не менее wcin.getline() работает без _setmode(). Я говорил об этом.
Ну попробуй ввести текст в консоли на французском. Поток произведет перекодировку в UTF-16 в соответствии с текущей локалью (которая русская) и получишь ты в wchar_t буфере нечитаемый бред. Это называется работает?
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
30.10.2014, 18:50
Я просто немного о другом сказал. wcin работает без переключения консоли на utf, и корректно формирует строку, но ограничен выбранной локалью.
Можно французскую установить.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.10.2014, 18:50

Как сделать чтобы таймер дойдя до 0 стартовал снова и снова?
Здравствуйте :) Как сделать чтобы таймер дойдя до 0 стартовал снова и снова? TimerSec = 59; TimerMin = 6; for(int i = TimerSec;...

Кодировки (ошибки кодировки) в логировании
Здравствуйте. Работаю с WINAPI и оттуда нормально приходят наименования на русском. Вот решил логирование организовать и на этом повалился...

Преобразовние Utf-16 <=> Utf-8
Вопрос казалось бы простой, но нормально ответа на него я пока не нашел. Нужно вывести строчку юникода(UTF-16) в файл с изменением...

Снова ошибки кодировки UTF-8 именно подпись BOM
На WAMP создавая любой новый PHP скрипт с помощью Adobe Dreamweaver CS5.5 - файлу указывал UTF-8 (без BOM). И все нормально работало. На...

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru