dimanche 19 février 2023

c++ getline fails to operate with spaces and 2-digit long input [duplicate]


#include <iostream>
#include <random>
#include <fstream>
#include <string>

        using namespace std;

        void converter(string klucz)
        {
            string failename;
            string buffer;
            string tekst;
            string dummy;
            int mode = 0;
            cout << "\nNazwa pliku z rozszerzeniem: ";
            getline(cin, failename);
            cout << "\n\nTYP OPERACJI:\n--------------------------------\n1. Jednoliniowa konwersja\n2. Wieloliniowa konwersja (plik)\n--------------------------------\n\n";
            cin >> mode;
            cin.ignore();
            if (mode == 2)
            {
                fstream peik;
                peik.open(failename);
                if (peik)
                {
                    std::cout << "Converting...\n";
                }
                else
                {
                    peik.close();
                    fstream plik;
                    std::cout << "File created. Input any text and press enter when ready." << endl;
                    bool ended = false;
                    int i = 1;
                    plik.open(failename, std::ios_base::app);
                    while (ended != true)
                    {
                        string appendtext;
                        cout << i << "> ";
                        getline(cin, appendtext);
                        if (appendtext == "[end]")
                        {
                            ended = true;
                        }
                        else
                        {
                            plik << appendtext + "\n";
                        }
                        i++;
                    }
                    plik.close();
                }
            }
            if (mode == 1)
            {
                string ciagwyrazow;
                cout << "\nKONWERTUJ: ";
                getline(cin, ciagwyrazow);
                if (ciagwyrazow.length() - 1 > 1)
                {
                    for (int i = 0; i <= ciagwyrazow.length() - 1; i++)
                    {
                        cout << ciagwyrazow[i] << " ";
                    }
                    for (int i = 0; i <= ciagwyrazow.length() - 1; i++)
                    {
                        for (int j = 0; j <= 94 - 1; j++)
                        {
                            if (j == (int)ciagwyrazow[i] - 32)
                            {
                                cout << klucz[j];
                            }
                        }
                    }
                    getline(cin, buffer);
                }
                else
                {
                    for (int j = 0; j <= 94 - 1; j++)
                    {
                        if (j == (int)ciagwyrazow[0] - 32)
                        {
                            cout << klucz[j];
                        }
                    }
                    getline(cin, buffer);
                }
            }
            else if (mode != 1 && mode != 2)
            {
                cout << "\nZłe dane.\n";
            }
        }
        int main()
        {
            std::cout << "KLUCZ: ";
            //key digits
            char characterenc[94]{};
            //initalize the table
            for (int i = 0; i <= 94 - 1; i++)
            {
                characterenc[i] = 0;
            }
            //IsCharGen = has given char generated?
            bool IsCharGen = false;
            //seed the generator
            random_device rd;
            mt19937 gen(rd());
            //generator range
            //32 = the smallest possible number
            //126 = highest possible number
            uniform_int_distribution<> distr(32, 126);
            for (int i = 0; i <= 94 - 1; i++)
            {
                //generate the number
                int liczbagenerowana = distr(gen);
                //check if the value has been generated already
                for (int j = 0; j <= 94 - 1; j++)
                {
                    //scenario = char has been generated before
                    if (liczbagenerowana == (int)characterenc[j])
                    {
                        IsCharGen = true;
                    }
                }
                if (IsCharGen == true)
                {
                    i--; //rerun the cycle for this digit
                }
                else
                {
                    characterenc[i] = liczbagenerowana; //value hasn't been generated
                }
                IsCharGen = false;
                //std::cout the key digit by digit
            }
            string klucz;
            for (int i = 0; i <= 94 - 1; i++)
            {
                klucz = klucz + characterenc[i];
            }
            std::cout << klucz <<endl;

            // converter
            converter(klucz);
        }

This code is a greater piece of a cipher changing characters to values found in klucz variable, randomized every launch. Ex.

Klucz: 'sN lou*n(/CYcw$;8PZ)y17a?M>x,~0Li2U%9k}XgAK=G^3H[@p".z-h:_]etQSqW#&RFdV<|m6b5rDBvT!4O`+JEfj{

"!" after conversion: s "!!!" after conversion: sss "! !" after conversion: s~s

\n found in sentences should also be treated as text

Value of given symbol is present in ciagwyrazow[x], where x = (int)char - 32.

Now let's focus on mode 1 (single-line conversion). Everything works just fine as long as user input's length isn't 2 (where only one character is output at the end) or when the sencence has spaces (only the piece before the first one gets converted, rest is discarded).

Error consequences differ from code studios. When started on onlinegdb.com, it makes a loud noise (see ascii elements 0-9) and displays some partially readable gibberish, with some root directory of its at the end, not featuring even a bit of expected output. (all tries)

Visual Studio Code outputs user input before conversion and then outputs converted sentence, everything seems to work normally except spaces, which are never modified.

Visual Studio outputs only the first converted piece if spaces are present, its IntelliSense doesn't detect errors in the code (Studio Code has the same problem too), and outputs only the first char if length of the sentence is 2.

I believe the problem resides in getlines, yet i wasn't able to properly debug my faulty concotion, as gdb debugger skipped user input no matter what I've tried and then proceeded to fail as described above, microsoft products' debuggers didn't work for me, making me unable to trace the problem.

So far I've tried adding namespaces (std) before cins and getlines themselves, using cin.ignore() in prolly every possible way and done other experiments on these i don't remember because of me being overloaded with information back then and read multiple articles about possible causes, including one that says it's dangerous to use cins and getlines in correlation (that's why cin.ignore() are pressent in the code). But to no avail, the program's behavior didn't change, no matter what I've tried. I'm out of ways how to fix this.




Aucun commentaire:

Enregistrer un commentaire