0
votes

So I am writing a code that encrypts and input by switching the letter to the one after it, using the formula ai = letter ( (position(ai )+ position(ai+1) ) mod k ) where k is the number of letters in the alphabet.

Now here is my code;

using namespace std;

class Encrypt {
private:
    char letters[27];
    char *String = new char[500];
    char letters_cipher[25];
    unsigned int i, k;
public:
    Encrypt() :letters{ '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' } {

        for (unsigned int i = 0; i < strlen(String); i++) {
            String[i] = '\0';
        }
    }
    ~Encrypt() {
        delete[] String;
    }
    void GetString() {
        cout << "Enter String : ";
        std::cin >> String;
    }

    void encrypt() {
        for (i = 1; i <= 26; i++) { // Run 26 times (1 for each letter)
            letters_cipher[i] = letters[(i + (i + 1)) % 26];
            cout << letters_cipher[i] << endl;
        }
        for (i = 0; i <= (strlen(String) - 1); i++) { // individual characters of string x can be referenced by x[0] etc
            for (k = 0; k <= 25; k++) {
                if (String[i] == letters[k]) {
                    cout << letters_cipher[k];
                }
            }
        }
    }

    void Print() {
        for (unsigned int i = 0; i < strlen(letters_cipher); i++) {
            cout << letters_cipher[i];
        }
    }

};

I get the following error

Exception thrown: read access violation. this->String was 0x128F112.

for the line:

if (String[i] == letters[k])

Any idea how I can fix this?

EDIT:

I have now made some edits on the code and it looks like the following;

class Encrypt {
private:
    char letters[27];
    char *String = new char[500];
    char letters_cipher[27];
    unsigned int i, k;
public:
    Encrypt() :letters{ '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' } {

        for (unsigned int i = 0; i < 500; i++) {
            String[i] = '\0';
        }
    }
    ~Encrypt() {
        delete[] String;
    }
    void GetString() {
        cout << "Enter String : ";
        std::cin >> String;
    }

    void encrypt() {
        for (i = 1; i <= 26; i++) { // Run 26 times (1 for each letter)
            letters_cipher[i] = letters[(i + (i + 1)) % 26];
            cout << letters_cipher[i] << endl;
        }
        for (i = 0; i <= (sizeof(String) - 1); i++) { // individual characters of string x can be referenced by x[0] etc
            for (k = 0; k <= 25; k++) {
                if (String[i] == letters[k]) {
                    cout << letters_cipher[k];
                }
            }
        }
    }

    void Print() {
        for (unsigned int i = 0; i < sizeof(letters_cipher); i++) {
            cout << letters_cipher[i];
        }
    }

};

The error is no longer there, the program runs but closes with an error;

'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel.appcore.dll'. Cannot find or open the PDB file. 'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcrt.dll'. Cannot find or open the PDB file. 'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\rpcrt4.dll'. Cannot find or open the PDB file. 'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\sspicli.dll'. Cannot find or open the PDB file. 'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\cryptbase.dll'. Cannot find or open the PDB file. 'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\bcryptprimitives.dll'. Cannot find or open the PDB file. 'ConsoleApplication5.exe' (Win32): Loaded 'C:\Windows\SysWOW64\sechost.dll'. Cannot find or open the PDB file. The program '[20764] ConsoleApplication5.exe' has exited with code 0 (0x0).

1
There is more than one problem. First you'll have to fix the constructor, using strlen() on an uninitialized char[] is UB and causes wide-spread memory corruption. Use sizeof. Next you'll have to make letters_cipher one bigger so you can index % 26. Next you'll need to google "c++ rule of three".Hans Passant
Your added messages are all normal and expected. Unless you want to debug inside system dlls because you think you have found a bug in their implementation or you really want to debug an interaction between your application and the OS the PDB files for these are unnecessary. I have similar warnings for every program I debug.drescherjm

1 Answers

4
votes

in

    for (i = 1; i <= 26; i++) { // Run 26 times (1 for each letter)
        letters_cipher[i] = letters[(i + (i + 1)) % 26];

you write 2 indexes out of letters_cipher being char letters_cipher[25];, the behavior is undefined

and in

       for (k = 0; k <= 25; k++) {
            if (String[i] == letters[k]) {
                cout << letters_cipher[k];
            }

you read one index out of letters_cipher, the behavior is again undefined

The max allowed index in letters_cipher is 24

Note also that in

   for (unsigned int i = 0; i < strlen(letters_cipher); i++) {
        cout << letters_cipher[i];
    }

strlen(letters_cipher) will not works too because nowhere in your code where you enter the null ending character in it, so strlen will also go out of the initialized part of letters_cipher and may be again out of it.

You also have a problem in :

    for (unsigned int i = 0; i < strlen(String); i++) {
        String[i] = '\0';
    }

because you do strlen(String) the first loop without having initialized String, replace it by 500 (or better use a std::string)

Any idea how I can fix this?

In a general way do not use number like 26 or 25 in your loops, use sizeof, and you can also use std::vector rather than (C) arrays. When the contents is constant do not size by yourself, so for letters just do :

static const char letters_cipher[] = {
   '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'
};

Probably letters_cipher must have the same size as letters, and correct the set because the for starts at 1 rather than 0

Additional remarks

  • the array letters is useless, it only contains the letters a..z, so letters[i] is just 'a' + i
  • you do both using namespace std; and std::xxx, choose one of them (lot of people will say you to not do using namespace std;)

A proposal if I well understand your enscript :

#include <iostream>
#include <string>

class Encrypt {
  private:
    std::string str;
    char letters_cipher['z' - 'a' + 1];

    inline char letter(size_t i) { return 'a' + i; } // to help
  public:
    Encrypt() {} // default definition is useless in fact
    ~Encrypt() {} // default definition is useless in fact

    bool Getstr() {
      std::cout << "Enter str : ";
     return (std::cin >> str); // to indicates EOF in case
    }

    void encrypt() {
      for (size_t i = 1; i <= sizeof(letters_cipher); i++) { // Run 26 times (1 for each letter)
        letters_cipher[i - 1] = letter((i + (i + 1)) % 26);
        std::cout << letters_cipher[i - 1] << std::endl;
      }
      for (size_t i = 0; i < str.length(); i++) { // individual characters of string x can be referenced by x[0] etc
        for (size_t k = 0; k < sizeof(letters_cipher); k++) {
          if (str[i] == letter(k)) {
            std::cout << letters_cipher[k];
          }
        }
      }
      std::cout << std::endl;
    }

    void Print() {
      for (size_t i = 0; i < sizeof(letters_cipher); i++) {
        std::cout << letters_cipher[i];
      }
      std::cout << std::endl;
    }
};

int main()
{
  Encrypt e;

  e.Getstr();
  e.encrypt();
  e.Print();
}

Compilation and execution :

/tmp % g++ -pedantic -Wextra e.cc
/tmp % ./a.out
Enter str : azerty
d
f
h
j
l
n
p
r
t
v
x
z
b
d
f
h
j
l
n
p
r
t
v
x
z
b
dbllpz
dfhjlnprtvxzbdfhjlnprtvxzb

Execution under valgrind :

/tmp % valgrind ./a.out
==29157== Memcheck, a memory error detector
==29157== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==29157== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==29157== Command: ./a.out
==29157== 
Enter str : azerty
d
f
h
j
l
n
p
r
t
v
x
z
b
d
f
h
j
l
n
p
r
t
v
x
z
b
dbllpz
dfhjlnprtvxzbdfhjlnprtvxzb
==29157== 
==29157== HEAP SUMMARY:
==29157==     in use at exit: 0 bytes in 0 blocks
==29157==   total heap usage: 4 allocs, 4 frees, 115 bytes allocated
==29157== 
==29157== All heap blocks were freed -- no leaks are possible
==29157== 
==29157== For counts of detected and suppressed errors, rerun with: -v
==29157== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)