Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
My solution to CS50 pset2 - "Hail, Caesar!"
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
/**
* Caesar.c
* A program that encrypts messages using Caesar’s cipher. Your program must
* accept a single command-line argument: a non-negative integer. Let’s call it
* k for the sake of discussion. If your program is executed without any
* command-line arguments or with more than one command-line argument, your
* program should yell at the user and return a value of 1.
*
* */
int main(int argc, string argv[])
{
// check for 2 arguments only
if (argc != 2)
{
printf("Nope\n");
return 1;
}
// once I check for correct argv put key into an int k
int k = atoi(argv[1]);
// check if the integer is non-negative
if (k < 0)
{
printf("Nope\n");
return 1;
}
else
{
// prompt user for a code to encrypt
string code = GetString();
for (int i = 0, n = strlen(code); i < n; i++)
{
//check if the letter is uppercase or lowercase then convert
if islower(code[i])
printf("%c", (((code[i] + k) - 97) % 26) + 97);
else if isupper(code[i])
printf("%c", (((code[i] + k) - 65) % 26) + 65);
//if neither then just print whatever it is
else
printf("%c", code[i]);
}
printf("\n");
return 0;
}
}
@elminson
Copy link

elminson commented Apr 26, 2020

Hello everyone!!

I got the same problem as most people..
My problem is :( handles non-numeric key timed out while waiting for program to exit

Could you help me, somebody, please?

Here is my code.

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

int main(int argc, char **argv)
{
//PROMT USER'S KEY
if (argc == 2 && isdigit(*argv[1]))
{
int k = atoi(argv[1]);
string plaintext = get_string("plaintext:");

    // check numeric key
    for(int j = 0, n = strlen(argv[1]); j < n; j++)
    {
    if(!isdigit(argv[1])
     {
        printf("Usage: ./caesar key\n");
        return 1;
     }
    }

 // loops over the plaintext and OUTPUT ciphertext
    printf("ciphertext: ");
    for (int i = 0, len = strlen(plaintext); i < len; i++)
    {
    // Lower letter
    if (islower(plaintext[i]))
       {
        printf("%c", (plaintext[i] - 'a' + k) % 26 + 'a');
       }
    // Upper letter
    else if (isupper(plaintext[i]))
        {
        printf("%c", (plaintext[i] - 'A' + k) % 26 + 'A');
        }
    else
        {
        printf("%c", plaintext[i]);

        }
    }
printf("\n");
 return 0;
}
else
  {
    printf("Usage: ./caesar key\n");
    return 1;
  }
  printf("\n");

}

THANKS!
you have to check if argv[1] is a number

if (!isNumeric(argv[1]))
{
    printf("Usage: ./caesar key\n");
    return 1;
}
int isNumeric (const char * s)
{
if (s == NULL || *s == '\0' || isspace(*s))
return 0;
char * p;
strtod (s, &p);
return *p == '\0';
}

@evgenydikarev
Copy link

evgenydikarev commented Apr 26, 2020

Hello everyone!!
I got the same problem as most people..
My problem is :( handles non-numeric key timed out while waiting for program to exit
Could you help me, somebody, please?
Here is my code.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char **argv)
{
//PROMT USER'S KEY
if (argc == 2 && isdigit(*argv[1]))
{
int k = atoi(argv[1]);
string plaintext = get_string("plaintext:");

    // check numeric key
    for(int j = 0, n = strlen(argv[1]); j < n; j++)
    {
    if(!isdigit(argv[1])
     {
        printf("Usage: ./caesar key\n");
        return 1;
     }
    }

 // loops over the plaintext and OUTPUT ciphertext
    printf("ciphertext: ");
    for (int i = 0, len = strlen(plaintext); i < len; i++)
    {
    // Lower letter
    if (islower(plaintext[i]))
       {
        printf("%c", (plaintext[i] - 'a' + k) % 26 + 'a');
       }
    // Upper letter
    else if (isupper(plaintext[i]))
        {
        printf("%c", (plaintext[i] - 'A' + k) % 26 + 'A');
        }
    else
        {
        printf("%c", plaintext[i]);

        }
    }
printf("\n");
 return 0;
}
else
  {
    printf("Usage: ./caesar key\n");
    return 1;
  }
  printf("\n");

}
THANKS!
you have to check if argv[1] is a number

if (!isNumeric(argv[1]))
{
    printf("Usage: ./caesar key\n");
    return 1;
}
int isNumeric (const char * s)
{
if (s == NULL || *s == '\0' || isspace(*s))
return 0;
char * p;
strtod (s, &p);
return *p == '\0';
}

I am not sure if I instert it right, but still the problem...

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

int isNumeric (const char * s);
int main(int argc, char **argv)
{
//PROMT USER'S KEY
if (argc == 2)
{

    string plaintext = get_string("plaintext:");

    // loop check numeric key
if (!isNumeric(argv[1]))
{
    printf("Usage: ./caesar key\n");
    return 1;
}


    // loops over the plaintext and OUTPUT ciphertext
    printf("ciphertext: ");
    int k = atoi(argv[1]);
    for (int i = 0, len = strlen(plaintext); i < len; i++)
    {
        // Lower letter
        if (islower(plaintext[i]))
        {
            printf("%c", (plaintext[i] - 'a' + k) % 26 + 'a');
        }
        // Upper letter
        else if (isupper(plaintext[i]))
        {
            printf("%c", (plaintext[i] - 'A' + k) % 26 + 'A');
        }
        else
        {
            printf("%c", plaintext[i]);

        }
    }
    printf("\n");
    return 0;
}
else
{
    printf("Usage: ./caesar key\n");
    return 1;
}
printf("\n");

}

int isNumeric (const char * argv)
{
if (s == NULL || *s == '\0' || isspace(*s))
return 0;
char * p;
strtod (s, &p);
return *p == '\0';
}

`

@elminson
Copy link

elminson commented Apr 26, 2020

Should be before asking for the plain text
string plaintext = get_string("plaintext:");

@evgenydikarev
Copy link

evgenydikarev commented Apr 26, 2020

Amazing! Thank you so much!! I am gonna try to understand the body of your function now haha

@elminson
Copy link

elminson commented Apr 26, 2020

Glad to help! Cool! go for it!

@thecodelearner5000
Copy link

thecodelearner5000 commented Apr 26, 2020

Is there a way to use isdigit to check if the string has anything other than a digit?

Tried using !isdigit(argv[1]) to check if argv[1] is a digit, but got "segmentation fault" output

Im tring to use an if statement " if argv[1] is not a digit then..."

@d-tonar
Copy link

d-tonar commented Apr 30, 2020

Is there a way to use isdigit to check if the string has anything other than a digit?

Tried using !isdigit(argv[1]) to check if argv[1] is a digit, but got "segmentation fault" output

Im tring to use an if statement " if argv[1] is not a digit then..."

argv[1] is not a char, so you're not able to check if it is a single digit 0-9

I converted argv[1] to a string and checked each character in a for loop

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

int main(int argc, string argv[])
{
    //check the command line argument
    //check if only 1 argument was given, else explain usage and return 1
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    
    //convert argv[1] to a string
    string str_array = argv[1];
    
    //check if the characters of str_array are numbers 0-9
    for (int i = 0; str_array[i] != 0; i++)
    {
        if (isdigit(str_array[i]) == false)
        {
            printf("Usage: ./caesar key\n");
            return 1;
        }
    }
    
    //convert str_array to an int k
    int k = atoi(str_array);

.
.
.

@d-tonar
Copy link

d-tonar commented May 2, 2020

@Angela-Ts
Copy link

Angela-Ts commented May 7, 2020

Hi all!

I have added some more code that covers the case that the user returns one alphanumeric key (e.g 5x). It doesn't look very...elegant though. Any suggestions are more than welcome. :)

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

int main(int argc, string argv[])
{
// Accept only one command-line argument

if (argc == 2)
{
    // Check that they all chars are digits
    int j = 0;
    string z = argv[1];
    for (int i = 0, n = strlen(z); i < n; i++)
    {
        if (isdigit(z[i]))
        {
            j++;
        }
    }
    // Convert according to the key
    if (j == strlen(z))
    {
        
        int k = atoi(argv[1]);
        string text = get_string("plaintext: ");
        printf("ciphertext: ");
        for (int l = 0, m = strlen(text); l < m; l++)
        {
            // Convert
            if islower(text[l])
            {
                printf("%c", (((text[l] - 'a') + k) % 26) + 'a'); 
            }
            else if isupper(text[l])
            {
                printf("%c", (((text[l] - 'A') + k) % 26) + 'A'); 
            }
            else 
            {
                printf("%c", text[l]);
            }
        }
        printf("\n");
        return 0;
    }
    else
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}
else
{
    printf("Please provide the key.\n");
    return 1;
}

}`

@asiozos
Copy link

asiozos commented May 17, 2020

Consider this solution to check for the correct input of the program:

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

//boolean variable that is true if argument is correct
bool check_arg;

//if more than 1 arguments error message
if (argc != 2)
{
printf("Correct usage: ./caesar key\n");
return 1;
}

// if correct number of arguments check for integer
if (argc == 2)
{
int arg_length = strlen(argv[1]);
for (int i = 0; i < arg_length; i++)
{
if (!isdigit(argv[1][i]))
{
check_arg = false;
}
else
{
check_arg = true;
}
}
// if argument is an integer go on with the ciphering
if (check_arg)
{
printf("Correct!!!\n");
}
//if argument is NOT an integer, error message
else
{
printf("Correct usage: ./caesar key\n");
}

}
}

@andrestunner
Copy link

andrestunner commented May 18, 2020

i keep getting this error message : handles non-numeric key
timed out while waiting for program to exit
please help
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar k\n");
return 1;
}

int k = atoi(argv[1]);
if  (k < 0)
  {
    printf("Usage: ./caesar k\n");
   return 1;
  }

string s = get_string("Plaintext: ");
printf("ciphertext: ");

for (int i =0, n = strlen(s); i < n; i++)
if (s[i] >='a'&& s[i] <='z')
{
printf("%c", (((s[i] - 'a') + k) % 26) + 'a');
}
else if (s[i] >='A'&& s[i] <='Z')
{
printf("%c", (((s[i] - 'A') + k) % 26) + 'A');
}
else
{
printf("%c", s[i]);
}
printf("\n");
return 0;

}

@asiozos
Copy link

asiozos commented May 18, 2020

i keep getting this error message : handles non-numeric key
timed out while waiting for program to exit
please help
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar k\n");
return 1;
}

int k = atoi(argv[1]);
if  (k < 0)
  {
    printf("Usage: ./caesar k\n");
   return 1;
  }

string s = get_string("Plaintext: ");
printf("ciphertext: ");

for (int i =0, n = strlen(s); i < n; i++)
if (s[i] >='a'&& s[i] <='z')
{
printf("%c", (((s[i] - 'a') + k) % 26) + 'a');
}
else if (s[i] >='A'&& s[i] <='Z')
{
printf("%c", (((s[i] - 'A') + k) % 26) + 'A');
}
else
{
printf("%c", s[i]);
}
printf("\n");
return 0;

}

Your code only checks the amount of arguments given when running the program.
It does not check whether the user has provided proper parameters.
It does not reject the use of chars as a key for example.
Hope I have helped.

@fdominguez88
Copy link

fdominguez88 commented May 22, 2020

I can't make it work when user inputs 20x

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

int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar key\n");
return 1;
}

//get encryption key from the user
int keyInt = atoi(argv[1]);

//check that key is valid
if (!isdigit(argv[1][keyInt]))
{
    printf("Usage: ./caesar key\n");
    return 1;
}

//encrypt message
else
{
    string plainText = get_string("Plaintext: ");

    for (int magicNumber = 0, toCipher = strlen(plainText); magicNumber < toCipher; magicNumber++)
    {
        //check lowercase
        if islower(plainText[magicNumber])
        {
            printf("%c", (((plainText[magicNumber] + keyInt) - 97) % 26) + 97);
        }
        //check uppercase
        else if isupper(plainText[toCipher])
        {
            printf("%c", (((plainText[magicNumber] + keyInt) - 65) % 26) + 65);
        }
        //rest of chars
        else
        {
            printf("%c", plainText[magicNumber]);
        }

    }

    printf("\n");
    return 0;
}

}

@asiozos
Copy link

asiozos commented May 22, 2020

CraigRodrigues, I have the feeling that if you pass "20x" as an input to atoi(), it will give 20 as output.
This being said, you have to check every single character of argv(1) whether it is an integer or not.
Check at my code a few posts above to see how I implemented it.

@amehta24
Copy link

amehta24 commented Jun 3, 2020

Hi I have a question.

I understand everything except for the algorithm. Why do we need to add and subtract the 97 and 65 (why is it the numbers for the just letter a and A not any other)?

@asiozos
Copy link

asiozos commented Jun 3, 2020

Hi I have a question.

I understand everything except for the algorithm. Why do we need to add and subtract the 97 and 65 (why is it the numbers for the just letter a and A not any other)?

Because many many years ago the scientists formed the so-called ASCII table where each character corresponds to a decimal value. You can see the ascii table here.

@amehta24
Copy link

amehta24 commented Jun 3, 2020

Hi I have a question.
I understand everything except for the algorithm. Why do we need to add and subtract the 97 and 65 (why is it the numbers for the just letter a and A not any other)?

Because many many years ago the scientists formed the so-called ASCII table where each character corresponds to a decimal value. You can see the ascii table here.

Ya I understand that, but why is just the ASCII decimal value that just represents lowercase a and uppercase A and not any of the other letters and corresponding letters?

@akshay9192
Copy link

akshay9192 commented Jul 15, 2020

It seems that you forgot to check if the key is a digit or not so I tried to fix and rearrange a little bit. If you have some trouble with my solution, just feel free to leave a comment and I will check it out
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
/**

  • Caesar.c
  • A program that encrypts messages using Caesar’s cipher. Your program must
  • accept a single command-line argument: a non-negative integer. Let’s call it
  • k for the sake of discussion. If your program is executed without any
  • command-line arguments or with more than one command-line argument, your
  • program should yell at the user and return a value of 1.
  • */

int main(int argc, string argv[])
{
// once I check for correct argv put key into an int k
if (argc == 2 && isdigit(*argv[1]))
{
int k = atoi(argv[1]);

    // check if the integer is non-negative
    if (k < 0)
    {
    printf("Usage: ./caesar key\n");
    return 1;
    }
    
    else
    {
    // prompt user for a code to encrypt
    string code = get_string("plaintext: ");
    printf("ciphertext: ");
    
    for (int i = 0, n = strlen(code); i < n; i++)
        {
            //check if the letter is uppercase or lowercase then convert
            if islower(code[i])
                printf("%c", (((code[i] + k) - 97) % 26) + 97);
            else if isupper(code[i])
                printf("%c", (((code[i] + k) - 65) % 26) + 65);
            //if neither then just print whatever it is
            else
                printf("%c", code[i]);
        }
        printf("\n");
        return 0;
    }
}

else 
{        
    printf("Usage: ./caesar key\n");
    return 1;
}

}

still not an optimal solution, if input equals "./caesar 20x", the output still not equals "Usage: ./caesar key". isdigit(*argv[1]) will only determine whether the string argv[1] starts with a digit or not, it doesn't apply to the full string.

bro it does not convert y it converts y to some other symbol when i try
./caesar 1
$:plain text:y
cipher text:`

@Ritvik-Nagabhushana
Copy link

Ritvik-Nagabhushana commented Oct 3, 2020

few changes:

  1. its not GetString , it is get_string
  2. its get_string("\n"), not GetString();
  3. variable name should be changed from code to Code
  4. ******** most important, add #include <stdlib.h> otherwise you will get an implicit conversion error

@ar94952
Copy link

ar94952 commented Oct 9, 2020

This is pretty good! Thank you for sharing this. I tested this code, but it appears that it doesn't handle non-numeric key.

Results for cs50/problems/2020/x/caesar generated by check50 v3.1.2
:) caesar.c exists.
:) caesar.c compiles.
:) encrypts "a" as "b" using 1 as key
:) encrypts "barfoo" as "yxocll" using 23 as key
:) 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
:) handles lack of key
:( handles non-numeric key
timed out while waiting for program to exit

:) handles too many arguments

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

int main(int argc, string argv[])
{
// Validate correct argv enter key into int
if (argc == 2 && isdigit(*argv[1]))

{
    int k = atoi(argv[1]);
    
    // validate integer is not negative
    if (k < 0)
    
    //if a letter or unrecognized character is entered, then print instructions
    {
        printf("Please enter the following: ./caesar key(number, i.e., 25 or 51) \n");
        return 1;
    }
    
    else
    
    {
        // Ask user for a word to encrypt
        string code = get_string("Enter word(s) to encrypt: ");  //someone told me to use GetString, but that doesn't seem right, so I asked around for suggestions
        printf("ciphertext: ");

        for (int i = 0, n = strlen(code); i < n; i++)
        {
            //check if the letter is uppercase or lowercase then convert
            if islower(code[i])
            
            {
                
                printf("%c", (((code[i] + k) - 97) % 26) + 97);    //testing suggestions on running negative -97 lowercase and 65 for uppercase
                
            }
            
            else if isupper(code[i])
            
            {
                
                printf("%c", (((code[i] + k) - 65) % 26) + 65);
                
            }
            
            else
            
            {
                printf("%c", code[i]);
            
            }    
            
        }
        
        printf("\n");
        return 0;
        
    }
    
}

//if a letter is entered instead of a number, then print instructions
else 

{        
    printf("Text not recognized. Please enter a number. Example: ./caesar 23 \n");
    return 1;
    
}

} `

@aaryan2134
Copy link

aaryan2134 commented Oct 19, 2020

I tried this. This solves the alpha numeric issue but starts giving more weird problems. I am getting these two problems, which were not there before i checked for alphanumeric thing
caesar.c exists.
:) caesar.c compiles.
:( encrypts "a" as "b" using 1 as key
output not valid ASCII text

:) encrypts "barfoo" as "yxocll" using 23 as key
:) 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 key
:) handles non-numeric key
:) handles too many arguments

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

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

if (argc == 2)
{

  for(int r = 0; r < strlen(argv[1]); r++) // after adding this to prevent taking "20x" type of input i am starting to get 2 new errors
  {
      if (isdigit(argv[1][r]) == false)
      {
           printf("Usage: ./caesar key\n");
    
            return 1;
      }
      
  }
    key = atoi(argv[1]); // converting from string to integer
    
    if (key > 0)        // bit of cheating, 0 will not be accepted as key  :(
    {
        string message = get_string("plaintext: ");
        int n = strlen(message);
        char cmessage[n];
        
        for (int i = 0; i < n; i++)
        {
            if (message[i] >= 'a' && message[i] <= 'z')
            {
               cmessage[i] = ((message[i] - 97) + key)%26 + 97; 
            }
            
            else if (message[i] >= 'A' && message[i] <= 'Z')   
            {
                cmessage[i] = ((message[i] - 65) + key)%26 + 65; 
            }
            
            else
            {
                cmessage[i] = message[i];
            }

        }

        printf("ciphertext: %s\n", cmessage);

        return 0;

    }

    else
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}

else
{
    printf("Usage: ./caesar key\n");
    return 1;
}

}

@engintosun34
Copy link

engintosun34 commented Dec 6, 2020

thank you!

@luthrasaara
Copy link

luthrasaara commented Dec 28, 2020

Can someone please give me a simple way to check if my key is a number or not because I am very confused?

@luthrasaara
Copy link

luthrasaara commented Dec 28, 2020

Hi all!

I have added some more code that covers the case that the user returns one alphanumeric key (e.g 5x). It doesn't look very...elegant though. Any suggestions are more than welcome. :)

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

int main(int argc, string argv[])
{
// Accept only one command-line argument

if (argc == 2)
{
    // Check that they all chars are digits
    int j = 0;
    string z = argv[1];
    for (int i = 0, n = strlen(z); i < n; i++)
    {
        if (isdigit(z[i]))
        {
            j++;
        }
    }
    // Convert according to the key
    if (j == strlen(z))
    {
        
        int k = atoi(argv[1]);
        string text = get_string("plaintext: ");
        printf("ciphertext: ");
        for (int l = 0, m = strlen(text); l < m; l++)
        {
            // Convert
            if islower(text[l])
            {
                printf("%c", (((text[l] - 'a') + k) % 26) + 'a'); 
            }
            else if isupper(text[l])
            {
                printf("%c", (((text[l] - 'A') + k) % 26) + 'A'); 
            }
            else 
            {
                printf("%c", text[l]);
            }
        }
        printf("\n");
        return 0;
    }
    else
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}
else
{
    printf("Please provide the key.\n");
    return 1;
}

}`

Oh my god! Thank you so much! This worked and was easy to understand as well. I have been so confused and stressed, you made my day. Thank youuuuu!

@aahanafromindia
Copy link

aahanafromindia commented Jan 30, 2021

let someone help me at this:
Connecting.......
Authenticating......
Preparing...............
Uploading.............
Checking.......
:) caesar.c exists.
:( caesar.c compiles.
expected exit code 0, not 1
:| encrypts "a" as "b" using 1 as key
can't check until a frown turns upside down
:| encrypts "barfoo" as "yxocll" using 23 as key
can't check until a frown turns upside down
:| encrypts "BARFOO" as "EDUIRR" using 3 as key
can't check until a frown turns upside down
:| encrypts "BaRFoo" as "FeVJss" using 4 as key
can't check until a frown turns upside down
:| encrypts "barfoo" as "onesbb" using 65 as key
can't check until a frown turns upside down
:| encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
can't check until a frown turns upside down
:| handles lack of argv[1]
can't check until a frown turns upside down

same is happening
with me any soon

@lauren-xox
Copy link

lauren-xox commented Feb 11, 2021

I like looking at these after I've finished mine to compare, and OP's code is definitely cleaner than mine. I thought of using ASCII but I don't know why my brain didn't just wrap itself around adding and subtracting... it's like I immediately ruled out the ASCII solution to go with something "easier" (arrays), even though they provided a nod to ASCII conversions being a more efficient way to do this on the pset page. Here's mine with a summary of how it all works at the bottom:

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h> //CAESAR.C, scroll to bottom to see full summary

const char upperalphabet[26] = {'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'};
const  char loweralphabet[26] = {'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'};


int main(int argc, string argv[])
{
    if (argc < 2)
    {
        return 1;
    }
    else if (argv[1] < 0)
    {
        return 1;
    }

    int key = atoi(argv[1]);

    string plaintext = get_string("plaintext: ");
    printf("\n ciphertext: ");

    for (int n = 0; n < strlen(plaintext); n++)
    {
        if (isalpha(plaintext[n]))
        {
            if (isupper(plaintext[n]))
            {
                int z;
                for (z = 0; plaintext[n] != upperalphabet[z]; z++)
                    ;

                int ciphernumber = ((z + key) % 26);
                printf("%c", upperalphabet[ciphernumber]);
            }
            else if (islower(plaintext[n]))
            {
                int z;
                for (z = 0; plaintext[n] != loweralphabet[z]; z++)
                    ;

                int ciphernumber = ((z + key) % 26);
                printf("%c", loweralphabet[ciphernumber]);
            }
        }
        else
        {
            printf("%c", plaintext[n]); //non-alphabetical plaintext array elements get printed here
        }
    }
    printf("\n");
    return 0;
}

/*Code summary: This code takes a character string that the user inputs - let's call that p. And p's individual characters can be called p^i.
Through a loop, the code finds a character in the above alphabet array that matches p^i. The index identifier for this index in the alphabet array
(that matches p^i), we'll call n. It can be seen as a numerical equivalent to p^i.

Using the modulus of (n + the key inputted through the command line) out of 26 (all the letters of the alphabet), we'll find the index identifier of
the index containing the char that is the cipher-shift of p^i. And once that's found, we can print it to see its char element.

The output should be a ciphertext directly corresponding to the plaintext, with whitespaces, punctuation and lettercase unchanged, the only thing
modified being the alphabetical letters themselves to a cipher-shifted char equivalent. */
`

@lauren-xox
Copy link

lauren-xox commented Feb 11, 2021

as you can see it's way too long lol

@Ishraj18
Copy link

Ishraj18 commented May 8, 2021

Steps:

  1. Get a single command-line argument "key" from the user that is a non-negative integer.
  2. If not a single argument then yell at user.
  3. Take the "key" and turn it into an int with atoi since it starts as a string.
  4. Prompt user for a code they want to encrypt.
  5. Need to loop through the entire code letter by letter.
  6. Check if each letter is either lowercase, uppercase or neither.
  7. Standardize the ASCII value of the char to 26 then add the key. Then convert back into ASCII so that the code can wrap around properly.
  8. If neither a lowercase or uppercase letter then just print whatever the char is. This allows for spaces or special characters like ! or &.
  9. Once all of the above is complete print a new line.
  10. Return 0.

Notes:

  • Checking if the argv[1] was a non-negative integer (don't think I even needed to do this).
  • Figuring out how to standardize ASCII to the regular alphabet then converting back took a lot of time.
  • This ASCII chart was incredibly useful - http://www.kerryr.net/pioneers/ascii3.htm
  • Trying to put argv[1] into a variable before I check if there is even an argv[1] caused a segmentation fault.
  • Didn't notice that toupper/tolower already checks if the character is a letter. First I had two more checks to see if the character was a letter or not when that wasn't necessary.
  • ctype.h library is very useful - https://cs50.harvard.edu/resources/cppreference.com/stdstring/all.html

What if the user enters an alphabet instead of a number in place of key?

@ClaudioCS50
Copy link

ClaudioCS50 commented Jan 27, 2022

Guys I'm getting this:

:) caesar.c exists.
:) caesar.c compiles.
:( encrypts "a" as "b" using 1 as key
expected "ciphertext: b...", not "ciphertext: b..."
:( encrypts "barfoo" as "yxocll" using 23 as key
expected "ciphertext: yx...", not "ciphertext: yx..."
:( encrypts "BARFOO" as "EDUIRR" using 3 as key
expected "ciphertext: ED...", not "ciphertext: ED..."
:( encrypts "BaRFoo" as "FeVJss" using 4 as key
expected "ciphertext: Fe...", not "ciphertext: Fe..."
:( encrypts "barfoo" as "onesbb" using 65 as key
expected "ciphertext: on...", not "ciphertext: on..."
:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
expected "ciphertext: ia...", not "ciphertext: ia..."
:) handles lack of argv[1]
:) handles non-numeric key
:) handles too many arguments

but the output match.... Any idea?

@bellatorsoprano
Copy link

bellatorsoprano commented Oct 1, 2022

idk
i'm also getting thi with similiar code

were u able to do it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment