0

First time here. I'm done with pset2's caesar but I get some error messages I don't understand. Hope someone can help me. Thanks in advance!

ERROR:

:) caesar.c exists.
:) caesar.c compiles.
:) encrypts "a" as "b" using 1 as key
:( encrypts "barfoo" as "yxocll" using 23 as key
    output not valid ASCII text
:) encrypts "BARFOO" as "EDUIRR" using 3 as key
:) encrypts "BaRFoo" as "FeVJss" using 4 as key
:) encrypts "barfoo" as "onesbb" using 65 as key
:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
    output not valid ASCII text
:) handles lack of argv[1]

FULL ERROR1:

:( encrypts "barfoo" as "yxocll" using 23 as key
output not valid ASCII text 

Log 
running ./caesar 23... 
sending input barfoo... 
checking for output "ciphertext: yxocll "...

FULL ERROR2:

:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
output not valid ASCII text 

Log 
running ./caesar 12... 
sending input world, say hello!... 
checking for output "ciphertext: iadxp, emk tqxxa! "...

CODE:

//Change plaintext to cyphertext by adding (+) some values

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ABL 26                                              //ABL is alphabet lenght

int main(int argc, string argv[])
{

    //Only runs when 1 command line argument is given (an int)
    if (argc != 2)
    {
        printf("This is just wrong!\n");
        return 1;
    }
    else
    {
        int c = atoi(argv[1]);                              //String -> int <3 <3 <3

        //Only runs when argv[1]>=0
        if(c < 0)
        {
            printf("This is just wrong!\n");
            return 1;
        }
        else
        {
            c = c % ABL;                                    //39 up in the alphabet == 13 up
            string pt = get_string("plaintext:");           //Prompt user for plaintext
            printf("ciphertext:");                          //Print "ciphertext"

            //The transformation begins
            for (int i = 0, j = strlen(pt); i < j; i++)
            {
                if (isupper(pt[i]))                         //for uppercase letters
                {
                    char p = pt[i] + c;
                    if (p > 'Z')
                    {
                        p = p - ABL;
                    }
                    printf("%c", p);
                }
                else if (islower(pt[i]))                    //for lowercase letters
                {
                    char p = pt[i] + c;
                    if (p > 'z')
                    {
                        p = p - ABL;
                    }
                    printf("%c", p);
                }
                else                                        //for other characters
                {
                    printf("%c", pt[i]);
                }
            }
            printf("\n");                                   //print enter
            return 0;                                       //terminate program

        }
    }
}
  • Hi Dorplein, welcome to CS50 Stack Exchange. When you perform check50, there's a link at the end to a page with the full error messages. Could you add to your post: the full error message for "world, say hello!" ? – Peter Pesch Oct 13 '18 at 7:09
  • Thanks! These are the both of them, I'll also add them to the original. 1.) :( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key output not valid ASCII text Log running ./caesar 12... sending input world, say hello!... checking for output "ciphertext: iadxp, emk tqxxa! "... 2.) :( encrypts "barfoo" as "yxocll" using 23 as key output not valid ASCII text Log running ./caesar 23... sending input barfoo... checking for output "ciphertext: yxocll "... – Dorplein Oct 13 '18 at 7:22
1

In this case, the output of check50 is very clear:

:) caesar.c exists.

:) caesar.c compiles.

:) encrypts "a" as "b" using 1 as key

:( encrypts "barfoo" as "yxocll" using 23 as key output not valid ASCII text

:) encrypts "BARFOO" as "EDUIRR" using 3 as key

:) encrypts "BaRFoo" as "FeVJss" using 4 as key

:) encrypts "barfoo" as "onesbb" using 65 as key

:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key output not valid ASCII text

:) handles lack of argv[1]

The error seems to occur when shifting the string upwards in the alphabet (with the key modulo 26) makes some of the letters beyond z. (Probably when the character code gets bigger than 127, where z has character code 122) ...


Actually, the error occurs in this part:

            else if (islower(pt[i]))                    //for lowercase letters
            {
                char p = pt[i] + c;
                if (p > 'z')
                {
                    p = p - ABL;
                }
                printf("%c", p);
            }

You declare p as a char. So p is a variable which can hold integer values between -128 and 127.

Suppose the current character is r, which has ascii code 114.

If you add 23 to that, you would like to get 137. However, as that is greater than 127 we get an integer overflow. Therefor, after char p = pt[i] + c;, p will actually hold the value -119.

So the line if (p > 'z') checks whether -119 is greater than 122 - which is false.

Therefore, p will not be corrected. And it clearly holds a non-ASCII value ...


Finally, to quote Cliff B:

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |
  • Yeeees! Thanks a lot. I understand it and it's fixed now. – Dorplein Oct 13 '18 at 18:35
1

You made a good effort to solve the caesar problem. Sometimes its better to start to have simple solutions to problems and not think complex or lengthy solution for em and therefore, I suggest that you may solve this by thinking on the core of this pset which is as I quote from the instrcutions " if p is some plaintext (i.e., an unencrypted message), pi is the ith character in p, and k is a secret key (i.e., a non-negative integer), then each letter, ci, in the ciphertext, c, is computed as

ci=(pi+k)mod26

wherein mod26 here means "remainder when dividing by 26." This formula perhaps makes the cipher seem more complicated than it is, but it’s really just a concise way of expressing the algorithm precisely". Now, if you focus then you may realize that there are two steps in your code that you might wanna change as follows :

c = c % ABL; 
char p = pt[i] + c;
if (p > 'Z')
{
       p = p - ABL;
}

Think of it as you got a key and plaintext from user which may have upper case and lower case or other chars. Now, chars are just for us but have ascii values for computers like A is 65,B is 66, a is 97, b is 98 so, first whatever key you add or whatever you subtract from the char has to be via these ascii values not the chars so, you may need explicit type casting like (int) c, to convert from char to int and then perform operations. Secondly, the key you have has to be added to the char in plaintext in such a way that the key is always added to the ascii equivalent of the alphabets or chars are considered from 0 through 25 like a char c = 'H' is 72 in ascii so, you may do it like (int) c - 65 which makes 'H' at index 7.Thirdly, you may add the key and then taking modulo 26 you ensure that the loop is from 'A' to 'Z' only and then convert that to ascii by adding 65 and then to the char by type casting.

If this helps, please give a checkmark!

| improve this answer | |
  • Thanks! Apparently I can't give two people checkmarks but you also helped me! Looks like there's a great community here! – Dorplein Oct 13 '18 at 18:36

You must log in to answer this question.

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