Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > [FAQ] Каракули вместо русских букв


Автор: papam 26.12.2007, 18:06

M
archimed7592
Обсуждаем статью для FAQ. Тема разделена из Пишем FAQ.

Всем Доброго времени суток!

В данной статье речь идет о преобразовании символьной информации между двумя кодировками OEM и ANSI  в ОС Windows




Метод первый :

Локализация 



   Локализация в первую очередь используется в потоках ввода/вывода стандарьной библиотеки.
  Программа открывает для чтения существующий файл и закрывает его. В противном случае ругается. Имя файла вводит пользователь. Причем предполагается, что файл находится в текущем каталоге (каталоге с нашим проектом). У меня проект называется Listing5, поэтому я в этой самой папке заранее создал текстовый файлик с именем Файлик.txt 

   Начнем с функции setlocale. Она нужна для установки, изменения или определения программной локали и имеет такой вид:
Код

char* setlocale(int category, const char* locale);


category – категория (тип) изменения локали;

locale – имя (название) локали;

   Первый параметр может принимать шесть различных значений, нам же подойдут два: LC_ALL или LC_CTYPE
   При использовании первого варианта изменения коснутся всех категорий, при использовании второго варианта изменения коснутся функций, работающих с символами.
   Второй параметр представляет собой имя национальных особенностей. Это может быть просто имя, например, “French” или же имя вместе с указанным через точку номером кодовой страницы “French_Canada.1252” или же только номер кодовой страницы “.866” . Можно не вспоминать номер кодовой страницы и поставить “.OCP” – текущий номер для OEM, определенный в операционной системе.

   Дальше в программе  объявляется prompt - строка С-стиля. 
   Здесь же она инициализируется строковым литералом с префиксом L.
   Префикс L указывает, что данная строка является строкой символов из расширенного набора (Unicode) и имеет тип const wchar_t[]. Дальше объявляется строка типа wstring. Это тот же самый string, но состоящий не из ANSI-символов, а из Unicode-символов (тип которых wchar_t). 
   Затем идет диалог с пользователем и инициализация filename строчкой, которую вводит пользователь.
   Последняя часть – собственно действия над файлом. Объявляется указатель на структуру FILE, которая содержит в себе информацию о текущем состоянии потока; используется во всех потоковых операциях ввода/вывода.
   Затем файл открывается с помощью функции [B]_wfopen[/b] (версия функции fopen стандартной библиотеки, но для Unicode). Эта функция принимает в качестве параметров имя файла и атрибут. 
   В нашем случае это 
Код
filename.c_str()
 – метод c_str преобразует строку string/wstring в строчку типа const char* или const wchar_t* соответственно. Это всё потому что функция _wfopen требует именно С-строки в качестве параметров.       Второй же параметр – атрибут, ну знаете: для чтения, для записи и т.д.… Файл открывается только для чтения, поэтому у нас он L”r”. Не забываем ставить префикс L, поскольку в нашем случае все в Unicode!
   В случае ошибки функция 
Код
_wfopen 
 возвращает 0, что и проверяется в условии if … else и в зависимости от его выполнения- невыполнения выводится соответствующее сообщение. 
   Функция 
Код
fclose
 закрывает файл. 

Пример:
Код

#include<iostream>
#include<locale>

using namespace std;

int main()
{
    setlocale(LC_ALL,".OCP");

    wchar_t prompt[21] = L"Введите имя файла...";
    wstring filename;

    wcout<<prompt<<endl;
    wcin>>filename;

    FILE* myFile;
    if((myFile = _wfopen(filename.c_str(),L"r")) == 0)
    {
        wcout<<L"Не работает!(Файл не найден)\n";
    }
    else
    {
        wcout<<L"Работает\n";
        fclose(myFile);
    }
    return 0;

}

Пример 2:
Код

#include <fstream>

int main()
{
  std::wofstream file;
  
  // Создаем новую локаль на основе локали потока и задать её файловому потоку
  file.imbue( std::locale(file.getloc(), new my_codecvt) );

  // Теперь можно открывать файл и осуществлять вывод
    file.open( "output" );
    file << L"АБВ";
 
  return 0;
}

 Метод второй:
функции SetConsoleCP и SetConsoleOutputCP


Вот эти функции:

Код

BOOL SetConsoleCP(UINT wCodePageID);

BOOL SetConsoleOutputCP(UINT wCodePageID);

Разница между этими двумя функциями такая: 
Код
SetConsoleCP    -     устанавливает номер кодовой страницы для ввода с консоли 

SetConsoleOutputCP -  для вывода в консоль 


  Чтобы узнать текущий номер кодовой страницы консоли, мы можем использовать вот эти две функции:

Код

UINT GetConsoleCP(void);

UINT GetConsoleOutputCP(void);


  Эти функции не принимают параметров, а возвращают текущий номер кодовой страницы консоли. Разница между ними такая же, как и у двух предыдущих - все ясно из названия.
  Более то, чтобы не мучаться  с таблицами всех этих номеров, есть ещё две функции:
Код

UINT GetACP(void);

UINT GetOEMCP(void);

  Обе функции без параметров, первая возвращает текущий номер кодовой страницы в ANSI, вторая - в OEM.
  Следовательно, эти функции очень удобно использовать в качестве параметров для функций:
  
Код
 SetConsoleCP  и  SetConsoleOutputCP
  
Эти функции  работают не всегда. Смотрите, какие у них требования:

Client: Included in Windows XP, Windows 2000 Professional, and Windows NT Workstation.

Server: Included in Windows Server 2003, Windows 2000 Server, and Windows NT Server.

Пример:
Код

#include<iostream>
#include<windows.h>

using namespace std;
int main()
{
    cout<<"Каракули!!!\n";

    ::SetConsoleCP(::GetACP());
    ::SetConsoleOutputCP(::GetACP());

    cout<<"Еще каракули!!!\n";
    cout<<"И еще каракули!!!\n";

    return 0;
}

Метод третий:

функции CharToOem и OemToChar



Две API-шные функции: 
Код

BOOL CharToOem(LPCTSTR lpszSrc, LPSTR lpszDs);

lpszSrc- указатель на С-строку (строка в ANSI, которую мы хотим преобразовать в OEM)

lpszDs - указатель на строку, в которую будет помещен результат преобразования


Код

BOOL OemToChar(LPCSTR lpszSrc, LPTSTR lpszDst);

lpszSrc- указатель на С-строку (строку в OEM, которую мы хотим преобразовать в ANSI)

lpszDst - указатель на строку, в которую будет помещен результат преобразования


   В качестве первого параметра функции принимают С-строчку, которую преобразуем, в качестве второго - строчку, в которую будет помещен результат преобразования. Если эти функции используются как ANSI-функции, то в качестве обоих параметров можно передавать одну и ту же строку. В таком случае переданная функции строчка просто преобразуется в нужную нам кодировку (без какого-либо буфера).
Есть еще пара вариантов:

Код

BOOL CharToOemBuff(LPCTSTR lpszSrc, LPSTR lpszDst, DWORD cchDstLength);

BOOL OemToCharBuff(LPCTSTR lpszSrc, LPTSTR lpszDst, DWORD cchDstLengt);


   Работают также как и CharToOem/OemToChar, с той лишь разницей, что в качестве третьего параметра принимают количество символов в строке, которые надо преобразовать.

  
Код
CharToOem и OemToChar 
  
  Эти функции  преобразуют строчку из ANSI в OEM и наоборот. Это значит, что нам вообще не надо мучаться  с номерами кодовых страниц и т.п. Но проблема в том, что преобразуют они лишь одну строчку. А сколько нам в программе может понадобиться выводить и вводить из консоли строчки - неизвестно, но каждую строчку (русскую) надо преобразовывать, следовательно, каждый раз при этом надо будет вызывать эти функции. Получается код, довольно захламленный постоянными вызовами одних и тех же функций. Но что поделаешь…  

  Чтобы избежать неудобств при использовании таких функций, можете, скажем, написать свой собственный класс, который будет чем-то вроде оболочки для выполнения этих операций. Например, класс, в котором будут перегружены операторы ввода (operator >>) и вывода (operator <<) таким образом, чтобы перед самим вводом/выводом выполнять необходимое преобразование. Чтобы для практики такой класс имел значение и был полезен, надо постараться - учесть всевозможные переполнения буфера, преобразования типов и т.д. и т.п. В общем, безопасность и функциональность - очень важны. А если вдруг захочется  попробовать создать класс, производный от iostream, учтите, что в нём  виртуальных функций нет. На мой взгляд, для теоретических знаний языка С++ это может быть полезно, но для практики проще (а пожалуй и лучше) просто явно вызывать функцию 
Код
CharToOem
 или 
Код
OemToChar
.
Пример:
Код

#include<iostream>
#include<windows.h>

using namespace std;
int main()
{
    char ourString1[100] = "Каракули!!!\n";
    char ourString2[100] = "Еще каракули!!!\n";

    cout<<ourString1;
    cout<<ourString2;


    ::CharToOem(ourString1,ourString1);
    ::CharToOem(ourString2,ourString2);

    cout<<ourString1;
    cout<<ourString2;

    return 0;
}



Метод четвертый:

CString::AnsiToOem и CString::OemToANSI


   В MFC для работы со строками есть специальный класс CString. И у этого замечательного класса есть кроме других два метода:
Код

void AnsiToOem();

void OemToAnsi();

  Эти функции осуществляют необходимое преобразование над объектом класса CString. Класс CString хорош, с ним очень удобно работать и уж лучше всегда по мере возможности использовать его вместо строк стиля С (массива символов). Хотя можно, конечно, и шаблон string из STL (Standard template library - Стандартная Библиотека Шаблонов, она входит в стандартную библиотеку). 
Пример:
Код

int  main(int argc,char* argv[], char* envp[])// принимает аргументы если используются параметры командной строки
{
    int nRetCode = 0;

    if(!AfxWinInit(::GetModuleHandle(NULL),NULL, :: GetCommandLine(),0))
    {
         nRetCode = 1;
    }
    else
    {
        Cstring ourStr("Каракули");
        cout<<(LPCTSTR)ourStr<<endl;

        ourStr.AnsiToOem();
        cout<<(LPCTSTR)ourStr<<endl;

    }
    return nRetCode;
}
  


Автор: nickless 26.12.2007, 18:38
Предлагаю написать в начале статьи, что речь идёт исключительно о windows, а то в линуксе, благодаря utf-8, прекрасно работают программки вроде
Код
#include <iostream>

int main()
{
    std::cout << "Траляля" << std::endl;
    return 0;
}

 smile 

Автор: papam 26.12.2007, 18:46
Можно прикрепить эти примеры к статье, тут 3 скриншота к каждому методу,я забыл, прошу прощения

Автор: Dov 26.12.2007, 19:27
Цитата(papam @  26.12.2007,  17:06 Найти цитируемый пост)
Так что, метод, конечно, очень удобный, но ни хрена толком не работающий. А жаль…


papam, кроме тех требований, которые ты упомянул, есть ещё, как минимум, два, которые ты не назвал, а именно:
1. Нужно использовать оконный режим, а не полноэкранный.
2. Нужно установить в свойствах окна шрифт Lucida Console.

Может быть по-этому у тебя и не работало на других машинах.  smile 

Автор: archimed7592 26.12.2007, 20:40
papam, всё пока не читал - только пробежался.
Первые претензии:
1. Убрать из текста слова "отродья", "ни хрена", "мессага", "фига" и пр. Воспользоваться более культурными синонимами. Короче говоря, переработать текст, чтобы его можно было "отдавать в печать".
1.1. Исправить множественные опечатки(в т.ч., часто встречающийся "&lt;" вместо "<").

2. Оформить все строки кода(в т.ч. прототипы ф-ций) в тэги code.

3. Я примеры не смотрел, но, если они не большие, то добавить их в текст, причём не просто в конце, а к каждому методу отдельно.

All, просьба оценить техническую корректность текста, причём, подойти к этому нужно настолько критично, насколько это возможно smile.

Автор: archimed7592 26.12.2007, 22:59
papam, как я вижу, ты немного подредактировал текст.

Смотри, если человек приходит с вопросом "почему у меня каракули в программе", то, очевидно, что он умеет создавать проект в своей любимой IDE(которая не обязательно будет MSVC), так что, думаю, что нужно убрать подробности о том, как создавать проект, какие строки и откуда нужно удалять и т.п.
Схема должна быть такой: описание метода, потом слова "Пример:" и сам пример, обрамлённый тегом code.

Причём, обязательно откорректировать примеры, убрав оттуда MS-специфичные вещи, аля _t, TCHAR и пр.(если метод не ориентирован исключительно на MSVC). main не должна принимать аргументы, если они ей не нужны.

Автор: papam 26.12.2007, 23:42
archimed7592,  историю убрать?

Автор: archimed7592 26.12.2007, 23:45
papam, я пока подробно не читал. Не знаю. После НГ будем более подробно разбираться. Сейчас, к сожалению, времени совсем нет.

Автор: zkv 27.12.2007, 17:29
Цитата(archimed7592 @  26.12.2007,  23:45 Найти цитируемый пост)
я пока подробно не читал. Не знаю. После НГ будем более подробно разбираться. Сейчас, к сожалению, времени совсем нет. 

да, тоже самое, давайте до после НГ отложим.  smile 

Автор: zkv 27.12.2007, 23:55
Цитата(nickless @  26.12.2007,  18:38 Найти цитируемый пост)
Предлагаю написать в начале статьи, что речь идёт исключительно о windows, а то в линуксе, благодаря utf-8, прекрасно работают программки вроде

да про это стоит упомянуть. 
для сведения, посмотри http://forum.vingrad.ru/index.php?showtopic=186208&view=findpost&p=1350138 (помню кто-то использовал преобразование к unsigned в качестве решения вопроса)
решение с локалью думаю стоит вынести в первую очередь, и упомянуть хотя-бы о существовании std::locale

а такие вещи:
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Две API-шные функции: 
Выделить всёкод C++
1:
    
CharToOem 
и 
Выделить всёкод C++
1:
    
OemToChar
.
Выделить всёкод C++
1:
    
BOOL CharToOem(LPCTSTR lpszSrc, LPSTR lpszDs);


Выделить всёкод C++
1:
    
lpszSrc
 - указатель на С-строку (строка в ANSI, которую мы хотим преобразовать в OEM)

Выделить всёкод C++
1:
    
lpszDs
 - указатель на строку, в которую будет помещен результат преобразования

Выделить всёкод C++
1:
    
BOOL OemToChar(LPCSTR lpszSrc, LPTSTR lpszDst);


Выделить всёкод C++
1:
    
lpszSrc
 - указатель на С-строку (строку в OEM, которую мы хотим преобразовать в ANSI)

Выделить всёкод C++
1:
    
lpszDst
 - указатель на строку, в которую будет помещен результат преобразования

окучить бы не мешало..
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Пользуемся расширенным символьным набором - Unicode

разве локали можно использовать только вместе с юникодом?

Автор: Winprogrammer 29.12.2007, 00:38
papam
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
 Первый параметр может принимать шесть различных значений, нам же подойдут два: LC_ALL или LC_CTYPE. 

опиши все параметры. Они могут пригодиться.
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Метод второй:
функции SetConsoleCP и SetConsoleOutputCP


Вот эти функции:

Сперва опиши в чем заключается второй метод. А потом уже приступай к описанию функций, как ты это сделал в первом методе.
Третий и четвертый методы имеют тот же недостаток оформления - нет описания.
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Две API-шные функции: 

Это функции какого API ???? API - это Application Programming Interface. Как таковых API много. Для опытного человека понятно, что это WinAPI. А для новичка - это тёмные дебри.
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
С-строчку

Используй более оффициальный язык.

ЗЫ: В принципе статья - отличная! только ее надо "вылизать"! ;)

Вот пока все, что могу сказать. Но над статьей надо еще работать... работать... и работать... smile Удачи автору! ;)

Автор: archimed7592 29.12.2007, 17:35
Что ж. Начну, наверное, с этой статьи. А точнее с первого метода(локаль).
Сразу предупрежу, что, даже если покажется, что я как-то грубо высказываюсь - это не означает, что я к Вам плохо отношусь. Можете считать, что я выражаю мысли новичка, который читает Вашу статью smile.


Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
В данной статье речь идет о преобразовании символьной информации между двумя кодировками OEM и ANSI  в ОС Windows

OEM - это что за кодировка такая? Неплохо было бы упомянуть.
ANSI - это что за кодировка? А Unicode мы в этой статье не рассматриваем?



Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Программа открывает для чтения существующий файл и закрывает его. В противном случае ругается. Имя файла вводит пользователь. Причем предполагается, что файл находится в текущем каталоге (каталоге с нашим проектом). У меня проект называется Listing5, поэтому я в этой самой папке заранее создал текстовый файлик с именем Файлик.txt 

Какая ещё программа? Какой файл? Зачем ругаться? О чём вообще речь?


Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Начнем с функции setlocale. Она нужна для установки, изменения или определения программной локали и имеет такой вид:

Отлично, а в каком заголовочном файле эта ф-ция объявлена?



Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Выделить всёкод C++
1:
    
category
 – категория (тип) изменения локали;

Выделить всёкод C++
1:
    
locale
 – имя (название) локали;

Ммм. Не обязательно каждое слово оформлять в тэг code. Можно было бы либо просто не оформлять никак, либо выделить моноширинным шрифтом(предпочтительнее). К примеру так:
category – категория (тип) изменения локали.
[font=courier]category[/font] – категория (тип) изменения локали.


Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
В файле <locale> объявлен объект locale. Он контролирует национальные особенности, классификацию символов на буквы, цифры и т.д., устанавливает порядок следования символов, управляет видом вводимых и выводимых численных значений (даты, денежки и т.д. и т.п.).

Очень интересно, хорошо бы ещё понять к чему мне нужно было читать этот абзац.

Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
 Первый параметр
Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Второй параметр
А ещё лучше - понять бы к чему нужен был предыдущий абзац между сигнатурой ф-ции и описанием её параметров.


Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Дальше в программе  объявляется prompt - строка С-стиля. 
В какой программе? Вы о чём?

Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
 Здесь же она инициализируется строковым литералом с префиксом L.

Кем кем? Литералом? А это кто?

Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
 Затем файл открывается с помощью функции _wfopen (версия функции fopen стандартной библиотеки, но для Unicode).

Хнык-хнык. А мой компилятор, говорит, что не знает о такой ф-ции :'(.

Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Не забываем ставить префикс L, поскольку в нашем случае все в Unicode!

А зачем нам юникод сдался? Мне что, из-за этих каракуль всю программу под юникод переписывать?

Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Пример:

Я что-то не понял - пример для Си или для С++?

Цитата(papam @  26.12.2007,  18:06 Найти цитируемый пост)
Пример2:

Хто есть my_codecvt? Мой компилятор отказывается это компилировать. Хнык-хнык.


Теперь в общем и целом: повествование оформленно как описание примера. Пример почему-то идёт после самого описания. Зачем-то смешаны и Си и С++.

Пожелания(кроме процитированных багов):
1. перед самими методами в двух словах написать откуда вообще взялась проблема.
2. перед методами перечислить список методов с очень кратким описанием.
3. метод: сначала описание метода как такого, потом пример, потом описание примера.
4. в примерах не должно быть ничего лишнего(зачем там вообще понадобились файлы? а юникод?)

Автор: papam 29.12.2007, 18:05
archimed7592,завтра постараюсь исправить все.
 

Автор: archimed7592 17.1.2008, 19:40
papam, как дела со статьей продвигаются? smile

Автор: archimed7592 20.1.2008, 19:46

M
archimed7592
Так, papam пропал.
Есть желающие довести статью до ума?
Желающих прошу отписаться здесь.

Автор: JackYF 20.1.2008, 20:06
Если
1) все примеры, наличествующие сейчас в статье, работоспособны
2) никто из камрадов не возьмётся
, то могу я с ограничениями - винды у меня не водится, поэтому могу подправить только стиль и описание до удобоваримого вида.

З.Ы.  smile Что там с остальными статьями?

Автор: archimed7592 20.1.2008, 20:11
Цитата(JackYF @  20.1.2008,  20:06 Найти цитируемый пост)
Если
1) все примеры, наличествующие сейчас в статье, работоспособны

Ок, есть желающие проверить? smile

Автор: Kanes 6.2.2008, 10:43
Пока проверил 2:
Цитата

 Метод второй:
функции SetConsoleCP и SetConsoleOutputCP

Работает без проблем, единственное надо дополнить огранечения по применению, т.е. установка шрифта Lucida Console и не возможность работы в полноэкранном режиме

Цитата

Метод третий:
функции CharToOem и OemToChar

Работает, но, может я конечно что-то сам напутал, короче, для простоты написал ф-цию ToRus:
Код

char * ToRus(char * str)
{
    char * buf = new char [sizeof(str)];
    CharToOem(str, buf);
    return buf;
}

и простенький пример:
Код

//----------------------------------------------------------------
int main()
{
  cout << ToRus("строка\n");
  //какие-нибудь вычисления и т.п.
  cout << ToRus("еще текст");
  return 0;
}

Так вот, компилятор собирает все нормально, только при работе программа вылетает когда доходит до  второго cout'а

P.S.
Скоро проверю остольные способы

Автор: bsa 6.2.2008, 13:36
Kanes
1. sizeof(str) в твоем случае всегда равно 4 (размер указателя, а не массива)
2. ты сделал new[], а кто будет делать delete[]?
Код
#include <string.h>
#include <stdio.h>
#include <windows.h>

char * ToRus(const char * str)
{
    char * buf = (char*)malloc(strlen(str) + 1); //если бы нужен был C++, то кто мешал бы воспользоваться std::string?
    CharToOem(str, buf);
    return buf;
}

int main()
{
     char *p;
     p = ToRus("строка\n");
     puts(p);
     free(p);
     //какие-нибудь вычисления и т.п.
     p = ToRus("еще текст");
     puts(p);
     free(p);
     return 0;
}

Автор: Damarus 6.2.2008, 17:40
Код
#include <stdio.h>
#include <locale.h>

int main()
{
    printf("Тест\n");
    setlocale(LC_ALL, ".OCP");
    printf("Тест\n");
}

Цитата
D:\>gcc test.c -o test.c.exe

D:\>test.c.exe
╥хёЄ
╥хёЄ

D:\>


Код
#include <iostream>
#include <locale>
#include <stdexcept>

int main()
{
    std::cout << "Тест" << std::endl;
    
    try
    {
        std::locale::global(std::locale(".OCP"));
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
    
    printf("Тест\n");
}

Цитата
D:\>g++ test.cpp -o test.cpp.exe

D:\>test.cpp.exe
╥хёЄ
locale::facet::_S_create_c_locale name not valid
╥хёЄ

D:\>


MinGW 3.4.5

Автор: JackYF 6.2.2008, 18:48
Цитата(Damarus @  6.2.2008,  16:40 Найти цитируемый пост)
name not valid

дык и верно, что за .OCP? почему не .1251, не CP1251?

Автор: bsa 6.2.2008, 18:52
Damarus, посмотри внимательно статью. там перед текстовыми константами буква L стоит.

Автор: Damarus 6.2.2008, 20:50
Цитата(JackYF @  6.2.2008,  18:48 Найти цитируемый пост)
дык и верно, что за .OCP? почему не .1251, не CP1251? 

1. Почему .OCP надо спрашивать у papam'а. 
2. С .1251, CP1251, ru_RU, Russian_Russia.1251, French_Canada.1252 и т.д. результат тот-же.

Цитата(bsa @  6.2.2008,  18:52 Найти цитируемый пост)
Damarus, посмотри внимательно статью. там перед текстовыми константами буква L стоит. 

libstdc++ из mingw не поддерживает unicode. Я думаю это вообще не должно играть роли.

PS. Вообще я хотел только показать, что не на всех компиляторах пример будет работать.

Автор: JackYF 6.2.2008, 21:13
Цитата(Damarus @  6.2.2008,  19:50 Найти цитируемый пост)
PS. Вообще я хотел только показать, что не на всех компиляторах пример будет работать. 

Нет, ну это да. Поэтому столько костылей и приводится, чтобы хоть что-нибудь работало в виндовой консоли...

З.Ы. Недавно разбирался с QString, могу показать, как сделать ещё один костыль на основе Qt4Core smile

Автор: Kanes 6.2.2008, 21:51
ИМХО, пока реально работает только SetConsoleCP и SetConsoleOutputCP, проверял на 
* Microsoft Visual C++ Free Toolkit 2003
* Borland C++ Compiler 5.5
* mingw


Автор: LinuxanT 7.2.2008, 01:18
у мея так прокатило... в консоли

Код
#include <iostream>
#include <locale>
using namespace std;

int main()
{
  setlocale(LC_ALL, "Russian");
  cout << "Здесь должен быть русский текст\n";
  cin.get();

  return 0;
}


Автор: bsa 7.2.2008, 01:44
LinuxanT, какой компилятор?

Автор: Djinn 7.2.2008, 12:12
Код

setlocale(LC_ALL, "Russian");


Сработало в MSVC 2005

Пасиба большое !  smile  smile 

Автор: Djinn 7.2.2008, 19:46
правда у мея так прокатило... в консоли

Код
#include <iostream>
using namespace std;

int main()
{
  setlocale(LC_ALL, "Russian");
  cout << "Здесь должен быть русский текст\n";
  cin.get();

  return 0;
}


Автор: JackYF 7.2.2008, 19:48
Цитата(Djinn @  7.2.2008,  18:46 Найти цитируемый пост)
#include <locale>


Djinn, ?

Автор: Djinn 7.2.2008, 21:04
у меня без него  работает !

Автор: Kanes 7.2.2008, 21:34
А у меня и с ним не работает((((

Автор: LinuxanT 8.2.2008, 04:55
Цитата(bsa @ 7.2.2008,  01:44)
LinuxanT, какой компилятор?


MSVC 2008 pro на визуалках работает.....

Автор: Djinn 8.2.2008, 16:30
Не, у меня у знакомого такой как у мя компилятор и говорит не работает :( интересно от чего это зависит ? :(

Автор: Kanes 8.2.2008, 17:53
У меня на mingw заработало

Автор: Djinn 17.2.2008, 10:53
Вобщем работает оно у тех кто делает проект в Unicode, поэтому оно работает у всех =) просто стоит настроить немного.... 1 параметр smile

Автор: aleknek 1.3.2008, 18:47
Написал простенькую программу, которая запрашивает имя пользователя и фамилию, а затем выводит отдельной строкой. Так вот подключил локаль, как обычно делаю, для отображения русского текста, при наборе  все нормально, а вот при выводе получается абракадабра всякая, уже заходил в настройки проекта менял Use Unicode Character Set на Use Multi-Byte Character Set, толку никакого, подскажите, пожалуйста, как быть ???  Все это пишется в среде Microsoft Visual Studio 2005 :  
Код

// S_203_3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include "locale.h"
#include "conio.h"
#include <string>
#include "windows.h"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    setlocale (LC_CTYPE,".1251");
    setlocale (LC_MONETARY,".1251");

    char first_name [20];
    char last_name[20];
    char fio [40];
    char dest[100];
    cout << "Ваше имя: ";
    cin.getline(first_name, 20);
    cout << "Ваша фамилия: ";
    cin.getline(last_name, 20);
    strcpy (fio, first_name);
    strcat (fio, ", ");
    strcat (fio, last_name);
    CharToOem(fio, dest);
    cout << "Ваша фамилия и имя: " << dest;
    getch();
    return 0;
}



Автор: rugo 26.3.2008, 15:00
Подскажите,почему у меня не работает конвертация кодировки Dos в Win при вызове следующей функции
Код

OemToChar((Memo1->Lines->Strings[1]).c_str(),(Memo1->Lines->Strings[1]).c_str());

Автор: rugo 26.3.2008, 17:04
Цитата(rugo @ 26.3.2008,  15:00)
Подскажите,почему у меня не работает конвертация кодировки Dos в Win при вызове следующей функции
Код

OemToChar((Memo1->Lines->Strings[1]).c_str(),(Memo1->Lines->Strings[1]).c_str());

Разобрался сам.

Автор: Baton2007 12.5.2008, 20:04
Извеняюсь если такое уже было я лично пользуюсь такой функцией:

Код

void rus(char* str)
  {
    char *str1 = new char[100];
    CharToOem(str, str1);
    cout << str1;
  }



Вот пример:

Код

#include "iostream.h"
#include "windows.h"

void rus(char* str)
  {
    char *str1 = new char[100];
    CharToOem(str, str1);
    cout << str1;
  }
  void main()
  {
   
    rus ("Русские буквы");

}



Автор: mmvds 10.8.2008, 01:08
Код

system("chcp 1251 > nul");
cout << "Русский текст\n";

Открываем свойства запущенного окна, шрифт - Lucida Console, для всех окон и ни каких проблем

Автор: миг 16.1.2011, 10:32
Цитата(JackYF @ 6.2.2008,  18:48)
Цитата(Damarus @  6.2.2008,  16:40 Найти цитируемый пост)
name not valid

дык и верно, что за .OCP? почему не .1251, не CP1251?

 У меня с .OCP и с .866 все работает.. а с.1251 в консоли кракозябры smile 

Автор: wester 16.1.2011, 19:39
миг
посмотри на даты сообщений.
и отложи лопату в сторону

Автор: миг 16.1.2011, 20:01
wester, Я видел) Просто консольные приложение под виндовс используют кодировку Доса.. а ребята  пытаются установить кодировку для виндовс и вывести символы.. Не смог не пройти мимо такого)

Автор: xvr 17.1.2011, 14:43
Цитата(миг @ 16.1.2011,  20:01)
wester, Я видел) Просто консольные приложение под виндовс используют кодировку Доса..

'Консольным программам' кодировка по барабану - их просят вывести байтики, они их и выводят. Дальше личное дело самой консоли. В девичестве она печатала байтики в cp866
Цитата

а ребята  пытаются установить кодировку для виндовс и вывести символы.. 
И что не так? chcp 1251 замечательно 'поженит' консоль с cp1251 кодовой страницей. И все выведется
Цитата

Не смог не пройти мимо такого)
Да уж. Вынуть тему 4х годичной давности, что бы ляпнуть глупость - как уж тут пройти мимо  smile 

Автор: миг 17.1.2011, 20:26
Цитата(xvr @ 17.1.2011,  14:43)
 И что не так? chcp 1251 замечательно 'поженит' консоль с cp1251 кодовой страницей. И все выведется



А в каких по вашему операционках используют консоль с кодовой страницей cp1251?
А ничего если по умолчанию кодовые страницы буферов консоли устанавливаются на кодовую страницу производителя OEM? 
И что по вашему должно произойти если по умолчанию стоит кодовая страница cp866.. а пытаются вывести символы в кодировке cp1251?

Автор: xvr 17.1.2011, 21:44
Цитата(миг @  17.1.2011,  20:26 Найти цитируемый пост)
И что по вашему должно произойти если по умолчанию стоит кодовая страница cp866.. а пытаются вывести символы в кодировке cp1251?
Именно по умолчанию. Строчку
Код

system("chcp 1251 > nul");
заметили? Она переключит консоль в cp1251. А дальше все символы в кодировке cp1251 будут замечательно выводится (причем именно по русски, а не кракозябрами)


Автор: миг 17.1.2011, 22:34
Да. но это уже было не в том примере о котором я говорил .

Автор: xvr 18.1.2011, 10:59
Цитата(миг @ 17.1.2011,  22:34)
Да. но это уже было не в том примере о котором я говорил .

С большим трудом нашел тот пример. Там локаль для консоли пытались выставить программно. Что так же нормально работает. 'Ребята' всего лишь напутали с именем локали, а так там все правильно.
Цитата

а ребята  пытаются установить кодировку для виндовс и вывести символы.. 
Вы не поверите, но это реально работает!  smile 

Автор: Rutti 30.5.2012, 13:04
В поисках настройки кириллицы наткнулся на такой вот исходник:
Код

// Упражнение из книги

#include <iostream>
#include <string>

using namespace std;

int main()
{
  string hello="ЏаЁўҐв";
  string message=hello+", ¬Ёа"+"!";

  cout<<message;

  return 0;
}

который прекрасно отображает кириллицу без смены шрифта в окне консоли в Windows.
Заметьте - комментарий и текст написаны в разных кодировках.
Как это делалось? Писатель постоянно переключал кодовые страницы? Или как?
В Dev C++ , кстати, не нашёл как можно поменять проект на Unicode - возможно ли вообще?

Автор: bsa 30.5.2012, 17:49
Rutti, пишешь код каким-нибудь досовым редактором (например, из borland c++ 3.1), сохраняешь. загружаешь в виндовый редактор и пишешь комментарии. но это для понимающих толк в извращенствах.

Автор: Rutti 30.5.2012, 20:13
Цитата(bsa @  30.5.2012,  17:49 Найти цитируемый пост)
для понимающих толк в извращенствах.

Вот разве что.

Автор: Rutti 30.5.2012, 22:55
Цитата(mmvds @  10.8.2008,  01:08 Найти цитируемый пост)
код C++1:2:system("chcp 1251 > nul");cout << "Русский текст\n";

У меня кракозябры

Цитата(Djinn @  17.2.2008,  10:53 Найти цитируемый пост)
Вобщем работает оно у тех кто делает проект в Unicode

А как этот проект создать в Dev C++ ?


Автор: bsa 31.5.2012, 23:22
Rutti, http://forum.vingrad.ru/index.php?showtopic=269794&view=findpost&p=2086699

Автор: Rutti 1.6.2012, 19:59
Цитата(Djinn @  7.2.2008,  12:12 Найти цитируемый пост)
код C++1:setlocale(LC_ALL, "Russian");highlightSyntax('cpp_kN2NhZ','cpp');Сработало в MSVC 2005

А почему тогда в GCC не работает? Не универсальное решение?

Автор: GraNit 2.6.2012, 06:01
Господа, значит остается редактировать вывод в какой-нибудь Far-е?

Для windows работает только system("chcp 1251>nul");

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)