Возникла та же проблема, что и в этой теме 2014 года - Регулярные выражения и кириллица Собстна, вопрос: за 4 года в плюсах не появился способ без доп. библиотек (типа boost) использовать регулярки без учета регистра в кириллице? Каким тогда образом решить эту проблему, не подключая буст?
Для любой простой 8-битной локали всё должно работать из-коробки, само собой, локаль должна быть корректно задана, терминал корректно настроен, а если в исходниках есть не-ASCII строки, то они должны быть правильно подготовлены.
// исходник в utf-8
#include <iostream>
#include <locale>
#include <regex>
#include <assert.h>
void printRxMatches (std::string line, std::regex rx) {
auto words_begin = std::sregex_iterator(line.begin(), line.end(), rx);
auto words_end = std::sregex_iterator();
if (words_begin!=words_end) {
auto wi = words_begin;
std::cout << wi->str();
for (++wi; wi != words_end; ++wi) {
std::cout << ' ' << wi->str();
}
} else {
std::cout << "<none>";
}
}
int main(int argc, char **argv) {
std::locale::global(std::locale(""));
assert(argc==2);
std::regex rxInput(argv[1],
std::regex_constants::collate | std::regex_constants::icase);
std::regex rxVowelsWords("\\b[аеёиоуыэюя]+\\b",
std::regex_constants::collate | std::regex_constants::icase);
for (std::string line; std::getline(std::cin, line); ) {
std::cout << line << " : " ;
std::cout << "InputMatches (";
printRxMatches (line, rxInput);
std::cout << ") ";
std::cout << "VowelWordsMatches (";
printRxMatches (line, rxVowelWords);
std::cout << ")" << std::endl;
}
return 0;
}
Сборка:
g++ -std=c++14 -fexec-charset=koi8-r -o reg-8bit reg-8bit.cpp
Запуск (множество iconv'ов симулируют изменение локали терминала на koi8):
$ echo "А я есьм строка. уууу! ЁЁ" | iconv -t KOI8-R | (LC_ALL=ru_RU.KOI8-R ./reg-8bit "$(echo "[есто]+" | iconv -t KOI8-R)" ) |iconv -f KOI8-R
А я есьм строка. уууу! ЁЁ : InputMatches (ес ст о) VowelsWordsMatches (А я уууу ЁЁ)
Для поддержки Мультибайтовых локалей (utf-8) единственным переносимым способом на чистом С++ будет использовать широкие символы. К сожалению в самом С++ нет адекватных методов для преобразования между обычной строкой в системной локали и широкой, поэтому придётся вручную доделывать костыли на основе функций из C99:
#include <iostream>
#include <locale>
#include <regex>
#include <wchar.h>
#include <assert.h>
void printRxMatches (std::wstring line, std::wregex rx) {
auto words_begin = std::wsregex_iterator(line.begin(), line.end(), rx);
auto words_end = std::wsregex_iterator();
if (words_begin!=words_end) {
auto wi = words_begin;
std::wcout << wi->str();
for (++wi; wi != words_end; ++wi) {
std::wcout << ' ' << wi->str();
}
} else {
std::wcout << "<none>";
}
}
std::wstring toWString(const char *str) {
std::wstring rv;
mbstate_t ps;
memset (&ps, 0, sizeof(ps));
size_t len = strlen(str);
rv.reserve(len);
while (len>0) {
wchar_t wch;
size_t transLen = mbrtowc(&wch, str, len, &ps);
if (transLen == (size_t)-1) {
throw std::runtime_error ("Incorrect multibyte sequence");
} else if (transLen == (size_t)-2) {
throw std::runtime_error ("Incomplete string");
} else {
rv.push_back(wch);
len -= transLen;
str += transLen;
}
}
rv.shrink_to_fit();
return rv;
}
int main(int argc, char **argv) {
std::locale::global(std::locale(""));
assert(argc==2);
std::wregex rxInput(toWString(argv[1]),
std::regex_constants::collate | std::regex_constants::icase);
std::wregex rxVowelWords(L"\\b[аеёиоуыэюя]+\\b",
std::regex_constants::collate | std::regex_constants::icase);
for (std::wstring line; std::getline(std::wcin, line); ) {
std::wcout << line << " : " ;
std::wcout << "InputMatches (";
printRxMatches (line, rxInput);
std::wcout << ") ";
std::wcout << L"VowelWordsMatches (";
printRxMatches (line, rxVowelWords);
std::wcout << L")" << std::endl;
}
return 0;
}
Из бонусов: * Это корректно работает для любой локали, и мультибайтовой и простой. * Потенциально переносима на любой компилятор поддерживающий C++11 и libc с поддержкой С99. * В UTF локалях работает даже эмодзи-безумие.
$ echo "А я есьм строка. уууу! ЁЁ" | iconv -t KOI8-R | (LC_ALL=ru_RU.KOI8-R ./reg-wide "$(echo "[а-ж]+" | iconv -t KOI8-R)" ) |iconv -f KOI8-R
А я есьм строка. уууу! ЁЁ : InputMatches (А е а ЁЁ) VowelWordsMatches (А я уууу ЁЁ)
$ echo "я
Виртуальный выделенный сервер (VDS) становится отличным выбором
VStudio не находит библиотеки, такие как conioh, time
Добрый деньИмеется нативный винапи поток, создаваемый функцией CreateThread(