1

the problem is that when the program encounters a Polish letter in a text file, it misinterprets it - the character encoding issue.

The program is to decrypt an encrypted message, depending on the position of the letter (even, odd) there is to be a different key to decrypt.

When it comes across a Polish letter, it numbers it as two items. And it mistakenly gets values to functions.

I want the decrypted text to go to the txt file, I don't want to display it in the console.

I'm having a little fun with this, help and thank you in advance!

The code looks like this, something I tried to grind from Python to C ++ (working Python further below):

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
 
using namespace std;
 
char Decrypt(char letter, int kay);
 
int main(int argc, char const *argv[])
{
    ifstream file("text.txt");
    ofstream file2("text2.txt");
 
    int kay, kay2;
    cout << "Podaj klucz dla miejsc parzystych: ";
    cin >> kay;
    cout << "Podaj klucz dla miejsc nieparzystych: ";
    cin >> kay2;
 
    string text, text2;
 
    while (!file.eof())
    {
        getline(file, text);
        text2 = "";
        for (int i = 0; i < text.length(); i++)
        {
            if (i % 2 == 0)
            {
                text2 += Decrypt(text[i], kay);
            }
            else
            {
                text2 += Decrypt(text[i], kay2);
            }
        }
        file2 << text2 << endl;
        text2 = "";
    }
    file2.close();
    file.close();
 
    return 0;
}
 
char Decrypt(char letter, int kay)
{
    string lowercaseAlphabetPL = "aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż";
    string uppercaseAlphabetPL = "AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ";
 
    int index = lowercaseAlphabetPL.find(letter);
    if (index >= 0 && index <= 34)
    {
        if ((index - kay) % 35 < 0)
        {
            return lowercaseAlphabetPL[35 + (index - kay) % 35];
        }
        else
        {
            return lowercaseAlphabetPL[(index - kay) % 35];
        }
    }
    else
    {
        index = uppercaseAlphabetPL.find(letter);
        if (index >= 0 && index <= 34)
        {
            if ((index - kay) % 35 < 0)
            {
                return uppercaseAlphabetPL[35 + (index - kay) % 35];
            }
            else
            {
                return uppercaseAlphabetPL[(index - kay) % 35];
            }
        }
        else
        {
            return letter;
        }
    }
}

I also tried something like this with a better result, but it ignores Polish characters:

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
 
using namespace std;
 
const string lowercaseAlphabetPL[35] = {"a", "ą", "b", "c", "ć", "d", "e", "ę", "f", "g", "h", "i", "j", "k", "l", "ł", "m", "n", "ń", "o", "ó", "p", "q", "r", "s", "ś", "t", "u", "v", "w", "x", "y", "z", "ź", "ż"};
 
const string uppercaseAlphabetPL[35] = {"A", "Ą", "B", "C", "Ć", "D", "E", "Ę", "F", "G", "H", "I", "J", "K", "L", "Ł", "M", "N", "Ń", "O", "Ó", "P", "Q", "R", "S", "Ś", "T", "U", "V", "W", "X", "Y", "Z", "Ź", "Ż"};
 
string Decrypt(char letter, int kay);
 
int main(int argc, char const *argv[])
{
    ifstream file("text.txt");
    ofstream file2("text2.txt");
 
    int kay, kay2;
    cout << "Podaj klucz dla miejsc parzystych: ";
    cin >> kay;
    cout << "Podaj klucz dla miejsc nieparzystych: ";
    cin >> kay2;
 
    string text, text2;
 
    while (!file.eof())
    {
        getline(file, text);
        for (int i = 0; i < text.length(); i++)
        {
            if (i % 2 == 0)
            {
                cout << text[i] << " "; // rozbija polskie litery na 2 znaki im odpowiadające w innym kodowaniu
                text2 += Decrypt(text[i], kay);
            }
            else
            {
                cout << text[i] << " ";
                text2 += Decrypt(text[i], kay2);
            }
        }
        file2 << text2 << endl;
        text2 = "";
    }
    file2.close();
    file.close();
 
    return 0;
}
 
string Decrypt(char letter, int kay)
{
    string decryptedLetter;
    decryptedLetter += letter;
    for (int i = 0; i < 35; i++)
    {
        if (decryptedLetter == lowercaseAlphabetPL[i])
        {
            if ((i - kay) % 35 < 0)
                return lowercaseAlphabetPL[(i - kay) % 35 + 35];
            else
                return lowercaseAlphabetPL[(i - kay) % 35];
        }
        else if (decryptedLetter == uppercaseAlphabetPL[i])
        {
            if ((i - kay) % 35 < 0)
                return uppercaseAlphabetPL[(i - kay) % 35 + 35];
            else
                return uppercaseAlphabetPL[(i - kay) % 35];
        }
    }
    return decryptedLetter;
}

Works in Python, but I have to do in C ++ :(

def Decrypt(letter, kay):
    lowercaseAlphabetPL = "aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż"
    uppercaseAlphabetPL = "AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"
 
    index = lowercaseAlphabetPL.find(letter)
    if index >= 0 and index <= 34:
        if ((index - kay) % 35 < 0):
            return lowercaseAlphabetPL[35 + (index - kay) % 35]
        else:
            return lowercaseAlphabetPL[(index - kay) % 35]
    else:
        index = uppercaseAlphabetPL.find(letter)
        if index >= 0 and index <= 34:
            if ((index - kay) % 35 < 0):
                return uppercaseAlphabetPL[35 + (index - kay) % 35]
            else:
                return uppercaseAlphabetPL[(index - kay) % 35]
        else:
            return letter
 
 
def main():
    file = open("text.txt", "r", encoding="utf-8")
    file2 = open("text2.txt", "w", encoding="utf-8")
    kay = int(input("Podaj klucz dla miejsc parzystych: "))
    kay2 = int(input("Podaj klucz dla miejsc nieparzystych: "))
 
    for line in file:
        text = line
        text2 = ""
        for i in range(len(text)):
            if i % 2 == 0:
                text2 += Decrypt(text[i], kay)
            else:
                text2 += Decrypt(text[i], kay2)
        print("Po rozszyfrowaniu: " + text2.strip())
        file2.write(text2)
        text2 = ""
    file.close()
    file2.close()
 
main()

Any suggestions and ideas are welcome :)

  • Future bug: [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) Replace `while (!file.eof()) { getline(file, text);` with `while (getline(file, text)) {`. – user4581301 Mar 04 '22 at 19:55
  • `std::string` stores `char`s. Based on the way the files are opened in python, the input is in a format that uses more than a single `char`. This Question may contain useful answers: [Read Unicode UTF-8 file into wstring](https://stackoverflow.com/questions/4775437/read-unicode-utf-8-file-into-wstring). – user4581301 Mar 04 '22 at 20:01

1 Answers1

1

To store Polish (or any UTF-8) characters you would need to use some wider type than char e.g. wchar_t and wstring.

Let's rewrite you Polish alphabet to std::wstring type.

const wstring lowercaseAlphabetPL = L"aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż";
const wstring uppercaseAlphabetPL = L"AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ";

Such change, in turn, forces us to change types in a few more places:

  1. Now you text and text2 variables need to be std::wstring types as well.

  2. Your Decrypt function signature need to use wchar_t type, so it looks as follows:

    wchar_t Decrypt(wchar_t letter, int key)
    
  3. decryptedLetter inside Decrypt function also needs to be of wchar_t type

And finally, you need to have code capable of writing and reading wide chars and strings. Here we use std::wifstream and std::wofstream with appriopriate std::locale object set - capable of handling UTF-8 characters.

    std::wstring readFile(const std::string& filename)
    {
        const auto utf8Locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>());

        std::wifstream in(filename);
        in.imbue(utf8Locale);

        std::wstringstream wss;
        wss << in.rdbuf();
        return wss.str();
    }

    void writeFile(const std::string& filename, const std::wstring& text)
    {
        const auto utf8Locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>());

        std::wofstream out(filename);
        out.imbue(utf8Locale);
        out << text;
    }
eXpl0it3R
  • 90
  • 2
  • 6