Неправильно отображаются символы кириллицы в richTextBox, Windows Forms, C++
Создаю программу на Windows Forms
по взлому шифра Цезаря на C++. В проекте определены два класса: Decrypt
и RussianDecrypt
, которые возвращают строку std::wstring
. Пользователь вводит текст в richTextBox
, и по нажатии на кнопку buttonCrack
на другие richTextBox
выводится расшифрованный текст (для английского и русского языков). При работе с английским языком проблем не возникает, всё работает корректно, но если ввести текст на русском, то при нажатии на кнопку вместо символов кириллицы выводятся непонятные символы.
RussianDecrypt.h
#pragma once
#include <string>
#include <vector>
class RussianDecrypt {
public:
static std::wstring CaesarCypherCrack(std::wstring& inputText);
private:
static double CalculateD(const std::vector<double>& p, const std::vector<double>& f, int s, const std::wstring& alphabet);
};
RussianDecrypt.cpp
#include "RussianDecrypt.h"
#include <cmath>
#include <algorithm>
#include <cctype>
double RussianDecrypt::CalculateD(const std::vector<double>& p, const std::vector<double>& f, int s, const std::wstring& alphabet)
{
double sum = 0;
for (size_t i = 0; i < alphabet.size(); i++) {
sum += std::abs(p[i] - f[(i + s) % alphabet.size()]);
}
return sum;
}
std::wstring RussianDecrypt::CaesarCypherCrack(std::wstring& inputText)
{
// Частоты букв в русском языке
std::vector<double> p = {
0.07821, // А
0.01732, // Б
0.04533, // В
0.01687, // Г
0.02977, // Д
0.08398, // Е
0.00094, // Ё
0.00940, // Ж
0.01641, // З
0.07367, // И
0.01210, // Й
0.03486, // К
0.04343, // Л
0.03203, // М
0.06700, // Н
0.10983, // О
0.02804, // П
0.04746, // Р
0.05473, // С
0.06318, // Т
0.02615, // У
0.00162, // Ф
0.00764, // Х
0.00348, // Ц
0.01440, // Ч
0.00728, // Ш
0.00331, // Щ
0.00020, // Ъ
0.01983, // Ы
0.01732, // Ь
0.00331, // Э
0.00541, // Ю
0.01801 // Я
};
std::wstring alphabetLower = L"абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
std::wstring alphabetUpper = L"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
// Подсчитываем частоты в зашифрованном тексте
std::vector<double> f(alphabetLower.size(), 0);
int total = 0;
for (char c : inputText) {
auto pos = alphabetLower.find(tolower(c));
if (pos != std::wstring::npos) {
f[pos]++;
total++;
}
}
for (double& count : f) {
count /= total;
}
// Поиск минимального D(s)
int bestShift = 0;
double minD = CalculateD(p, f, 0, alphabetLower);
for (int s = 1; s < alphabetLower.size(); s++) {
double currentD = CalculateD(p, f, s, alphabetLower);
if (currentD < minD) {
minD = currentD;
bestShift = s;
}
}
// Расшифровка с найденным сдвигом
std::wstring result;
for (char c : inputText) {
if (isalpha(c)) {
bool isUpper = isupper(c);
const std::wstring& alphabet = isUpper ? alphabetUpper : alphabetLower;
auto pos = alphabet.find(c);
if (pos != std::wstring::npos) {
result += alphabet[(pos - bestShift + alphabet.size()) % alphabet.size()];
}
}
else {
result += c;
}
}
return result;
}
фрагмент кода формы, функция buttonCrack_Click
private: System::Void buttonCrack_Click(System::Object^ sender, System::EventArgs^ e) {
// Расшифровка шифра на английском
msclr::interop::marshal_context context;
std::wstring stdInputText = context.marshal_as<std::wstring>(inputText);
std::wstring stdDecryptedText = Decrypt::CaesarCipherCrack(stdInputText);
System::String^ DecryptedText = gcnew System::String(stdDecryptedText.c_str());
this->richTextBox2->Text = DecryptedText;
// Расшифровка шифра на русском
std::wstring wstdInputText = context.marshal_as<std::wstring>(inputText);
std::wstring wstdDecryptedText = RussianDecrypt::CaesarCypherCrack(wstdInputText);
System::String^ russianDecryptedText = gcnew System::String(wstdDecryptedText.c_str());
this->richTextBox3->Text = russianDecryptedText;
}
Что самое интересное, если в richTextBox3
попробовать просто вывести строку, например, скопировав вводимый текст, то русские символы будут отображаться корректно.
this->richTextBox3->Text = inputText + L" ЭТО КОПИЯ";
Пробовал настроить проект под символы Юникода, но там и так всё правильно.
Изначально использовал std::string
, но потом сделал через std::wstring
так как он поддерживает символы Юникода, но проблема не решилась.
Также, для вашего удобства прикрепляю ссылку на этот проект на GitHub, чтобы вы могли полностью просмотреть проект.