C++. Проблемы с кодировкой кириллицы в массиве char
Столкнулся с проблемой. У меня раздвоенная кодировка.
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
Когда ввожу массив через консоль cin>>MassChar;
он принимает кодировку, где 1 символ хранится в 1-м элементе. Для слова "Привет" требуется массив размером минимум 7 элементов.
Когда я присваиваю значение в коде char MassChar[]="Привет";
, то для 1 символа требуется 2 элемента и при выводе одного элемента массива выводит М или О. Для слова "Привет" требуется массив размером минимум 13 элементов.
Как мне сделать, чтобы всё было как в первом случае (1 символ = 1 элемент). Сразу говорю: wchar_t и char16_t предлоть не надо.
Ответы (2 шт):
Длина вектора 13 символов т.к. каждый не-ASCII символ использует 2 байта, 6*2=12 (Привет), последний символ \0 нуль обозначающий конец строки. Можно сделать свой класс для данного случая и перегрузить оператор индексирования.
#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>
class Utf8String {
public:
Utf8String(const std::string& str) : data(str) {}
std::string operator[](size_t index) const {
return getCharacterAt(index);
}
size_t length() const {
return countCharacters();
}
private:
std::string data;
size_t countCharacters() const {
size_t count = 0;
for (size_t i = 0; i < data.size(); ) {
if ((data[i] & 0x80) == 0) {
i += 1;
}
else if ((data[i] & 0xE0) == 0xC0) {
i += 2;
}
else {
throw std::runtime_error("Неправильная последовательность UTF-8.");
}
count++;
}
return count;
}
std::string getCharacterAt(size_t index) const {
size_t count = 0;
for (size_t i = 0; i < data.size(); ) {
if ((data[i] & 0x80) == 0) {
if (count == index) return data.substr(i, 1);
i += 1;
}
else if ((data[i] & 0xE0) == 0xC0) {
if (count == index) return data.substr(i, 2);
i += 2;
}
else {
throw std::runtime_error("Неправильная последовательность UTF-8.");
}
count++;
}
throw std::out_of_range("Индекс вне границ вектора символов.");
}
};
int main() {
SetConsoleOutputCP(65001);
SetConsoleCP(65001);
const char* charArray = "Привет";
Utf8String MassChar(charArray);
std::cout << "Первый символ строки: " << MassChar[0] << std::endl;
std::cout << "Длина строки: " << MassChar.length() << std::endl;
std::cout << "Полная строка: " << MassChar[0] << MassChar[1] << MassChar[2] << MassChar[3] << MassChar[4] << MassChar[5] << std::endl;
char userInput[2 * 6 + 1];
std::cout << "Введите новую строку: ";
std::cin >> userInput;
Utf8String userUtf8Input(userInput);
std::cout << "Вы ввели: " << userUtf8Input[0] << userUtf8Input[1] << userUtf8Input[2] << std::endl;
return 0;
}
Вывод будет в консоли:
Первый символ строки: П
Длина строки: 6
Полная строка: Привет
Введите новую строку: Мир
Вы ввели: Мир
Кодировка файла 65001.
Если вам нужно просто присвоить значение "Привет", то можно сделать так char MassChar[7]{'П','р','и','в','е','т'};
, либо char MassChar[]{'П','р','и','в','е','т','\0'};
(если вы не указываете размер массива, то без \0 в конце у вас может вывести cout <<MassChar;
, что-то по типу "приветММММММММММММММММММММММММММММММРНZч"). 1 символ = 1 элемент.