2

I have been working on this since yesterday and after much struggle have managed to encrypt the message successfully. However, my output is missing spaces.

As I understand it, the reason this is happening is because I'm using isalpha(), isupper() and islower() commands and as a result am ignoring the spaces in the original input.

Can one please help me with how to retain the original spaces and punctuation?

Below is my code- its far from elegant and any comments on style will also be appreciated!

(Also, while there are plenty of questions on Caesar Cipher, none barring one deal with this problem. Since this is my first week programming, I had trouble understanding the syntax in that one.)

There is a blatant mistake in my algorithm which causes it to output the wrong values if given certain arguments. For instance with a k of 13, inputting anything after the 13th alphabet (m, I think) will output something very bizarre. I will amend this and get back soon! Till then, take my code with a grain of salt!

# include <cs50.h> 
# include <stdio.h> 
# include <stdlib.h>
# include <string.h>
# include <ctype.h>


int main(int argc, string argv[])

{
    if (argc != 2)
    {
        printf("Please enter a valid number of arguments! \n");
        return 1;
    }

    string num = argv[1];
    int k = atoi(num);

        if (k < 0)
            {
                printf("Please enter a valid number! \n");
                return 1;
            }

    printf("Please type the message which needs to be encrypted: ");
    string p = GetString();

        for (int i = 0, n = strlen(p); i < n; i++)
        {
            int oldletter = p[i];
            int result1 = (oldletter + k);
            int result2 = (oldletter - 65 + k);
            int result3 = (result2) % 26;
            int result4 = (oldletter - 97 + k);
            int result5 = (result4) % 26;

                if (isalpha(p[i]) && isupper(p[i]) && k < 26)
                {
                    printf("%c", result1);
                }

                if (isalpha(p[i]) && isupper(p[i]) && k >= 26) 
                {
                    int result7 = (result3 + oldletter); 
                    printf("%c", result7);
                }


                if (isalpha(p[i]) && islower(p[i]) && k < 26)
                {
                    printf("%c", result1);
                }

                if (isalpha(p[i]) && islower(p[i]) && k >= 26)
                {
                    int result8 = (result5 + oldletter); 
                    printf("%c", result8);
                }

        }
        printf("\n");
}

Corrected code, working properly: SPOILERS AHEAD

# include <cs50.h> 
# include <stdio.h> 
# include <stdlib.h>
# include <string.h>
# include <ctype.h>

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Please enter a valid number of arguments! \n");
        return 1;
    }

    string num = argv[1];
    int k = atoi(num);

    if (k < 0)
        {
            printf("Please enter a valid number! \n");
            return 1;
        }

    printf("Message: ");
    string p = GetString();

        for (int i = 0, n = strlen(p); i < n; i++)
        {
            int oldletter = p[i];
            int result1 = (oldletter - 65 + k);
            int result2 = (result1) % 26;
            int result3 = (oldletter - 97 + k);
            int result4 = (result3) % 26;


                if (isalpha(p[i]) && isupper(p[i])) 
                {
                    int result5 = (result2 + 65); 
                    printf("%c", result5);
                }


                else if (isalpha(p[i]) && islower(p[i]))
                {
                    int result6 = (result4 + 97); 
                    printf("%c", result6);
                }

                else 
                {
                    printf("%c", p[i]);
                }

        }
        printf("\n");
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    Is this really C? There is no `string` type in C, you're programming in C++. – unwind Jun 04 '14 at 12:54
  • @unwind this is in fact C, I've taken the online version of the Harvard CS50 myself and they typedef string as char * for the first part of the course to make it a bit "simpler" and not have students wonder about the asterisk and pointers. – AliciaBytes Jun 04 '14 at 12:57
  • Note: No need for `isalpha(p[i])` with , `isupper(p[i])` or with `islower(p[i])`. "The isalpha function tests for any character for which isupper or islower is true,..." §7.4.1.2 – chux - Reinstate Monica Jun 04 '14 at 14:50
  • @chux That was an decision by the course staff, I just wanted to give information unwind that it's in fact C code. As for undefined behavior, you do all programming inside a VM that's a pre-configured and modified 32bit fedora version with the same compiler. Therefore the staff got some assertions about the actual implementation. The test input is all `0-127` ascii range so for sure in the range of `unsigned char`. – AliciaBytes Jun 04 '14 at 15:09
  • @chux As for supporting the decisions of the "simplifications" the staff made, that's up to everyone to decide if they agree. I just wanna note that's really just the very first intro course they take and they take away the magic of strings and talk about pointers after they are a few weeks into the course. – AliciaBytes Jun 04 '14 at 15:10
  • In this post, there is nothing stated or tagged that specifies this is some course work. "cs50.h" may hint to that but certainly does not define it. There is nothing that defines a VM that's a pre-configured nor inputs are tested input to a 0-127 ASCII range. AFAIK, "cs50.h" is some company standard and the OP is presenting simplified code. – chux - Reinstate Monica Jun 04 '14 at 15:24
  • Sorry for the confusion- This is indeed one of the problem sets for CS50 and I am using a VM but I am not taking the class on EdX or any other forum but simply using the last year's archived version of the website to teach myself something I have wanted to learn for long :) I am toying with the idea of taking this class next semester and just wanted to get my hands dirty before I begin. If I feel comfortable enough, I might skip this class altogether and take CS51 which is Introduction to Computer Science II! Hope that clears things! – boametaphysica Jun 05 '14 at 04:43

2 Answers2

2

A common pitfall I see when people implement this is to go straight to ascii values. Consider making an alphabet array, you can just get the position of your current letter in it, and then determine what the modified letter should be.

Imagine adding a '%' character to this with the ascii solution, you'll end up having a ton of special if's. You can chose in that case to ignore spaces/etc if you like, personally I would add them to the alphabet array so the ciphertext didn't reveal the spaces (giving away hints).

capybaras
  • 198
  • 1
  • 6
  • This is a good idea. Then you can just use `(current_index +/- shift)%26` to easily change the index as needed. – houckrj Jun 04 '14 at 13:50
1

You should probably chain together the if's as else if's, there is no need to evaluate an if condition if one of the previous was already true in your case. This would also allow for a final else case to be executed when isalpha is false like in the case with spaces.

Just change the if conditions to:

if (isalpha(p[i]) && isupper(p[i]) && k < 26)
{
    printf("%c", result1);
}

else if (isalpha(p[i]) && isupper(p[i]) && k >= 26) 
{
    int result7 = (result3 + oldletter); 
    printf("%c", result7);
}


else if (isalpha(p[i]) && islower(p[i]) && k < 26)
{
    printf("%c", result1);
}

else if (isalpha(p[i]) && islower(p[i]) && k >= 26)
{
    int result8 = (result5 + oldletter); 
    printf("%c", result8);
}

else
{
    printf("%c", p[i]);
}

I wanna note that your logic is pretty complex and you should also choose better names than the result* variables that you currently use, in programming readability and maintainability are really important. You can easily do assignments without considering them due to the small programs you write there but it's a good habit to get into.

I also took the course (with prior C experience) and uploaded my final solution for you to compare to/improve with once you finished yours. Just a warning, I used a function, not sure if it was already explained before this problem set but should be at least explained soon after. Here is my solution: http://pastebin.com/vJqPY6Ne

AliciaBytes
  • 7,300
  • 6
  • 36
  • 47
  • 1
    @boametaphysica I added a small part about readability and my solution from this problem at the end to compare with for improvements when you finished yours. Also since you updated the question that you got a logic problem, you probably should identify your problem yourself and try to fix it (only ask a question if you got a specific problem with it due to learning consideration). – AliciaBytes Jun 04 '14 at 13:31
  • I have finished my version and just went through your code. Your code is definitely a lot more elegant than mine. I would've loved to use the functions. The professor did introduce it in the first lecture of this week's problem set but did not delve much into it as the main focus was on arrays and loops. Thanks once again! – boametaphysica Jun 05 '14 at 04:50