LINUX.ORG.RU

Помогите новичку с вопросом по c++


0

1

Подскажите пожалуйста как в с++ заставить переменную типа char правильно понимать русские символы? Допустим в простом примере:

#include "iostream"
int main()
{
 char a = '0';
 std::cout << "Введите символ:\n"; 
 std::cin >> a;
 std::cout << "Вы ввели символ '" << a << "'\n" ;
 return 0;
}
При вводе «ф» программа выдает: Вы ввели символ '�'

Русская 'ф' занимает один байт (а именно столько может вместить char) далеко не во всех кодировках.

Попробуйте std::string вместо char.

kulti ★★
()

Ты пытаешься ввести двухбайтный unicode-символ в однобайтную переменную. Вводится только первый байт, он же потом и выводится. Попробуй тип wchar_t.

#include «iostream»

Кавычки лучше ставить, когда заголовок лежит в том же каталоге, что и исходник, иначе надо писать так:

#include <iostream>

gentoo_root ★★★★★
()

Как-то так:

#include <iostream>
#include <locale>

int main()
{
 std::locale l("ru_RU.utf8");
 std::locale::global(l);
 wchar_t a = L'0';
 std::wcout << L"Введите символ:\n";
 std::wcin >> a;
 std::wcout<<a;
 std::wcout << L"Вы ввели символ '" << a << L"'\n" ;
 return 0;
}
Waterlaz ★★★★★
()
Ответ на: комментарий от Waterlaz

А вот пример того, почему iostream - говно:

#include <iostream>
#include <locale>

int main()
{
 std::locale l("ru_RU.utf8");
 std::locale::global(l);
 wchar_t a = L'0';
 std::cout<<"trololo\n"; // этот cout ломает всё, хотя сам по себе вполне корректен
 std::wcout << "Введите символ:\n";
 std::wcin >> a;
 std::wcout<<a;
 std::wcout << L"Вы ввели символ '" << a << L"'\n" ;
 return 0;
}
[[/code]]

Waterlaz ★★★★★
()
Ответ на: комментарий от kulti

Так со string никаких проблем не возникает, просто string занимает несколько больше чем char, или нет (именно на примере 1-ого символа)?

hikkikamori
() автор топика
Ответ на: комментарий от hikkikamori

> Так со string никаких проблем не возникает, просто string занимает несколько больше чем char, или нет (именно на примере 1-ого символа)?

char — историческое обозначение байта в с/с++. на дворе уже третье тысячелетие, и длина символа давно переросла один байт (винду не считаем).

arsi ★★★★★
()
Ответ на: комментарий от Waterlaz

Спасибо принцип понял , только std::wcout<<a; тут кажется лишней. А разве Linux по умолчанию не utf8 использует?

 
hikkikamori@debian:~$ locale
LANG=ru_RU.utf8
LANGUAGE=
LC_CTYPE="ru_RU.utf8"
LC_NUMERIC="ru_RU.utf8"
LC_TIME="ru_RU.utf8"
LC_COLLATE="ru_RU.utf8"
LC_MONETARY="ru_RU.utf8"
LC_MESSAGES="ru_RU.utf8"
LC_PAPER="ru_RU.utf8"
LC_NAME="ru_RU.utf8"
LC_ADDRESS="ru_RU.utf8"
LC_TELEPHONE="ru_RU.utf8"
LC_MEASUREMENT="ru_RU.utf8"
LC_IDENTIFICATION="ru_RU.utf8"
LC_ALL=
и ещё в строчках std::locale l(«ru_RU.utf8»); std::locale::global(l); - l - маленькая, а допустим в wchar_t a = L'0'; - L - заглавная, почему?

hikkikamori
() автор топика
Ответ на: комментарий от hikkikamori

> т.е. char в с++ желательно обходить?

куда обходить? о_О

char — это байт (8+ бит, согласно стандарту). постоянно используется при работе с «сырыми» данными или с ascii/latin1. в других случаях лучше «обходить» и использовать singned char/unsigned char вместо непостоянного char, но это уже из другой оперы :)

arsi ★★★★★
()
Ответ на: комментарий от arsi

Да! Ты правильно меня понял :) спасибо за ответ, теперь есть от чего скакать дальше. Начал читать книгу Страуструпа «Принципы и практика использования C++», а там к сожалению про ввод и вывод русских символов ничего не написано, что кажется вполне логичным.

hikkikamori
() автор топика
Ответ на: комментарий от hikkikamori

Спасибо принцип понял , только std::wcout<<a; тут кажется лишней.

Да, лишнее.

А разве Linux по умолчанию не utf8 использует?

В большинстве дистрибутивов - да. Но это не имеет значение. В идеале, следовало бы прочитать значение переменной окружения LANG и использовать локаль оттуда:

#include <iostream>
#include <locale>
#include <stdlib.h>

int main()
{
    std::locale l(getenv("LANG"));
    std::locale::global(l);
    wchar_t a = L'0';
    std::wcout << L"Введите символ:\n";
    std::wcin >> a;
    std::wcout << L"Вы ввели символ '" << a << L"'\n" ;
    return 0;
}
[[/code]]

[quote]и ещё в строчках std::locale l("ru_RU.utf8"); std::locale::global(l); - l - маленькая, а допустим в wchar_t a = L'0'; - L - заглавная, почему?[br][/quote]маленькая l - объект locale. Большая L - способ записи "юникодных" констант строк и символов. 

"Hello" - строка char
L"Hello" - строка длинных символов (юникод).
Waterlaz ★★★★★
()
Ответ на: комментарий от r2d2

man std::wstring

а если хочется вменяемого сразу решения - man ICU или, если используешь Qt, - QString

shty ★★★★★
()
Ответ на: комментарий от Waterlaz

Waterlaz благодарю за ответ, вы с arsi мне очень помогли :)

hikkikamori
() автор топика
Ответ на: комментарий от Waterlaz

А вот пример того, почему iostream - говно:

Нет, это пример почему нужно читать документацию перед написание программ. Попробуй так:

#include <iostream>
#include <locale>
#include <clocale>

int main()
{
 std::setlocale(LC_ALL, "");
 std::locale l("");
 std::locale::global(l);
 std::cout.imbue(l); 
 std::cerr.imbue(l); 
 std::clog.imbue(l); 

 std::wcout.imbue(l); 
 std::wcerr.imbue(l); 
 std::wclog.imbue(l); 
 std::ios::sync_with_stdio(false);
 wchar_t a = L'0';
 std::cout<<"trololo"<<std::endl; // RTFM
 std::wcout << L"Введите символ:"<<std::endl;
 std::wcin >> a;
 std::wcout<<a;
 std::wcout << L"Вы ввели символ '" << a <<std::endl;
 return 0;
}

Eshkin_kot ★★
()
Ответ на: комментарий от Eshkin_kot

Прекрасный пример того, какое говно iostream.

Waterlaz ★★★★★
()
Введите символ:
а
Вы ввели символ 'а'

Введите символ:
ф
Вы ввели символ 'ф'

Введите символ:
ы
Вы ввели символ 'ы'

Введите символ:
ЪВы ввели символ 'Ъ'

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

нехорошо, ой как нехорошо светить своей КОИ-8

do0dlez ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.