0

I am working on the Vigenere pset and seem to be getting the correct encryption but the output has nonsense characters added to it.

For example:

:( encrypts "a" as "a" using "a" as keyword
\ expected output, but not "ciphertext: aÖhÿ\n"
:( encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword
\ expected output, but not "ciphertext: xoqmd, rby gflkp!L*<ÿ\n"

if I run my code outputting characters as I go I get this:

~/workspace/ $ ./vigenere baz
plaintext: world, say hello!
1  ciphertext: x
2  ciphertext: xoK
3  ciphertext: xoq
4  ciphertext: xoqm
5  ciphertext: xoqmd
6  ciphertext: xoqmd,
7  ciphertext: xoqmd, 
8  ciphertext: xoqmd, r@
9  ciphertext: xoqmd, rb
10 ciphertext: xoqmd, rbyK
11 ciphertext: xoqmd, rby 
12 ciphertext: xoqmd, rby g
13 ciphertext: xoqmd, rby gf
14 ciphertext: xoqmd, rby gfl
15 ciphertext: xoqmd, rby gflk
16 ciphertext: xoqmd, rby gflkpH}
17 ciphertext: xoqmd, rby gflkp!H}

As you can see, lines 2, 8, 10, 16 and 17 have extraneous characters and I don't know how they ended up there.

Here is my code:

//Get user to input a message to encrypt
printf("plaintext: ");
string plain = get_string();
int p_len = strlen(plain); //length of the plaintext
char cipher[p_len]; //create ciphertext string as long as the plaintext

//Create a key algorithim based on user input key
int key[n];
for (int i = 0; i < n; i++)
{
    argv[1][i] = toupper(argv[1][i]);
    key[i] = (int) argv[1][i] - 65;

}

//encrypt plaintext with key
for (int i = 0; i < p_len;)
{
    //A seperate counter for Key so that it repeats until all of plain is encrypted
    for (int j = 0; j < n; j++)
    {
        if (i < p_len) //checks to make sure we haven't gone out of bounds on plaintext string array
        {

          //Skips over non alpha characters and keeps j the same
            if (!isalpha(plain[i]))
            {
               cipher[i] = plain[i];
               j--;
            }

            //rolls back to the beginning of uppercase alphabet if key encrypts to a character past 'Z'
            else if (isupper((int) plain[i]) && ((int) plain[i] + key[j]) > 90)
            {
                cipher[i] = ((int) plain[i] + key[j] - 26);
            }

            //rolls back to the beginning of lowercase alphabet if key encrypts to a character past 'z'
            else if (((int) plain[i] + key[j]) > 122 )
            {
                cipher[i] = ((int) plain[i] + key[j] - 26);
            }

            else
            {
                cipher[i] = ((int) plain[i] + key[j]);
            }
            i++;
        }
    }
}
printf("ciphertext: %s\n", cipher);
return 0;

Sorry for the long post. I hope someone can help me.

Thank You.

1 Answer 1

4

First, notice that the check50 result and your result have different nonsense characters at the end.

Recall from the Week 2 Lecture "More on Strings" (starting around 1:18) the discussion about string termination and the nul character '\0'.

The system expects a string to be terminated with '\0'. This line printf("ciphertext: %s\n", cipher); will print cipher up to that null terminator. The "nonsense" characters are whatever is in memory after the last ciphered character until it encounters a '\0'.

If you are going to treat the cipher array as a string (as with "%s" format in printf), you must allocate an extra byte for the null terminator (eg. char cipher[p_len + 1]; and add the null-terminator when you are done encoding the string (eg cipher[p_len] = '\0';)

4
  • Let's see if I understand this correctly. For example, if I had 'cipher[5]' and ran it through the above loop, the computer would just fill the empty array slots with random characters. Is this so the computer knows to set aside a certain amount of memory for the array and doesn't accidentally write something else into it? And because there was no nul character, the random characters were just appended?
    – Mike
    Commented Jan 31, 2017 at 3:52
  • The random chars were not appended; technically they were there to start with. cipher[5] allocates 5 bytes of memory to cipher, but it does not initialize them. printf says "I'm printing this cipher thingy until I see a null byte ('\0')";. It will keep "printing" bytes until it finds one; it has no idea you, the programmer, only allocated cipher for 5. It is printfing past the end of the array. Commonly known as a memory leak. Commented Jan 31, 2017 at 4:39
  • Ahh..... That makes sense. I get it. Last question. Why does cipher[p_len] = '\0'; not overwrite everything in cipher[p_len] with that '\0' character? (e.g. int x = 25 would make x 25 but if you put x = 27 on the next line then it would make x 27) Does the char or string declaration work differently than an int would?
    – Mike
    Commented Feb 3, 2017 at 0:51
  • cipher[p_len] = '\0' does overwrite everything in that specific index in the char array, that one byte. It works exactly the same as an int declaration. Commented Feb 3, 2017 at 1:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .