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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 27, средняя оценка - 4.85
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
#1

Непонятка с кодировкой - C++

05.08.2011, 00:22. Просмотров 3778. Ответов 14
Метки нет (Все метки)

Есть следующий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "stdafx.h"
#include <iostream>
#include <string>
 
using std::wstring;
using std::getline;
using std::wcout;
using std::wcin;
using std::endl;
 
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale( LC_ALL, "russian_Russia.1251" );
    
    wstring str;
    wcout << L"Введите строку на русском: ";
    getline(wcin, str);
    wcout << L"Результат: " << str << endl;
 
    wcout << endl;
    system("PAUSE");
    return 0;
}
Вопрос: почему вместо введенного мной, в ответ на запрос, русскоязычного текста, программа выводит какую-то абракадабру? Как это исправить?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.08.2011, 00:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Непонятка с кодировкой (C++):

непонятка - C++
на парах нам учитель дает зделаную прогу как пример (скорей всего на студия-08) и в компютерном класе оно все работает (там тоже студия...

Непонятка с float - C++
float s = (123 * 100 / 360000); cout &lt;&lt; fixed &lt;&lt; setprecision(3) &lt;&lt; s; По идее, в консоли должно вывести &quot;0,034&quot;, но видимо с++ не...

fstream непонятка - C++
скажите,плз,правильно ли я открываю файл с fstream, и где должен лежать сам файл? #include &lt;fstream&gt; #include &lt;iostream&gt; #include...

Непонятка с указателями - C++
Как так что если указатель на int он покажет свой адрес а на char покажет символ свой. int * pointerInt = new int; char *...

Непонятка со скобками - C++
У меня такой вопрос: есть два куска кода, по сути одинаковых, в одном есть дополнительные скобки, которые по-моему не влияют ни на что, но...

Непонятка с постфиксами в VS 2013 - C++
#include &lt;iostream&gt; using namespace std; int main() { int a = 10; a = a++ + a++; cout &lt;&lt; a &lt;&lt; endl; system(&quot;pause&quot;); ...

14
Avazart
Эксперт С++
7247 / 5419 / 297
Регистрация: 10.12.2010
Сообщений: 24,055
Записей в блоге: 17
05.08.2011, 00:37 #2
Я решаю эту проблему с помощью ф-ции:

C++
1
2
3
4
5
6
7
8
9
10
11
12
string rus(std::string strIn)  //Русский язык
{
    string strOut=strIn;
    for(string::size_type i=0;i<strOut.length();++i)
    {
        if(strOut[i]>='А'&& strOut[i]<='п' )
            strOut[i]-=64;
        if(strOut[i]>='р'&& strOut[i]<='я' )
            strOut[i]-=16;
    }
    return strOut;
}
0
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 00:50  [ТС] #3
Avazart
К сожалению, для wstring эта функция работает не корректно...
Для string функция тоже работает не корректно. Начинает работать только если закомментить строку setlocale( LC_ALL, "russian_Russia.1251" ), но это не есть гуд...

P.S: У меня VS2010 Pro
0
OstapBender
584 / 523 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
05.08.2011, 03:00 #4
попробуй убери нафиг
setlocale( LC_ALL, "russian_Russia.1251" );

у меня этот код отрабатывает
C++
1
2
3
    std::wstring c;
    std::getline(std::wcin,c);
    std::wcout << c;
0
silentnuke
Android Programmer
139 / 140 / 5
Регистрация: 08.12.2010
Сообщений: 421
05.08.2011, 03:55 #5
Цитата Сообщение от Oleg_SK Посмотреть сообщение
Вопрос: почему вместо введенного мной, в ответ на запрос, русскоязычного текста, программа выводит какую-то абракадабру? Как это исправить?
Потому что строка записывается в кодировки Oem(старая досовская). А когда выводите, используется кодировка Ansi.
При работе со строками например типа char, проблема решается использование функции OemToAnsi, как её применить к wstring не знаю)
0
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 06:53  [ТС] #6
OstapBender
У меня предложенный вариант тоже нормально отрабатывает, но тут затык в том, что стоит в этот код добавить вывод в консоль текста заданного в программе (например: wcout << L"Введите строку на русском: ") и работа программы сразу становится некорректной... Чтобы это исправить приходится вставлять в код строку: setlocale( LC_ALL, "russian_Russia.1251" ), но после ее вставки начинается безобразие с выводом текста полученного от getline... Хочу попробовать похимичить с командой setlocale. Подскажите, плиз, как отменить действие команды setlocale( LC_ALL, "russian_Russia.1251" ), чтобы кодировка вернулась на дефолтную?

Добавлено через 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
#include "stdafx.h"
#include <iostream>
#include <string>
#include <windows.h>
 
using std::wstring;
using std::getline;
using std::wcout;
using std::wcin;
using std::endl;
 
int _tmain(int argc, _TCHAR* argv[])
{
    wstring c;
 
        setlocale( LC_ALL, "russian_Russia.1251" );
    wcout << L"Тест_1" << endl;
 
    setlocale(LC_ALL, "russian_Russia.866");
    getline(wcin,c);
    wcout << c << endl;
 
    setlocale( LC_ALL, "russian_Russia.1251" );
    wcout << L"Тест_2" << endl;
 
    wcout << endl;
    system("PAUSE");
    return 0;
}
То есть, перед выводом в консоль заданного в программе текста нужно давать команду: setlocale( LC_ALL, "russian_Russia.1251" ), а перед вызовом getline давать команду: setlocale(LC_ALL, "russian_Russia.866")...

Добавлено через 24 минуты
Осталось еще разобраться: как перекодировать строки из 866 кодировки в 1251 или обратно для типа wstring, чтобы можно было сравнивать строки введенные через getline со строками заданными в тексте программы... Может быть кто-нибудь знает, как это можно сделать?

Добавлено через 19 минут
Кажись опять сам разобрался. Вроде бы для сравнения строк не нужно приводить их к одной кодировке, т.к. метод compare класса wstring сам прекрасно с этим справляется...
0
kazak
3050 / 2371 / 160
Регистрация: 11.03.2009
Сообщений: 5,436
Завершенные тесты: 1
05.08.2011, 07:02 #7
Можно сменить кодовую страницу для консоли
SetConsoleCP и SetConsoleOutputCP.
0
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 07:17  [ТС] #8
Цитата Сообщение от kazak Посмотреть сообщение
Можно сменить кодовую страницу для консоли
SetConsoleCP и SetConsoleOutputCP.
В самом начале попробовал поиграться с этими командами (заменив ими команду: setlocale( LC_ALL, "russian_Russia.1251" )), но что-то у меня ничего не вышло... После выполнения строк:
C++
1
2
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
Мало того, что русскоязычный текст заданный в программе перестал выводиться в консоли, так еще и русские буквы убежали с привычных клавиш и разбежались по клавиатуре... Я что-то не так сделал?

З.Ы: Проблема обсуждаемая в этом топике уже решена. Спрашиваю просто из любопытства...
0
silentnuke
Android Programmer
139 / 140 / 5
Регистрация: 08.12.2010
Сообщений: 421
05.08.2011, 07:36 #9
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
#include <iostream>
#include <string>
 
std::string narrow(std::wstring const & wstr, std::locale const & loc, char def = '?')
{
    if (wstr.empty())
        return std::string();
 
    std::string ret;
    ret.resize(wstr.length());
 
    std::use_facet<std::ctype<wchar_t> >(loc).narrow(&wstr[0], &wstr[0] + wstr.length(), '?', &ret[0]);
 
    return ret;
}
 
std::wstring widen(std::string const & str, std::locale const & loc)
{
    if (str.empty())
        return std::wstring();
 
    std::wstring ret;
    ret.resize(str.length());
 
    std::use_facet<std::ctype<wchar_t> >(loc).widen(&str[0], &str[0] + str.length(), &ret[0]);
 
    return ret;
}
 
std::string to1251(std::string const & cp866)
{
    std::string ret;
    ret.reserve(cp866.length());
 
    for (std::size_t i = 0, e = cp866.length(); i < e; ++i)
    {
        wchar_t wide = std::use_facet<std::ctype<wchar_t> >(std::locale(".866")).widen(cp866[i]);
        ret.push_back(std::use_facet<std::ctype<wchar_t> >(std::locale(".1251")).narrow(wide, '?'));
    }
 
    return ret;
}
 
int main()
{
    setlocale(LC_ALL,"rus");
    std::cout<<"Введите строку\n";
    std::string cp866;
    std::cin>>cp866; // Кодировка в консоли — CP866
    std::string cp1251 = to1251(cp866); // Преобразуем в CP1251
    std::cout<<cp1251;
    return 0;
}
как вариант=)
1
kazak
3050 / 2371 / 160
Регистрация: 11.03.2009
Сообщений: 5,436
Завершенные тесты: 1
05.08.2011, 08:07 #10
Oleg_SK, а шрифт на Lucida Console меняли?
0
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 08:19  [ТС] #11
silentnuke
Спасибо. Интересный код, активно использующий средства STL. А можете показать аналогичный код, но для типа wstring, а не string? То есть, чтобы функция to1251 выглядела бы так:
std::wstring to1251(std::wstring const & cp866)

P.S: Мне было бы и самому интересно модифицировать ваш пример, но, к сожалению, пока мои знания STL близки к нулю...

Добавлено через 1 минуту
kazak
Нет, не менял... А как это можно сделать и какой шрифт стоит по дефолту?
0
kazak
3050 / 2371 / 160
Регистрация: 11.03.2009
Сообщений: 5,436
Завершенные тесты: 1
05.08.2011, 08:38 #12
По дефолту стоит точечный шрифт, изменить можно клацнув правой кнопкой по заголовку консоли, и выбрав Свойства.
0
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 09:08  [ТС] #13
kazak
Поменял шрифт, и это дало то, что русские буквы вернулись на положенные клавиши и русский текст введенный через getline стал выводиться в консоль корректно. Русский текст, заданный в программе, по прежнему не выводится (даже крякозябликов нет) и если попытаться его выводить программа начинает работать не корректно...
0
Avazart
Эксперт С++
7247 / 5419 / 297
Регистрация: 10.12.2010
Сообщений: 24,055
Записей в блоге: 17
05.08.2011, 13:41 #14
Странно у меня ф-ция вроде нормально работает, брал с рабочего проекта
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
07.11.2012, 11:12 #15
Цитата Сообщение от OstapBender Посмотреть сообщение
std::wcout << c;
У меня этот поток чего то вообще не виден.
0
07.11.2012, 11:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.11.2012, 11:12
Привет! Вот еще темы с ответами:

непонятка в связном списке - C++
есть 2 конструктора - list(const str&amp;) и list() если в main использую 1ый конструктор, то всё работает, если 2ой - ошибка, всякие там...

Непонятка с минусами в double - C++
такая шляпа вот, почему-то, если if(9.8 - 7.6 == 2.2) cout &lt;&lt; &quot;TRUE&quot; &lt;&lt; endl; else cout &lt;&lt; &quot;FALSE&quot; &lt;&lt; endl; выводит FALSE,...

Непонятка с заголовочными файлами - C++
game.h #ifndef _GAME_H_ #define _GAME_H_ #include &lt;gl\gl.h&gt; #include &lt;gl\glu.h&gt; #pragma comment (lib,...

Непонятка с функцией(ошибка в коде) - C++
Необходимо вычислить значения нескольких сумм с помощью функций в следующей функции: y=a+4*sum J=2, N+1(3*J^2+J+2)/4+3*sum J=1,N(2*J+3);J...


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

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

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