Reputation: 31
Current situation:
User runs my program and gives it a key. Let's say that key == 1. User is prompted for text. If they enter the word "Hello"
the key rotates each char by 1 and the output is "Ifmmp"
.
THE PROBLEM:
If the user inputs the word "zoo", the output (if the key == 1) is {pp. The output should be "app". How do I get the output to go from Z back to A for any char entered that crosses the letter Z.
Here's the code I constructed (with much help) to build this functionality:
#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: ");
printf("ciphertext: ");
for (int j = 0; j < strlen(s); j++)
{
int c = (int) s[j];
printf("%c", c + atoi(argv[1]));
}
printf("\n");
}
else
{
printf("Usage: ./caesar key\n");
}
}
else
{
printf("Usage: ./caesar key\n");
}
}
Any assistance would be great!
Upvotes: 2
Views: 729
Reputation: 70392
Since C does not guarantee the adjacency of the letters, you should create a table that maps the input letter to the appropriate output letter.
A compact way to do this is just with a special string.
const char *map =
"abcdefghijklmnopqrstuvwxyza"
"ABCDEFGHIJKLMNOPQRSTUVWXYZA";
With this string, you can implement a simple function that searches for the input character, and return the output character.
int rot1(int c) {
const char *x = strchr(map, c);
return x ? x[1] : c;
}
The strchr
call searches map
for the first occurrence of c
. If it's found, it returns the pointer where in the map
it is. The value in the location after this pointer is the output value.
The trick used here is that the string in map
has an extra a
after z
. Similarly for Z
. Since strchr
finds the first occurrence, the extra occurrence doesn't affect the correctness of the algorithm.
Upvotes: 1
Reputation: 193
I will just explain you the principle and it is your task to code the source code:
Iterate through your given string in order to get each char. Get the value of the proper char and increment it. For example, 'h' has value value 104. 104 incremented equals 105 which corresponds to the char 'i' which is exactly what you want. Ultimately, what you need to do is to add the condition if the char value is 122 which is 'z'. In this case do not increment but set it manually to 97('a').
That is it. You simply need to do the same task for the capital letters too. Set 90('Z') manually to 65('A').
Keep in mind that you should check whether the user input is even in the range of the latin alphabet as the principle would not work with crazy unicode chars.
Upvotes: 0
Reputation: 587
When I have a problem like this where I want a number to loop back to the start once it crosses a threshold (like a clock), I find modulus to be the best solution.
Example:
int hour = 11;
hour = (hour + SOME_VALUE) % 12; // This will ensure hour is always a value between 0 and 11
Now, you'd have to check whether the letter is a capital letter (check an ASCII table), and apply a different modulus.
Upvotes: 1