Ввод и вывод русского текста в консоли windows
От: Rediska555  
Дата: 13.08.11 18:18
Оценка:
Здравствуйте!
Недавно начал изучать С++ и сразу возник вопрос по поводу ввода и вывода кириллических символов в консольном приложении Windows. К примеру вот в таком приложении :

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string name;
    cout << "Введите ваше имя: " << endl;
    cin >> name;
    cout << "Привет " << name << "!" << endl;
    system("PAUSE");
    return 0;
}

текст выводится абракадаброй. Пробовал в начале функции main вставлять setlocale( 0, "" ) работает только на вывод текста, а введенное имя выводит абракадаброй. У Шилдта не нашел ответа на этот вопрос, хотя наши переводчики и перевели все слова в примерах его книги, но эти примеры выводят нормальный русский текст только в консоли linux.

Нашел еще вот такое решение с использованием широких строк wstring и потоков ввода wcin и вывода wcout:

#include <iostream>
#include <sstream>
#include <locale>
using namespace std;

int main()
{    // установка русской локали
    wcout.imbue(locale("rus_rus.866"));
    wcin.imbue(locale("rus_rus.866"));
    
    wstring name;
    
    wcout << L"Введите ваше имя: " << endl;
    wcin >> name;
    wcout << L"Привет " << name << L"!" << endl;
    
    system("PAUSE");
    return 0;
}

Вроде все работает, но не знаю на сколько это решение правильное и есть ли решение для обычных потоков ввода и вывода?
Помогите, пожалуйста!
русский текст в консоли windows setlocale #include<locale>
Re: Ввод и вывод русского текста в консоли windows
От: LaptevVV Россия  
Дата: 13.08.11 18:31
Оценка:
Здравствуйте, Rediska555, Вы писали:

R>Здравствуйте!

R>Недавно начал изучать С++ и сразу возник вопрос по поводу ввода и вывода кириллических символов в консольном приложении Windows. К примеру вот в таком приложении :

R>Нашел еще вот такое решение с использованием широких строк wstring и потоков ввода wcin и вывода wcout:

R>
R>#include <iostream>
R>#include <sstream>
R>#include <locale>
R>using namespace std;

R>int main()
R>{    // установка русской локали
R>    wcout.imbue(locale("rus_rus.866"));
R>    wcin.imbue(locale("rus_rus.866"));
    
R>    wstring name;
    
R>    wcout << L"Введите ваше имя: " << endl;
R>    wcin >> name;
R>    wcout << L"Привет " << name << L"!" << endl;
    
R>    system("PAUSE");
R>    return 0;
R>}

R>

R>Вроде все работает, но не знаю на сколько это решение правильное и есть ли решение для обычных потоков ввода и вывода?
R>Помогите, пожалуйста!
setlocale(LC_ALL, "Russian");
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Самое простое и элегантное решение
От: Rediska555  
Дата: 13.08.11 19:39
Оценка:
Здравствуйте, LaptevVV, Вы писали:


LVV>setlocale(LC_ALL, "Russian");


Но это решение не помогает, оно работает только на поток вывода. Если я ввожу в консоли свое имя русскими буквами, то в ответ программа пишет:
"Введите свое имя:"
ввожу "Вова", отвечает
"Привет абракадабра!"

Мое решение выше выдает:
"Введите свое имя:"
ввожу "Вова", отвечает
"Привет Вова!"

Но я нашел самое простое и элегантное решение . В Visual Studio в меню File есть пункт "Advanced Save Options", в нем можно выбрать кодировку DOS 866, в которой сохраняется исходник, что и есть решение всей проблемы. В выбранной кодировке сохраняются все файлы проекта.

И код:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string name;
    
    cout << "Введите ваше имя: " << endl;
    cin >> name;
    cout << "Привет " << name << "!" << endl;
    
    system("PAUSE");
    return 0;
}


будет работать на все 100%.!
русский текст в консоли windows
Re: Ввод и вывод русского текста в консоли windows
От: Centaur Россия  
Дата: 14.08.11 05:56
Оценка: +3 :)
Здравствуйте, Rediska555, Вы писали:

R>Недавно начал изучать С++ и сразу возник вопрос по поводу ввода и вывода кириллических символов в консольном приложении Windows. К примеру вот в таком приложении :


R>    cout << "Введите ваше имя: " << endl;

R>текст выводится абракадаброй.

Во-первых, кодировка файла. Если в файле встречается хоть что-то выходящее за пределы us-ascii, его нужно хранить в utf-8.

Во-вторых, в Windows для корректной работы со всем разнообразием символов нужно использовать Unicode, wide строки и wide потоки, потому что utf-8 нельзя установить в качестве мультибайтной кодировки, а все кодировки, которые можно — не имеют смысла.

И в-третьих, нужно вызывать setlocale(LC_ALL, ""), чтобы подтянуть локаль, установленную в настройках пользователя, и никогда не передавать названия конкретных локалей.

R>Пробовал в начале функции main вставлять setlocale( 0, "" ) работает только на вывод текста, а введенное имя выводит абракадаброй. У Шилдта не нашел ответа на этот вопрос, хотя наши переводчики и перевели все слова в примерах его книги, но эти примеры выводят нормальный русский текст только в консоли linux.


А здесь сразу две проблемы. Первая — ты читаешь книгу по программированию в русском переводе. И вторая, более серьёзная — ты читаешь Шилдта.
Re[2]: Ввод и вывод русского текста в консоли windows
От: Rediska555  
Дата: 14.08.11 17:14
Оценка:
Здравствуйте, Centaur, Вы писали:



C>Во-первых, кодировка файла. Если в файле встречается хоть что-то выходящее за пределы us-ascii, его нужно хранить в utf-8.


C>Во-вторых, в Windows для корректной работы со всем разнообразием символов нужно использовать Unicode, wide строки и wide потоки, потому что utf-8 нельзя установить в качестве мультибайтной кодировки, а все кодировки, которые можно — не имеют смысла.


C>И в-третьих, нужно вызывать setlocale(LC_ALL, ""), чтобы подтянуть локаль, установленную в настройках пользователя, и никогда не передавать названия конкретных локалей.


R>>Пробовал в начале функции main вставлять setlocale( 0, "" ) работает только на вывод текста, а введенное имя выводит абракадаброй. У Ш

илдта не нашел ответа на этот вопрос, хотя наши переводчики и перевели все слова в примерах его книги, но эти примеры выводят нормальный русский текст только в консоли linux.

C>А здесь сразу две проблемы. Первая — ты читаешь книгу по программированию в русском переводе. И вторая, более серьёзная — ты читаешь Шилдта.


Будьте добры подскажите кого почитать и приведите пожалуйста свою версию кода данной простой программы и по подробней по поводу кодировки!
Re: Ввод и вывод русского текста в консоли windows
От: MasterZiv СССР  
Дата: 14.08.11 21:12
Оценка: +2
On 08/13/2011 10:18 PM, Rediska555 wrote:
> #include <iostream>
> #include <string>
> using namespace std;
>
> int main()
> {
> string name;
> cout<< "Введите ваше имя:" << endl;
> cin>> name;
> cout<< "Привет" << name<< "!" << endl;
> system("PAUSE");
> return 0;
> }
>
>
> текст выводится абракадаброй.

chcp 1251

Это не в программе вашей должно быть, а выполнить надо в консоли перед
запуском в этой консоли вашей программы.

Пробовал в начале функции main вставлять
> setlocale( 0, "" ) работает только на вывод текста, а введенное имя выводит
> абракадаброй.




У Шилдта не нашел ответа на этот вопрос, хотя наши переводчики и
> перевели все слова в примерах его книги, но эти примеры выводят нормальный
> русский текст только в консоли linux.

Ну дык, ....

> Нашел еще вот такое решение с использованием широких строк wstring и потоков

> ввода wcin и вывода wcout:

> Вроде все работает, но не знаю на сколько это решение правильное и есть ли

> решение для обычных потоков ввода и вывода?

Правильное. Одно из правильных.


Тут всё дело в чём: в консоли Win32 вслед за консолями ещё Win16 и DOS-а
принято по умолчанию приметять т.н. OEM-кодировку, для русского это
кодировка cp866, т.н. альтернативная расширенная ASCI. ЧТобы в таком
случае в консоли что-то выводить правильно по-русски, надо выводить
именно в этой кодировке, для этого надо либо чтобы изначально все
тексты в программе были в этой кодировке (т.е. набирать всё в cp866),
но это достаточно сложно, потому как в Windows вы днём с огнём не
сыщите такой редактор, который позволял бы вам вводить текст в cp866,
либо перед выводом преобразовывать текст в cp866 из cp1251 вызовами
Win32 API, либо (что проще всего) переключить консоль в режим работы
в другой кодировке, в cp1251. Делается это вызовом комманды в консоли

chcp 1251

после этого весь вывод и ввод в этой консоли будет уже в cp1251 и всё
всегда будет ОК. (не забудьте только поменять ещё и шрифт, если у
вас в консоли выбран шрифт, не поддерживающий UNICODE, по умолчанию
в Win как раз такой и стоит, можно LucidaConsole выбрать).
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Ввод и вывод русского текста в консоли windows
От: Centaur Россия  
Дата: 15.08.11 06:42
Оценка:
Здравствуйте, Rediska555, Вы писали:

R>Будьте добры подскажите кого почитать


Где-то кто-то когда-то хвалил учебники Липмана. Впрочем, не думаю, что у него рассмотрен вопрос кодировок кириллицы.

Вообще ещё можно читать Джоэля Спольски, The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).

R>и приведите пожалуйста свою версию кода данной простой программы и по подробней по поводу кодировки!


Моя версия кода не будет содержать текстовых строк на русском языке. Кроме всего прочего, я не располагаю сейчас настроенной средой разработки под Windows, а непроверенный код постить не хочу. Но там будут встречаться слова wmain, wchar_t, std::wcout и std::wstring и не будут встречаться слова main, char, cout и string. (Ну, то есть если я не пишу кроссплатформенную программу, в каковом случае вместо всего вышесказанного будут использоваться тайпдефы и, возможно, макросы, в *nix-версии разворачивающиеся в char, а в виндовой в wchar_t.)
Re[4]: Ввод и вывод русского текста в консоли windows
От: MasterZiv СССР  
Дата: 15.08.11 07:09
Оценка:
On 15.08.2011 10:42, Centaur wrote:

Но там будут встречаться слова wmain,
> wchar_t, std::wcout и std::wstring и не будут встречаться слова main, char, cout
> и string. (Ну, то есть если я не пишу кроссплатформенную программу, в каковом
> случае вместо всего вышесказанного будут использоваться тайпдефы и, возможно,
> макросы, в *nix-версии разворачивающиеся в char, а в виндовой в wchar_t.)

С чего бы это ? В винде программа запросто может использовать MBCS и char*,
т.е. НЕ использовать т.н. UNICODE, т.е. не работать в UCS-2.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Ввод и вывод русского текста в консоли windows
От: Centaur Россия  
Дата: 15.08.11 07:35
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>С чего бы это ? В винде программа запросто может использовать MBCS и char*,

MZ>т.е. НЕ использовать т.н. UNICODE, т.е. не работать в UCS-2.

Виндовая программа не может без дополнительных существенных извращений использовать UTF-8 в качестве MBCS. А подавляющее большинство поддерживаемых MBCS-кодировок не покрывает юникод (даже базовую её плоскость).
Re[6]: Ввод и вывод русского текста в консоли windows
От: MasterZiv СССР  
Дата: 15.08.11 08:45
Оценка: -1
On 15.08.2011 11:35, Centaur wrote:

> Виндовая программа не может без дополнительных существенных извращений

> использовать UTF-8 в качестве MBCS.

Ну, может, как бы, но да, это редкость.

А подавляющее большинство поддерживаемых
> MBCS-кодировок не покрывает юникод (даже базовую её плоскость).

А на хрен он кому нужен ?
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Ввод и вывод русского текста в консоли windows
От: Rediska555  
Дата: 15.08.11 17:35
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Моя версия кода не будет содержать текстовых строк на русском языке. Кроме всего прочего, я не располагаю сейчас настроенной средой разработки под Windows, а непроверенный код постить не хочу. Но там будут встречаться слова wmain, wchar_t, std::wcout и std::wstring и не будут встречаться слова main, char, cout и string. (Ну, то есть если я не пишу кроссплатформенную программу, в каковом случае вместо всего вышесказанного будут использоваться тайпдефы и, возможно, макросы, в *nix-версии разворачивающиеся в char, а в виндовой в wchar_t.)


То есть примерно такой код, который я писал в первом посте:

#include <iostream>
#include <sstream>
#include <locale>
using namespace std;

int main()
{
    wcout.imbue(locale("rus_rus.866"));
    wcin.imbue(locale("rus_rus.866"));
    
    wstring name;
    
    wcout << L"Введите ваше имя: " << endl;
    wcin >> name;
    wcout << L"Привет " << name << L"!" << endl;
    
    system("PAUSE");
    return 0;
}

То есть использовать wide строки, символы и потоки и не париться, я правильно вас понял? Но вот как правильно пользоваться locale я не понял!!!
Re[2]: Ввод и вывод русского текста в консоли windows
От: Rediska555  
Дата: 15.08.11 18:08
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>chcp 1251


MZ>Это не в программе вашей должно быть, а выполнить надо в консоли перед

MZ>запуском в этой консоли вашей программы.

Легкие пути — не наш метод. Хочется работать с русскими символами средствами самой программы, а не сменой настроек в консоли. Хотя бы для того, что бы знать как это делается.

>> Нашел еще вот такое решение с использованием широких строк wstring и потоков

>> ввода wcin и вывода wcout:

>> Вроде все работает, но не знаю на сколько это решение правильное и есть ли

>> решение для обычных потоков ввода и вывода?

MZ>Правильное. Одно из правильных.


Только где почитать об этих wide строках( wstring ), символах( wchar_t ) и потоках ( wcin, wcout )??? У Шилдта об этом сказано вскользь, ну типа это где-то есть, а как это правильно юзать ни слова!!!


MZ>Тут всё дело в чём: в консоли Win32 вслед за консолями ещё Win16 и DOS-а

MZ>принято по умолчанию приметять т.н. OEM-кодировку, для русского это
MZ>кодировка cp866, т.н. альтернативная расширенная ASCI. ЧТобы в таком
MZ>случае в консоли что-то выводить правильно по-русски, надо выводить
MZ>именно в этой кодировке, для этого надо либо чтобы изначально все
MZ>тексты в программе были в этой кодировке (т.е. набирать всё в cp866),
MZ>но это достаточно сложно, потому как в Windows вы днём с огнём не
MZ>сыщите такой редактор, который позволял бы вам вводить текст в cp866,
MZ>либо перед выводом преобразовывать текст в cp866 из cp1251 вызовами
MZ>Win32 API, либо (что проще всего) переключить консоль в режим работы
MZ>в другой кодировке, в cp1251. Делается это вызовом комманды в консоли

MZ>chcp 1251


MZ>после этого весь вывод и ввод в этой консоли будет уже в cp1251 и всё

MZ>всегда будет ОК. (не забудьте только поменять ещё и шрифт, если у
MZ>вас в консоли выбран шрифт, не поддерживающий UNICODE, по умолчанию
MZ>в Win как раз такой и стоит, можно LucidaConsole выбрать).

В общем это все я понял, но пишут ведь люди проги на консоль с русским текстом не зависимо от настроек моей консоли. ХОЧУ ЗНАТЬ КАК!
Re[3]: Ввод и вывод русского текста в консоли windows
От: Alex_Avr Россия  
Дата: 16.08.11 05:29
Оценка:
Здравствуйте, Rediska555, Вы писали:

R>В общем это все я понял, но пишут ведь люди проги на консоль с русским текстом не зависимо от настроек моей консоли. ХОЧУ ЗНАТЬ КАК!


Ну например так:



   #include <locale>

   //...

   // Получаем текущую локаль CRT (если нужно потом восстановить)
   char* crtLocale = setlocale (LC_ALL, NULL); 
   
   // Устанавливаем текущую локаль CRT (если нужно использовать функции CRT, которым нужна локаль).
   char* newCrtLocale = setlocale (LC_ALL, ".ACP");// или то же самое setlocale (LC_ALL, ""); - кодовая страница ANSI по умолчанию.

   // также можно использовать вариант setlocale (LC_ALL, "ru_ru.1251"); или просто setlocale (LC_ALL, ".1251");

   std::locale currentLocale (newCrtLocale);
   wcout.imbue (currentLocale);

   // Восстанавливаем локаль CRT.
   setlocale (LC_ALL, crtLocale);
С уважением, Александр Авраменко.
Re[3]: Ввод и вывод русского текста в консоли windows
От: AleksandrN Россия  
Дата: 16.08.11 06:32
Оценка:
Здравствуйте, Rediska555, Вы писали:

R>В общем это все я понял, но пишут ведь люди проги на консоль с русским текстом не зависимо от настроек моей консоли. ХОЧУ ЗНАТЬ КАК!


Храни текст в Юникоде, а для вывода конвертируй в кодировку текущей локали.
Для конвертирования можно использовать WideCharToMultiByte, wtomb, wcstombs, либо прикрутить libiconv.
Re[3]: Ввод и вывод русского текста в консоли windows
От: MasterZiv СССР  
Дата: 16.08.11 12:32
Оценка:
On 15.08.2011 22:08, Rediska555 wrote:

> MZ>Это не в программе вашей должно быть, а выполнить надо в консоли перед

> MZ>запуском в этой консоли вашей программы.
>
> Легкие пути — не наш метод. Хочется работать с русскими символами средствами
> самой программы, а не сменой настроек в консоли.

Так ты и так это делаешь именно так. Просто твоя программа должна хранить
и выводить тексты в том виде, в котором работает консоль. Если твоя
программа работает в cp1251, надо консоль переключать в 1251.

Хотя бы для того, что бы знать
> как это делается.

Ну, уже сказали.

> Только где почитать об этих wide строках( wstring ), символах( wchar_t ) и

> потоках ( wcin, wcout )???

В стандарте языка С++. В книгах по С++.

> В общем это все я понял, но пишут ведь люди проги на консоль с русским текстом

> не зависимо от настроек моей консоли. ХОЧУ ЗНАТЬ КАК!

По-разному.
На самом деле гораздо важнее чтобы данные программы выводились правильно,
а не только текстовые литералы из неё.
Posted via RSDN NNTP Server 2.1 beta
Re: Ввод и вывод русского текста в консоли windows
От: shvellerr Россия  
Дата: 16.08.11 14:04
Оценка:
Здравствуйте, Rediska555

незнаю поможет ли версия для широких символов

#define UNICODE // сам незнаю но сказали "надо"
#include <iostream>
using namespace std;
int main()
    {
    setlocale (LC_CTYPE, ".866"); 
    wcout<< L"testФЫ"<< endl;
    wcout<<L"Ля-Ля-Ля-Ля"; //выводит нормально
    return 0;
    }



з.ы.
для вывода в файл подошла другая локация
setlocale (LC_CTYPE, "");
Re[2]: Ввод и вывод русского текста в консоли windows
От: Rediska555  
Дата: 16.08.11 17:57
Оценка:
Здравствуйте, shvellerr, Вы писали:
S>
S>#define UNICODE // сам незнаю но сказали "надо"
S>#include <iostream>
S>using namespace std;
S>int main()
S>    {
S>    setlocale (LC_CTYPE, ".866"); 
S>    wcout<< L"testФЫ"<< endl;
S>    wcout<<L"Ля-Ля-Ля-Ля"; //выводит нормально
S>    return 0;
S>    }
S>


Спасибо, примерно понял как использовать setlocale. У меня работает и ввод и вывод и без #define UNICODE вот такой код:
#include <iostream>
#include <string>
using namespace std;

int main()
{
    setlocale (LC_ALL, ".866");
    wstring name;
    wcout << L"Введите ваше имя: " << endl;
    wcin >> name;
    wcout << L"Привет " << name << L"!" << endl;
    return 0;
}

и такой:
#include <iostream>
#include <locale>
using namespace std;

int main()
{
    wcout.imbue(locale("rus_rus.866"));
    wcin.imbue(locale("rus_rus.866"));
    wstring name;
    wcout << L"Введите ваше имя: " << endl;
    wcin >> name;
    wcout << L"Привет " << name << L"!" << endl;
    return 0;
}

Не знаю, только, в чем принципиальное отличие обоих вариантов. Мне больше нравиться первый вариант!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.