0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 24

Русский язык в Linux, регистр

09.09.2016, 01:30. Показов 7341. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, пытаюсь запустить код, работавший в Visual Studio на Debian, IDE Codeblocks. Возникла проблема с переводом русских слов в нижний регистр (строка 34). Латиницу переводит, но русский не принимает. Помогите, пожалуйста, заранее спасибо.
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
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <cctype>
#include <algorithm>
#include <time.h>
#include <regex>
using namespace std;
 
struct Word
{
    std::string word = "";
    int wordfreq = 0;
};
 
int main(int argc, _TCHAR* argv[])
{
    
    setlocale(LC_ALL, "Russian");
    
    cin >> NewFile;
 
    map <string, int> words; // контейнер для входного текста
    ifstream in;
    in.open(NewFile);// файл с входным текстом
    string word;
    int wCount = 0; // счетчик слов во входном тексте
 
    while (in >> word) // удаляем не важные символы из текста
    {
        setlocale(LC_ALL, "");
        std::transform(word.begin(), word.end(), word.begin(), tolower);// перевод в нижний регистр
        for (int i = 0; i<word.size(); i++)
        {
            if (word[i] == '.' || word[i] == ',' || word[i] == '(' || word[i] == ')' || word[i] == '[' || word[i] == ']' || word[i] == '!' || word[i] == '?' ||
                word[i] == '"' || word[i] == ';' || word[i] == ':' || word[i] == '#' || word[i] == '$' || word[i] == '%' || word[i] == '^' || word[i] == '&' ||
                word[i] == '*' || word[i] == '*' || word[i] == '+' || word[i] == '-' || word[i] == '“' || word[i] == '/' || word[i] == '”' || word[i] == '„' ||
                word[i] == '_' || word[i] == '—' || word[i] == '«' || word[i] == '»' || word[i] == '…' || word[i] == '*' || word[i] == '–') {
                word.erase(word.begin() + i);
                i--;
            }
        }
 
        if (!word.empty() && word != "--")
            words[word]++;
        wCount++;
    }
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.09.2016, 01:30
Ответы с готовыми решениями:

Почему Linux понимает русский язык, и как разучить его это делать?
Здравствуйте! Зная, что в Linux принята неравномерная кодировка UTF-8, я удивлялся, как считай однобайтовый тип char позволяет...

Xcode , С++ и русский язык: как вывести в файл русский текст без сбитой кодировки?
Как сделать так, чтобы после некоторых манипуляций в файл выводился русский текст без сбитой кодировки?

Английский язык для окна ввода пароля, русский язык для самой системы
собственно, сабж. у меня пароль на английском языке, при включении компьютера по умолчанию стоит русский, соответственно надо переключать...

15
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.09.2016, 01:33
особенное внимание обратите на наличие локали
http://www.cplusplus.com/reference/locale/tolower/
0
0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 24
09.09.2016, 01:56  [ТС]
hoggy, Сделал по примеру, русский текст не тронут, но теперь английский поплыл. В верхний регистр переводит.
0
Модератор
Эксперт С++
 Аватар для zss
13759 / 10954 / 6487
Регистрация: 18.12.2011
Сообщений: 29,212
09.09.2016, 07:31
Ну так меняйте локаль на время перевода английского текста обратно.
0
0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 24
09.09.2016, 13:12  [ТС]
В любом случае регистр русских слов не смог поменять, подскажите, пожалуйста, как именно мой код нужно изменить. С удовольствием выслушаю все возможные варианты.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
09.09.2016, 14:54
Цитата Сообщение от asdawvwv Посмотреть сообщение
Возникла проблема с переводом русских слов в нижний регистр (строка 34). Латиницу переводит, но русский не принимает.
У пингвинов по умолчанию utf-8, tolower в него не умеет и уметь не будет даже после плясок с бубном вокруг локалей (потому что под обнобайтовые кодировки). Самый простой выход - переделать файл в utf-16/utf-32 и читать в wstring. Плюс, кинуть в начало программы std::setlocale(LC_ALL,"Что ни будь из выдачи locale -a, только не C/POSIX");.
1
0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 24
09.09.2016, 15:39  [ТС]
Renji, Перегнал в utf16 входной файл. Перелопатил программу под wstring, вылетает с ошибкой invalyde byte sequence in file. Локаль воткнул в начале utf8. Кроме нее только с и посикс.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
09.09.2016, 16:16
Цитата Сообщение от asdawvwv Посмотреть сообщение
Renji, Перегнал в utf16 входной файл. Перелопатил программу под wstring, вылетает с ошибкой invalyde byte sequence in file.
Хм, поэкспериментировал у себя, ерунда какая-то. Вроде бы пишу std::wifstream, но оно все равно расценивает файл как utf-8. При этом читая из него только английский текст, несмотря на вроде бы верно выставленную локаль. Ну, в общем, файл в utf-32 то я открыл, но к стыду своему, только через костыль.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include<fstream>
using namespace std;
 
int main()
{
    setlocale(LC_ALL,"C.UTF-8");
    std::ifstream stream("test.txt");
    //получаем размер файла
    stream.seekg(0,std::ios_base::end);
    size_t size=stream.tellg();
    stream.seekg(0);
 
    //и низкоуровневым чтением его, чтоб точно ничего не сбойнуло
    std::wstring str(size/sizeof(wchar_t),' ');
    stream.read((char*)str.data(),size);
 
    //выводим что прочитали
    wcout<<str;
    return 0;
}
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
09.09.2016, 16:18
Цитата Сообщение от asdawvwv Посмотреть сообщение
invalyde byte sequence in file
Задайте локаль для wifstream.
C++
1
in.imbue(std::locale(""));
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
09.09.2016, 16:19
Цитата Сообщение от Nosey Посмотреть сообщение
Задайте локаль для wifstream.
Хм, а с imbue на utf-8 файле действительно работает.
0
0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 24
09.09.2016, 17:09  [ТС]
Renji, Ваш код возврашает ноль на любом файле( в консоль ничего не выводит. С wifstream ругается на строку 16.
УПД. В строке 16 поменял чар на wchar_t. Segmentation fault выдает. Файл утф8
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
09.09.2016, 17:10
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от Renji Посмотреть сообщение
Хм, а с imbue на utf-8 файле действительно работает.
Все потому что std::setlocale - это сишная локаль, она затрагивает гору свободных функций, а вот на стримы не влияет.
Если желаете общую плюсовую локаль выставить, то std::local::global готов к работе, ну либо *.imbue(..).
0
923 / 639 / 198
Регистрация: 08.09.2013
Сообщений: 1,693
09.09.2016, 20:20
Цитата Сообщение от asdawvwv Посмотреть сообщение
В любом случае регистр русских слов не смог поменять, подскажите, пожалуйста, как именно мой код нужно изменить. С удовольствием выслушаю все возможные варианты.
Например, функцией из glib
C++
1
g_utf8_strdown (word.c_str(), -1)
Если известно, что файл в utf-8, то локаль имеет значение, если вы денежные единицы или форматы даты будете менять в зависимости от пользовательских настроек.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.09.2016, 22:20
Цитата Сообщение от asdawvwv Посмотреть сообщение
Сделал по примеру, русский текст не тронут, но теперь английский поплыл. В верхний регистр переводит.
если вкратце: жизнь - боль и страдание.
с++ не осилил локали.

единственное, что стабильно работает - это английский текст (сишная локаль).
национальные локали либо не работают вообще, либо глючат.

если поприседать вокруг локалей, то можно родить свою собственную,
которая сможет сделать вам хорошо.

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

исходя из этого можно придти к выводу,
что проще использовать специфическое апи системы,
либо толстые специализированные библиотеки.


что касается стандартных средств: максимум, что тут можно сделать:
родить собственную локаль, которая сможет корректно работать только с нормализированным текстом.
то есть, с текстом, в котором национальные символы можно представить одной буквой.

Цитата Сообщение от Nosey Посмотреть сообщение
а вот на стримы не влияет.
влияет.
стримам так же можно посетить локаль.

например, грузить файл в утф8 кодировке.


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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#pragma once
 
#ifdef dUSING_PRECOMPILED_HEADER
    #ifndef _STDEXCEPT_
        #error #include <stdexcept> first
    #endif
 
    #ifndef _FSTREAM_
        #error #include <fstream> first
    #endif
 
    #ifndef _CODECVT_
        #error #include <codecvt> first
    #endif
 
    #ifndef _STRING_
        #error #include <string> first
    #endif
#else
    #include <stdexcept>
    #include <fstream>
    #include <codecvt>
    #include <cassert>
    #include <string>
#endif
 
namespace fs{
namespace stream{
 
// ===================================================================================================
// ===================================================================================================
namespace detail
{
    template<class ch> 
    std::basic_ofstream<ch> 
    open__(const std::basic_string<ch>& filename, const int flag, const bool with_BOM)
    {
        std::basic_ofstream<ch> stream_;
 
        #ifdef _MSC_VER
            stream_.open(filename, std::ios::out | flag, _SH_DENYRW);
        #else
            stream.open(filename, std::ios::out | flag);
        #endif
 
        stream_.imbue(get_utf8_locale(with_BOM));
        
        if(!stream_)
            throw std::runtime_error("can`t open file");
 
        return stream_;
    }
 
    inline std::locale get_utf8_locale(const bool with_bom)
    {
        typedef std::codecvt_utf8<wchar_t, 0x10ffff, std::generate_header> 
            bom_codec_t;
        typedef std::codecvt_utf8<wchar_t> 
            no_bom_codec_t;
 
        return with_bom?
            std::locale(std::locale::empty(), new bom_codec_t):
            std::locale(std::locale::empty(), new no_bom_codec_t);
    }
 
    template<class Container, class Value> 
    void append__(Container& cont, Value&& val)
    {
        
        #ifdef _MSC_VER
        __if_exists(Container::emplace_back) 
            { cont.emplace_back( std::forward<Value>(val) );       return; }
 
        __if_exists(Container::push_back)    
            { cont.push_back( std::forward<Value>(val) )   ;       return; }
 
        __if_exists(Container::insert)       
            { cont.insert( cont.end(), std::forward<Value>(val) ); return; }
        #else
        TODO: not implemented...
        #endif
    }
 
}// namespace detail
// ===================================================================================================
// ===================================================================================================
    
// --- пересоздает файл заного
template<class ch> 
std::basic_ofstream<ch>
create(const std::basic_string<ch>& filename, const bool with_BOM)
{
    return detail::open__(filename, std::ios::trunc, with_BOM);
}
// ===================================================================================================
    
// --- открывает для добавления
template<class ch> 
std::basic_ofstream<ch>
append(const std::basic_string<ch>& filename, const bool with_BOM)
{
    return detail::open__(filename, std::ios::app, with_BOM);
}
// ===================================================================================================
    
// --- открывает для чтения    
template<class ch>
std::basic_ifstream<ch>
load(const std::basic_string<ch>& filename, const bool with_BOM)
{
    std::basic_ifstream<ch> stream_;
 
    stream_.open(filename, std::ios::in);
    stream_.imbue(detail::get_utf8_locale(with_BOM));
    
    if(!stream_)
        throw std::runtime_error("can`t open file");
    
    return stream_;
}
// ===================================================================================================
    
// --- хэлпер для загрузки всего файла построчно
template<class ch, class container> 
void load_lines(const std::basic_string<ch>& filename, container& cont, const bool with_BOM)
{
    auto in = load(filename, with_BOM);
    std::basic_string<ch> line;
    while (std::getline(in, line))
        detail::append__(cont, line);
}
    
template<class ch, class container> 
void load_lines(const ch* filename, container& cont, const bool with_BOM)
{
    assert(filename);
    load_lines(std::basic_string<ch>(filename), cont, with_BOM);
}
    
// ===================================================================================================
    
// --- хэлпер для загрузки отдельных слов 
template<class ch, class container> 
void load_words(const std::basic_string<ch>& filename, container& cont, const bool with_BOM)
{
    auto in = load(filename, with_BOM);
    std::basic_string<ch> word;
    while(in >> word)
        detail::append__(cont, word);
}
    
template<class ch, class container> 
void load_words(const ch* filename, container& cont, const bool with_BOM)
{
    assert(filename);
    load_words(std::basic_string<ch>(filename),cont, with_BOM);
}
    
// ===================================================================================================
 
} //namespace stream
} //namespace fs
 
 
#include <iostream>
#include <vector>
#include <set>
 
int main()
{
    setlocale(LC_ALL, "");
    
    std::cout << "Hello, world!\n";
    
    try
    {
        // --- загружаем весь файл построчно в указанный контейнер
        std::vector<std::wstring> mylines;
        fs::stream::load_lines(L"sample-utf8.txt", mylines, true);
    
        // --- загружаем все слова из файла в указанный контейнер
        std::set<std::wstring> mywords;
        fs::stream::load_words(L"sample-utf8.txt", mywords, true);
    }
    catch(const std::exception& e)
    {
        std::cout << e.what()<<std::endl;
    }
}
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
09.09.2016, 23:00
Цитата Сообщение от hoggy Посмотреть сообщение
если вкратце: жизнь - боль и страдание.
с++ не осилил локали.
Главные слова на деревне.
asdawvwv, также если вкратце, если вы пишите что-то серьезное, то используйте следующее:
Все файлы ресурсов в utf8. Все строки в программулине в u32string(который UCS4, UTF-32), тогда у вас возможно(не все языки, как отметил hoggy) будут работать функции типа tolower..., а потом по нужде, если что, переедите на либу посерьезней.
Прошу заметить, что при кроссплатфрме на wchar не стоит надеяться, только char32(его невозможно сломать реализацией )

Цитата Сообщение от hoggy Посмотреть сообщение
влияет.
стримам так же можно посетить локаль.
например, грузить файл в утф8 кодировке.
Ну-ка ну-ка покажите, как через std::setlocale задать дефолтный codecvt для файловых стримов . Ну а вообще, да, погорячился я с заявлением. std::setlocale задает сишную локаль для глобальных функций, которые уже юзаются фасетами плюсовой локали, но проблема ТС'а в codecvt, который сишной локалью не меняется.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.09.2016, 23:17
Цитата Сообщение от Nosey Посмотреть сообщение
Ну-ка ну-ка покажите, как через std::setlocale задать дефолтный codecvt для файловых стримов
да дело же не в std::setlocale,
а в том, что стриму можно посетить локаль.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.09.2016, 23:17
Помогаю со студенческими работами здесь

Русский язык
Всем добрый день! Как исправить проблему того, что в консоле вместо русского языка отображаются квадратики.

Русский язык в C++
Как в C++ консоли подключить русский язык желательной setLoceta(Rus) такой функцией, у меня не получилось её использваоть

Русский язык
char szNonColorEmbeddedMsg; int iNonColorEmbeddedMsgLen = 0; for (size_t pos = 0; pos &lt; strlen(szMsg) &amp;&amp; szMsg != '\0'; pos++) ...

Русский язык
Здравствуйте! Я практикуюсь в создании веб сайтов. Когда я писал сайт и тестировал его на локальном сервере, то всё работало хорошо, но...

русский язык
Вопрос один, как поставить русский язык ODude Ecard . Объясняют ...


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

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

Новые блоги и статьи
CQRS (Command Query Responsibility Segregation) на Java
Javaican 12.05.2025
CQRS — Command Query Responsibility Segregation, или разделение ответственности команд и запросов. Суть этого архитектурного паттерна проста: операции чтения данных (запросы) отделяются от операций. . .
Шаблоны и приёмы реализации DDD на C#
stackOverflow 12.05.2025
Когда я впервые погрузился в мир Domain-Driven Design, мне показалось, что это очередная модная методология, которая скоро канет в лету. Однако годы практики убедили меня в обратном. DDD — не просто. . .
Исследование рантаймов контейнеров Docker, containerd и rkt
Mr. Docker 11.05.2025
Когда мы говорим о контейнерных рантаймах, мы обсуждаем программные компоненты, отвечающие за исполнение контейнеризованных приложений. Это тот слой, который берет образ контейнера и превращает его в. . .
Micronaut и GraalVM - будущее микросервисов на Java?
Javaican 11.05.2025
Облачные вычисления безжалостно обнажили ахиллесову пяту Java — прожорливость к ресурсам и медлительный старт приложений. Традиционные фреймворки, годами радовавшие корпоративных разработчиков своей. . .
Инфраструктура как код на C#
stackOverflow 11.05.2025
IaC — это управление и развертывание инфраструктуры через машиночитаемые файлы определений, а не через физическую настройку оборудования или интерактивные инструменты. Представьте: все ваши серверы,. . .
Инъекция зависимостей в ASP.NET Core - Практический подход
UnmanagedCoder 11.05.2025
Инъекция зависимостей (Dependency Injection, DI) — это техника программирования, которая кардинально меняет подход к управлению зависимостями в приложениях. Представьте модульный дом, где каждая. . .
Битва за скорость: может ли Java догнать Rust и C++?
Javaican 11.05.2025
Java, с её мантрой "напиши один раз, запускай где угодно", десятилетиями остаётся в тени своих "быстрых" собратьев, когда речь заходит о сырой вычислительной мощи. Rust и C++ традиционно занимают. . .
Упрощение разработки облачной инфраструктуры с Golang
golander 11.05.2025
Причины популярности Go в облачной инфраструктуре просты и одновременно глубоки. Прежде всего — поразительная конкурентность, реализованная через горутины, которые дешевле традиционных потоков в. . .
Создание конвейеров данных ETL с помощью Pandas
AI_Generated 10.05.2025
Помню свой первый опыт работы с большим датасетом — это была катастрофа из неотформатированных CSV-файлов, странных значений NULL и дубликатов, от которых ехала крыша. Тогда я потратил три дня на. . .
C++ и OpenCV - Гайд по продвинутому компьютерному зрению
bytestream 10.05.2025
Компьютерное зрение — одна из тех технологий, которые буквально меняют мир на наших глазах. Если оглянуться на несколько лет назад, то сложно представить, что алгоритмы смогут не просто распознавать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru