Function only works once

The 'multiArrayCipher' function calls on 2 other functions to fill a vector and then output that vector. However, only the first vector gets filled and outputted, the rest are just outputted as squares. For instance, if I input "Hello my name is" the output will be "ho e▢▢▢▢▢▢▢▢▢▢▢▢"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <cmath>
#include <string>
#include <fstream>
#include <vector>

using namespace std;

class functions
{
    private:
        char alphabet[26];
        string sentance;
        int counter=0;
        vector <char> multiArrayOne;
        vector <char> multiArrayTwo;
        vector <char> multiArrayThree;
        vector <char> multiArrayFour;

    public:
        void collectAlphabet ()
        {
            ifstream file;
            file.open("alphabet.txt");

            for (int j=0; j<26;j++)
            {
                file >> alphabet[j];
            }
        }

        void input ()
        {
            cout << endl;
            cout << "Write a sentence: ";
            getline(cin,sentance);

        }

        void arrayFill (int x, vector <char> & tempArray)
        {
            for (int j=x;j<=sentance.length();j+=4)
            {
                tempArray.push_back(1);
                tempArray[counter]=sentance[j];
                counter++;
            }

        }

        void arrayOutput (vector <char> tempArray)
        {
            for (int j=0;j<tempArray.size();j++)
            {
                cout << tempArray[j];
            }
        }

        void subCipher ()
        {
            cout << endl << "The new version is ";

            for (int i=0;i<sentance.length();i++)
            {
                if (sentance[i]==' ')
                    {
                        cout << " ";
                    }

                for (int j=0;j<26;j++)
                {
                    if (alphabet[j]==alphabet[23] && sentance[i]==alphabet[23])
                    {
                        cout << alphabet[0];
                    }

                    else if (alphabet[j]==alphabet[24] && sentance[i]==alphabet[24])
                    {
                        cout << alphabet[1];
                    }

                    else if (alphabet[j]==alphabet[25] && sentance[i]==alphabet[25])
                    {
                        cout << alphabet[2];
                    }

                    else if (alphabet[j]==sentance[i])
                    {
                        cout << alphabet[j+3];
                    }
                }
            }
            cout << endl << endl;
        }

        void multiArrayCipher()
        {
            arrayFill(0,multiArrayOne);
            arrayOutput(multiArrayOne);
            arrayFill(1,multiArrayTwo);
            arrayOutput(multiArrayTwo);
            arrayFill(2,multiArrayThree);
            arrayOutput(multiArrayThree);
            arrayFill(3,multiArrayFour);
            arrayOutput(multiArrayFour);
        }

};

int main()
{
    functions program;
    int input{};

    while (input!=5)
    {
        cout << "1. Substitution cipher" << endl;
        cout << "2. Multi-array cipher" << endl;
        cout << "3. Transposition cipher" << endl;
        cout << "4. Code breaker" << endl;
        cout << "5. Exit" << endl << endl;
        cout << "Enter the number of the option you want to proceed with: ";
        cin >> input;
        cin.ignore();

        switch (input)
        {
            case 1:
                program.collectAlphabet();
                program.input();
                program.subCipher();
                break;

            case 2:
                program.input();
                program.multiArrayCipher();
                break;


        }

    }


    return 0;
}
your alphabet array is probably filled with garbage if user immediately goes to option 2, because you didn't yet perform a population of alphabet.

Usually you want to do these things in the class constructor and not force the user to explicitly call collectAlphabet() method when really this is something that the class should do every time to initialize its data.

Also, does the alphabet.txt file ever change? If not, you may prefer this initializer list refactor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Consider naming your class with a capital letter, i.e. Functions.  It's more
//   stylistic, and also may avoid some trouble esp if you're using the std namespace, 
//   since many of those classes begin with lowercase letters.
class Functions  
{

// Simpler to align public: and private: with the opening of class bracket because, for the 
//   most part, it unnecessarily indents everything else.
private:

    // Adding an underscore is a common way to show private var at a glance
    vector<char> alphabet_;  

public:
    Functions()  // Constructor
    {
        alphabet_ = {'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'};
    }
};


If alphabet.txt does change, then you can either keep alphabet as char array as you currently have, or as a vector<char>, as long as you perform the insertions in constructor.
Last edited on
Hello Shezshade,

I thought I had mentioned this before, but I could not find it. Maybe when I finish here.

Your function:
1
2
3
4
5
6
7
8
9
10
void arrayFill (int x, vector <char> & tempArray)
{
        for (int j=x;j<=sentance.length();j+=4)
        {
            tempArray.push_back(1);
            tempArray[counter]=sentance[j];
            counter++;
        }

}

is a problem. I had a run time error when "counter" was ==4, but the vector size was only 3. You can not put something into a vector element when it does not exit in the first place.

All you need for this function is:
1
2
3
4
5
6
7
8
void arrayFill (int x, vector <char> & tempArray)
{
        for (int j=x;j<=sentance.length();j+=4)
        {
            tempArray.push_back(sentance[j]);
        }

}

The other two lines if not working against you are not needed. When I tested it this worked fine.

Hopoe that helps,

Andy
Thanks guys. I thought the push back function can only add space for a new element, not add the element itself?
Last edited on
Hello Shezshade,

No it does not add space it adds what you tell it to. You could define a vector as:
std::vector<type> name(10); where the (10) will create a vector with 10 empty elements. Then you could use a sub script to access the vector;

Take a look at these two pages:
http://www.cplusplus.com/reference/vector/vector/emplace_back/
http://www.cplusplus.com/reference/vector/vector/push_back/

And if you have any questions let me know.

Hope that helps,

Andy
vector::reserve() reserves space (internally changes its 'capacity' variable value).
If you know exactly how much space you'll be needing, then you can preemptively call this method before any push_back s.

vector::push_back() appends element(s) if the capacity is fine. If capacity is not fine, it is automatically increased (I believe it's set to exactly what's needed).

Don't be afraid to dig around in the docs; Google is your friend =)
Topic archived. No new replies allowed.