#include <stdio.h>
int main()
{
int rotation, i=0;
char str[80]={0};
printf("Enter Text: ");
scanf("%[^\n]", str);
printf("\"");
printf("Enter Rotation: ");
scanf("%i", &rotation);
while(str[i])
{
if (str[i] >= 'a' && str[i] <= 'z')
printf("%c\n", 'a' + (str[i] - 'a' + rotation)%26);
else
printf("%c\n", str[i]);
i++;
}
return 0;
}
Have a hard time understanding this line of code (printf("%c\n", 'a' + (str[i] - 'a' + rotation)%26); )
Can anyone just write a brief explanation quickly it would help me
The program is taking the user's input text and on a per character basis rotating it through the alphabet based on the number entered. It works because of the ASCII table.
The line in question takes the character a user entered, offsets it by 'a' (which equals 91 in ASCII), adds in the rotation factor then performs modulo 26 on the result (how many characters are there in the alphabet again?) to make sure the result is still a lowercase character.
I bet you could find a good way to break this program :)
Related
I recently took an interest in encryption, then I came across this piece code, but I don't understand the meaning of the second "IF" statement.
#include<stdio.h>
int main()
{
char message[100], ch;
int i, key;
printf("Enter a message to encrypt: ");
gets(message);
printf("Enter key: ");
scanf("%d", &key);
for (i = 0; message[i] != '\0'; ++i) {
ch = message[i];
if (ch >= 'A' && ch <= 'Z') {
ch = ch + key;
if (ch > 'Z') {
ch = ch - 'Z' + 'A' - 1;
}
message[i] = ch;
}
}
printf("Encrypted message: %s", message);
return 0;
}
One of the fundamental things to understand for that code to make sense is that char represents both a character and a number at the same time.
That's because to a C program (and effectively all programs on all computers) characters are just numbers anyway.
When you say 'A' you could equivalently use 65 or 0x41 *.
You already make use of that property by adding key to ch to "shift up" the characters (i.e. if key is 1 then 'A' becomes 'B').
However, if you add 1 to 'Z' then the result is no longer an upper-case character (it will be [ in ASCII and compatible encodings).
The second if is responsible to wrap those results back down to 'A' by first subtracting 'Z' (which means the value is now "how many steps above Z were we) and then adding 'A' - 1 (which means that 1 step above Z will result in 'A').
* Assuming this is using ASCII or a compatible encoding, which will hold true on most modern operating systems
Let's rewrite the calculation that is performed if the expression of the if statement is true:
ch = ch - 'Z' + 'A' - 1;
to
ch = ch - ('Z' - 'A' + 1);
This should already make more sense. Now the part between parentheses of course never changes value, so lets introduce a constant:
#define APHABET_SIZE = ('Z' - 'A' + 1)
...
ch = ch - ALPHABET_SIZE;
Ah, so if the value of the character is higher than Z, the last letter of the alphabet, then subtract the alphabet size.
This is the kind of programming that you should not perform yourself; it performs all the functions at once instead of breaking them down, and trades briefness for readability.
The Caesar cipher performs modular addition to shift the characters by index. You should instead have a function int charToIndex(char), then perform the modular addition (or subtraction for decryption) using the % modulo operator and ALPHABET_SIZE, and then have a function char indexToChar(int) to convert it back.
I'm working on a simple piece of program to incorporate into a larger program. I'm following what my professor has already taught.
#include <stdio.h>
int main()
{
char letter;
printf("Please Enter a Lower Case Letter:");
scanf("%s", letter);
if (letter >= 'a' && letter <= 'z')
letter = letter - 'a' + 'A';
printf("%s", letter);
return 0;
}
The initial 'Please Enter a Lowercase Letter:' appears but after inputting a letter the return is (null). Any help is appreciated.
Maybe try getchar() instead of scanf(). Links to C reference for getchar() and scanf()
#include <stdio.h>
int main()
{
char letter;
printf("Please Enter a Lower Case Letter:");
letter = getchar();
if (letter >= 'a' && letter <= 'z')
letter = letter - 'a' + 'A';
printf("%c", letter);
return 0;
}
scanf("%s", letter); will read a string and copy it to the memory letter points to so pass the pointer of letter instead (scanf("%s", &letter);).
Also use %c instead of %s if you only need one character otherwise scanf can write some unwanted bytes to adjacent memory.
Likewise for the last printf line.
I've searched the web quite long for a simple caesar chiper/encryption algorithm in C language.
I found one but is wasn't perfect so I already changed the code.
Still having problems, because a friend said that the programm should be able to handle big key's, too.
For example text "Hello World" with a Key: 50... And if I do that I get the following: (Console output)
This tiny application encodes plain text to the Caesar Encryption
Type in some text to decode: Hello World
Type in the key/shifting of the letters:
50
`}ääç oçèä|
Which is wrong.... And maybe the problem is the char/array - I don't know...So I would be happy if you could help me with that :)
Here is the source code(with some comments):
#include <stdio.h>
#include <conio.h>
#include <wchar.h>
int main()
{
unsigned char array[100], shifting; //creating 2 arrays for the encryption
//I changed it to unsigned char because otherwise Z with key 6/7 dosen't work
int z; //This is our key
printf("This tiny application encodes plain text to the Caesar Encryption\n");
printf("Type in some text to decode :");
fgets(array, 100, stdin); //because gets() is bad I'am using fgets()
printf("Type in the key/shifting of the letters:\n");
scanf("%d", &z);
for (int i = 0; array[i] != '\0'; i++)
{
shifting = array[i]; //overgive values from array to shifting
if (shifting >= 'a' && shifting <= 'z') { //check the containing lowercase letters
shifting = shifting + z;
if (shifting > 'z') {
shifting = shifting - 'z' + 'a' - 1; // if go outside the ascii alphabeth this will be done
}
array[i] = shifting;
}
else if (shifting >= 'A' && shifting <= 'Z') { //the same for uppercase letters
shifting = shifting + z;
if (shifting > 'Z') {
shifting = shifting - 'Z' + 'A' - 1;
}
array[i] = shifting;
}
}
printf("%s\n", array);
return 0;
}
The source of your problem is here:
if (shifting > 'z') {
shifting = shifting - 'z' + 'a' - 1; // if go outside the ascii alphabeth this will be done
}
What's the length of the English alphabet? It's 26.
If you give z greater than 26, a single decrement by the alphabet length does not suffice. You should either make sure z does not exceed the length of alphabet, of repeat decrementing until the result fits the alphabet range.
Solution 1:
int asciiAlphabetLength = 'z' - 'a' + 1;
printf("Type in the key/shifting of the letters:\n");
scanf("%d", &z);
z %= asciiAlphabetLength;
Solution 2:
shifting += z;
while (shifting > 'z') {
shifting -= asciiAlphabetLength; // while outside the ascii alphabeth reduce
}
I am trying to create a program in c language that gets a number and a string, for example the number is 3 and the string is "Zig".
The output should be alphabet's codes + the number. If the character's number goes more than "Z" (90) it should start from "A" again. Similarily, for lower case characters, when going beyond "z" start again from "a".
input : "Zig"
number : 3
output : "Clj"
I have a problem with the part that it should start from A(for capitals) & a again.
this is my code now ! I have a problem with rotation part how to start from A or a again :)
char a[50];
int n,i;
printf("enter your number:\t");
scanf("%d",&n);
printf("enter your string:\t");
fflush(stdin);
gets(a);
while('A'<= a[i] <= 'Z'){
if(a[i]+n > 'Z'){
}
else{
a[i]=a[i]+n;
}
i++;
}
while('a' <= a[i] <= 'z'){
if(a[i]+n > 'z'){
}
else{
a[i]=a[i]+n;
}
i++;
}
printf("string:\n");
puts(a);
}
Fixed Bug
#include <stdio.h>
#include <strings.h>
int main(){
char str [80];
int number;
printf ("Enter your string: ");
scanf ("%79s",str);
printf ("Enter your number: ");
scanf ("%d",&number);
for(int i= 0; i < strlen(str);i++){
str[i]+=number;
while(str[i]>'Z' && str[i] < 'a'){
str[i] = 'A'+ str[i] - 'Z';
}
while(str[i]>'z'){
str[i] = 'a'+ str[i] - 'z';
}
}
printf("%s",str);
}
I have a problem with the part that it should start from A(for capitals) & a again
When you get to Z (decimal 90) you can easily subtract 25 (ASCII char "EM") to get back to A (decimal 65). Similarly you can repeat subtraction of 25 when you reach z and it will cycle back to
I am trying to convert all lowercase to uppercase letter, using the ASCII table! It is very easy to deal and i have figured out the code. Problem is, that if there is a space between the words, then the program will only change the first word and after the space it will not print anything.
Example
Word: Andreas Gives: ANDREAS
Word: TeSt123Ha Gives: TEST123HA
BUT!!!
Word: Hello 45 Gives: HELLO
after the space it prints nothing!
I know that the space in ASCII table is equal to 32, and in my code i tell the program that if the current code that you are reading is not between 97 and 122, then don't perform any changes!
But it is still not working!
char currentletter;
int i;
for (i=0; i<49; i++)
{
currentletter = str[i];
if ((currentletter > 96) && (currentletter < 123))
{
char newletter;
newletter = currentletter - 32;
str[i] = newletter;
}
else
{
str[i] = currentletter;
}
}
printf("%s\n", str);
flipping the 5th lowest bit should help.
Each lowercase letter is 32 + uppercase equivalent. This means simply flipping the bit at position 5 (counting from least significant bit at position 0) inverts the case of a letter.
https://web.stanford.edu/class/cs107/lab1/practice.html
char *str;
int str_size = sizeof(str);
for(int i=0; i<str_size;i++){
if((str[i]>96) && (str[i]<123)) str[i] ^=0x20;
}
You have mentioned in one of the comments that you use scanf("%s", str); to get the string. The problem is that %s will stop scanning once it finds a whitespace character. In your case, it stops scanning when it sees the space character.
Use fgets() if you want to scan one whole line:
fgets(str, sizeof(str), stdin);
Once thing to note here is that fgets will scan in the newline character into the string as well.
Your code can be simplified to:
for (int i = 0; str[i] != '\0'; i++) // Loop until the NUL-terminator
{
if ((str[i] >= 'a') && (str[i] <= 'z')) // If the current character is a lowercase alphabet
str[i] = str[i] - ('a' - 'A'); // See the ASCII table to understand this:
// http://www.asciitable.com/index/asciifull.gif
}
printf("%s\n", str);
Or a more easier way would be to use tolower from ctype.h:
#include <ctype.h>
for(int i = 0; str[i] != '\0'; i++) // Loop until the NUL-terminator
{
str[i] = tolower(str[i]); // Convert each character to lowercase (It does nothing if the character is not an alphabet)
}
printf("%s\n", str);
I gave it a try using STL and a Lambda just for fun:
string input = "";
getline(cin, input);
transform(input.begin(), input.end(), input.begin(), [](char c) { return (c > 96 && c < 123) ? c ^= 0x20 : c; });
copy(input.begin(), input.end(), ostream_iterator<char>(cout, " "));
I compiled and tested with c++ 17 in Visual Studio 2019,
and did not perform exhaustive testing!