0

I've been trying different solutions but am not sure where to look for the solution.

I prompt the user for "plaintext" and whatever their input is, the chars in their input need to be rotated alphabetically by a number (aka the key) which they provide.

For example: plaintext: HELLO would spit out ciphertext: IFMMP if the key were 1.

Assuming the key will always be a number, here is what my code looks like which attempts to rotate each char by Key: 1. I'm a real noob so please break it down is possible.

{
     string s = get_string("plaintext: ");                                    
     printf("ciphertext: %s\n", s + 1);
}   

The remaining code (which includes identifying and filtering out the key is:

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

int main(int argc, string argv[])
{                
    int counter = 0;    
    if (argc == 2)
    {
        for(int k = 0; k <strlen(argv[1]); k++)
        {
            if (isdigit(argv[1][k]))
            {
                counter++;         
            }
        }   
        if (strlen(argv[1]) == counter)
        {
            string s = get_string("plaintext: ");
            if(s)
            {
                
                printf("ciphertext: %s\n", s + 1);
                free(s);
            }
        }   
        else
        {
            printf("Usage: ./caesar key\n");
        }
    }
    else
    {
        printf("Usage: ./caesar key\n");
    }                     

}

Any assistance would be appreciated.

Enis Arik
  • 665
  • 10
  • 24
Fransweezy
  • 29
  • 6
  • 1
    Are you using a version of C that includes `string` as a type? – ryyker Dec 12 '19 at 15:53
  • Change `+ 1` to `+ n` and get `n` from user. You may have to account for overflow. – Fiddling Bits Dec 12 '19 at 15:53
  • Does this answer your question? [Caesar's Cipher Code](https://stackoverflow.com/questions/8464936/caesars-cipher-code) – Mad Physicist Dec 12 '19 at 15:53
  • You need to modify every character in the string. (The "string" type in that course is pretty annoying – you still need to understand pointers in order to use it effectively.) – molbdnilo Dec 12 '19 at 15:53
  • This is C++ for what it's worth. – Qix - MONICA WAS MISTREATED Dec 12 '19 at 16:02
  • 1
    @ryyker It's part of the library for the CS50 free online course. It's just `typedef char* string;`. – molbdnilo Dec 12 '19 at 16:02
  • @ryyker I believe so. I'm new at this and still learning. – Fransweezy Dec 12 '19 at 16:13
  • If you are not constrained to use `cs50`, don't. It always seems ironic to me that a teaching organization, or program would offer a class that requires students use a weak imitation of the real thing when the _[real thing](https://gcc.gnu.org/install/download.html)_ is otherwise freely available, and would allow teaching the right things the first time through. – ryyker Dec 12 '19 at 16:14
  • @MadPhysicist Even though it probably contains the answer, i don't understand it. I need to understand what each line means and how to use it. For example "char cipher[50]" I know what a "char" is but now cipher[50]. Also please keep in mind, CS50 changes their problem sets every year. That example was 8 years ago so the problem set is no longer used. – Fransweezy Dec 12 '19 at 16:16
  • @molbdnilo Yeah I've heard of pointers but don't know how to use them. I'll have to research them further. – Fransweezy Dec 12 '19 at 16:17
  • @ryyker I've learned alot through using CS50 but there are definitely challenges. – Fransweezy Dec 12 '19 at 16:18
  • @ryyker After CS50 we get into which I'm pretty sure the industry uses. I'm sure Harvard has its reasons. – Fransweezy Dec 12 '19 at 16:43
  • 1
    @Fransweezy. Those reasons may have more to do with cash flow over your personal well being after school than you would care to admit to yourself. – Mad Physicist Dec 12 '19 at 17:16
  • @MadPhysicist Cool story. I'm just looking to rotate char, not argue with anybody on their opinions. – Fransweezy Dec 13 '19 at 00:29

2 Answers2

0

You can achieve this with typecasting:

char input = 'f';
char output = (char)((int)input + 1);

You should also handle edge cases, i.e. when the character value is near the end of the alphabet.

ryyker
  • 22,849
  • 3
  • 43
  • 87
Maxxik CZ
  • 314
  • 2
  • 9
  • I don't know how to handle edge cases. I am very new at this. – Fransweezy Dec 12 '19 at 16:12
  • @Fransweezy you just have to test whether the integer you got is even inside the alphabet. If it's not try subtracting or adding 26 till you get there. I won't tell you more on how to do this. – Maxxik CZ Dec 13 '19 at 07:18
0

I do not have cs50, so cannot test everything in your code, but addressing your primary question: How Do I Rotate A Char Alphabetically By Integer X, the code section you have identified as where the rotation occurs:

 if (strlen(argv[1]) == counter)
 {
      string s = get_string("plaintext: ");                                    
      printf("ciphertext: %s\n", s + 1);
 } 

But this section doesn't really rotate the text. It rather attempts to print the string obtained from the call to get_string after adding 1 to it. First, this is not modifying s at all. Second, s + 1 is not a legal operation. To rotate s, additional code is needed between those two lines.

If I understand get_string(), it is essentially a combination of printf(), fgets(,,stdin) and strdup(). So after the call to that function you are left with s which will be populated with whatever the user typed into stdin. For illustration, let say s contains "what the user typed". How that string is represented in memory, including the NULL terminator, can be depicted as follows:

 |w|h|a|t| |t|h|e| |u|s|e|r| |t|y|p|e|d|0|

To rotate this by X, as you have stated, each character needs to be modified by adding the value X, in this case 1

Showing ASCII equivalent values:

 |119|104|97|116|32|116|104|101|32|117|115|101|114|32|116|121|112|101|100|0|

The rotated string then would be each value + 1:
For the general case, assume rotation value is read in from command line argument and placed into int n = 0;

earlier in code:

if(isdigit(argv[2][0]))
{
    n = atoi(argv[2])   
}

The rotation: (the following is complete. It may need a little debugging around the corner case [where values wrap around the end of ASCII values when added to n.] Lines are commented indicating where I used ANSI C instead of CS50. [I do not have CS50])

int main(int argc, char *argv[])//note: command line requires a numeric
                                // argument be used:  prog.exe 12 (for n == 12)
{
    //char s[80];//used to test (I do not have cs50)
    char *rotated = NULL;
    int i;

    if(argc != 2) 
    {
        printf("Usage: prog.exe <positive int value.>\nExiting\n");
        return 0;
    }
    if(isdigit(argv[1][0]) == 0)
    {
        printf("Usage: prog.exe <positive int value.>\nExiting\n"); 
        return 0;
    }

    int n = atoi(argv[1]);
    string s = get_string("plaintext: ");
 //   printf("Enter text to be rotated\n");//used to test (I do not have cs50)
 //   scanf("%[^\n]", s);

   // string rotated = strdup(s); //preserve s by manipulating identical string
    rotated = StrDup(s);
    if(rotated)
    {   //advance value by n
        int origVal = 0;
        int len = strlen(rotated);
        for(i=0;i<len;i++)
        {
            origVal = rotated[i];
            if((rotated[i] + n) <= 127) 
            {
                rotated[i] += n;
            }
            else
            {
                rotated[i] = abs(127 - (origVal + n));
                if(rotated[i] == 0) rotated[i] += 23; //skip to printable characters (http://facweb.cs.depaul.edu/sjost/it212/documents/ascii-pr.htm)             
                //if(rotated[i] == 0) rotated[i] += 1; //skip only ASCII NULL value
            }       
        } 
        rotated[i] = 0; //adding NULL to end of string 
        printf("ciphertext: %s\n", rotated);
        free(rotated);
    }
    return 0;   
}
ryyker
  • 22,849
  • 3
  • 43
  • 87