Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 27, средняя оценка - 4.85
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 00:22     Непонятка с кодировкой #1
Есть следующий код:
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;
}
Вопрос: почему вместо введенного мной, в ответ на запрос, русскоязычного текста, программа выводит какую-то абракадабру? Как это исправить?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.08.2011, 00:22     Непонятка с кодировкой
Посмотрите здесь:

fstream непонятка C++
непонятка с минусами в double C++
C++ непонятка
Непонятка с заголовочными файлами C++
C++ Непонятка со скобками
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 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;
}
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
OstapBender
 Аватар для OstapBender
581 / 519 / 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;
silentnuke
Android Programmer
137 / 138 / 5
Регистрация: 08.12.2010
Сообщений: 421
05.08.2011, 03:55     Непонятка с кодировкой #5
Цитата Сообщение от Oleg_SK Посмотреть сообщение
Вопрос: почему вместо введенного мной, в ответ на запрос, русскоязычного текста, программа выводит какую-то абракадабру? Как это исправить?
Потому что строка записывается в кодировки Oem(старая досовская). А когда выводите, используется кодировка Ansi.
При работе со строками например типа char, проблема решается использование функции OemToAnsi, как её применить к wstring не знаю)
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 сам прекрасно с этим справляется...
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
05.08.2011, 07:02     Непонятка с кодировкой #7
Можно сменить кодовую страницу для консоли
SetConsoleCP и SetConsoleOutputCP.
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);
Мало того, что русскоязычный текст заданный в программе перестал выводиться в консоли, так еще и русские буквы убежали с привычных клавиш и разбежались по клавиатуре... Я что-то не так сделал?

З.Ы: Проблема обсуждаемая в этом топике уже решена. Спрашиваю просто из любопытства...
silentnuke
Android Programmer
137 / 138 / 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;
}
как вариант=)
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
05.08.2011, 08:07     Непонятка с кодировкой #10
Oleg_SK, а шрифт на Lucida Console меняли?
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
Нет, не менял... А как это можно сделать и какой шрифт стоит по дефолту?
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
05.08.2011, 08:38     Непонятка с кодировкой #12
По дефолту стоит точечный шрифт, изменить можно клацнув правой кнопкой по заголовку консоли, и выбрав Свойства.
Oleg_SK
5 / 5 / 2
Регистрация: 15.09.2010
Сообщений: 25
05.08.2011, 09:08  [ТС]     Непонятка с кодировкой #13
kazak
Поменял шрифт, и это дало то, что русские буквы вернулись на положенные клавиши и русский текст введенный через getline стал выводиться в консоль корректно. Русский текст, заданный в программе, по прежнему не выводится (даже крякозябликов нет) и если попытаться его выводить программа начинает работать не корректно...
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
05.08.2011, 13:41     Непонятка с кодировкой #14
Странно у меня ф-ция вроде нормально работает, брал с рабочего проекта
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.11.2012, 11:12     Непонятка с кодировкой
Еще ссылки по теме:

C++ Непонятка с указателями
непонятка в связном списке C++
Непонятка с float C++

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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
07.11.2012, 11:12     Непонятка с кодировкой #15
Цитата Сообщение от OstapBender Посмотреть сообщение
std::wcout << c;
У меня этот поток чего то вообще не виден.
Yandex
Объявления
07.11.2012, 11:12     Непонятка с кодировкой
Ответ Создать тему
Опции темы

Текущее время: 02:57. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru