Circular shift cipher - c

I have written a circular shift cipher for key -1 billion to +1 billion for encrypting messages of maximum 200 characters including 0 to 9, a to z and A to Z.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char input[215], key[11], msg[201], output[201], ch;
int i, j, k, shiftkeychar, shiftkeynum;
printf("Input: ");
gets(input);
for (i = 0; input[i] != ':'; i++)
key[i] = input[i];
key[i] = '\0';
i++;
k = 0;
for (j = i; input[j] != '\0'; j++) {
msg[k] = input[j];
k++;
}
msg[k] = '\0';
printf("\nmessage: %s\n", msg);
printf("key: %s\n", key);
shiftkeychar = atoi(key) % 26;
shiftkeynum = atoi(key) % 10;
printf("shiftkey for characters: %d\n", shiftkeychar);
printf("shiftkey for numbers: %d\n", shiftkeynum);
strcpy(output, msg);
for (i = 0; output[i] != '\0'; i++) {
ch = output[i];
if (ch >= 'A' && ch <= 'Z') {
ch = ch + shiftkeychar;
if (ch > 'Z') {
ch = ch - 'Z' + 'A' - 1;
}
else if (ch < 'A') {
ch = ch + 'Z' - 'A' + 1;
}
}
else if (ch >= 'a' && ch <= 'z') {
ch = ch + shiftkeychar;
if (ch > 'z') {
ch = ch - 'z' + 'a' - 1;
}
else if (ch < 'a') {
ch = ch + 'z' - 'a' + 1;
}
}
else if (ch >= '0' && ch <= '9') {
ch = ch + shiftkeynum;
if (ch > '9') {
ch = ch - '9' + '0' - 1;
}
else if (ch < '0') {
ch = ch + '9' - '0' + 1;
}
}
output[i] = ch;
//printf("output[%d]: %c", i, ch);
}
printf("Output: %s", output);
return 0;
}
This Circular shift cipher is working well for Capital letters and digits. However for small letters e.g. if message is 'xyz' and key is more than 5 (i.e., 6,7,...25) its generating some arbitrary output. input format is: "key:message". output is:"encrypted message".

Your character ch is a char, which in C may or may not be signed. On your machine, it seems to be signed, which means that you can store values from −128 to 127. The lower-case letters occupy the ASCII codes from 97 to 122. When you say:
ch = ch + shiftkeychar;
you may overflow the signed char for letters at the back of the alphabet. Technically, this is undefined behaviour; in practice you will probably get negative values, which will lead to strange characters later on.
To resolve your problem, make ch an int.

Related

Why does encryption code gives question mark while text contains the letters after s and key is 13?

So, I am writing an encryption code. My code takes the word or any message and also asks user to enter a key. The end output is the encrypted message. For example:
Please enter the text you want to encrypt: hello
Enter the key: 4
The encrypted text is: lipps
But there is a problem. When I enter text that contains an s inside, it gives a question mark for the encryption:
Please enter the text you want to encrypt: ssss
Enter the key: 13
The encrypted text is: ����
This problem doesn't occur when I write other keys than 13, and if the letter is uppercase. This problem happens when the text contains any letter that comes after s (t, v, u, w, x, y, z) and when the key is 13.
Aforementioned code is:
#include <stdio.h>
#include <string.h>
int main(void) {
int i;
int key;
char text[101], ch;
printf("Please enter the text you want to encrypt: ");
fgets(text, sizeof(text), stdin);
printf("Enter the key: ");
scanf("%i", &key);
for(i = 0; text[i] != '\0'; ++i){
ch = text[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch + key;
if(ch > 'z'){
ch = ch - 'z' + 'a' - 1;
}
text[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + key;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
text[i] = ch;
}
}
printf("The encrypted text is: %s", text);
}
The problem lies in the line ch = ch + key; when you have values for ch and key whose sum is greater than that which can be stored in a char variable. For example, for the character, 's' (ASCII value 115) and a key of 13, the sum is 128 - which overflows an 8-bit signed char (max value 127) and results in a negative number.
The problem is much less likely to occur for uppercase characters (unless you have a very big value for key), as their ASCII values are significantly lower ('A' thru 'Z' are 65 … 90, whereas 'a' thru 'z' are 97 … 122).
To fix the issue, make the 'temporary' ch variable an int and cast it back to a char after all calculations are complete:
#include <stdio.h>
#include <string.h>
int main(void)
{
int i, ch; // Use an int for our temporary "ch" variable
int key;
char text[101];
printf("Please enter the text you want to encrypt: ");
fgets(text, sizeof(text), stdin);
printf("Enter the key: ");
scanf("%i", &key);
for (i = 0; text[i] != '\0'; ++i) {
ch = text[i];
if (ch >= 'a' && ch <= 'z') {
ch = ch + key;
if (ch > 'z') {
ch = ch - 'z' + 'a' - 1;
}
text[i] = (char)ch; // Cast the int to a char to avoid compiler warnings
}
else if (ch >= 'A' && ch <= 'Z') {
ch = ch + key;
if (ch > 'Z') {
ch = ch - 'Z' + 'A' - 1;
}
text[i] = (char)ch;
}
}
printf("The encrypted text is: %s", text);
return 0;
}

why the program omitted some lines? (c program to encrypt text)

i am trying to make a program that encrypt text with a Caesar cipher.The number of positions to shift will be given to the program as a command line argument and characters other than letters should not be encrypted. The program should stop only at the end of input. My issue is that the program omit the lines that mod the number. the program is run on a platform that provided by my school, i am not sure what it is. please kindly help me to fix the program.
here is my program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char *argv[] ) {
int num = atoi(argv[1]);
char caesar[100];
char ch;
int shift = num%26;
while ( fgets(caesar, 100, stdin) != NULL){
for(int i = 0; i < strlen(caesar); i++){
ch = caesar[i];
if( ch >= 97 && ch <= 122){
if( ch + shift < 97){
ch = ch + shift + 26;
}
else if( ch + shift > 122){
ch = ch + shift - 26;
}
else{
ch = ch + shift;
}
caesar[i] = ch;
}
else if( ch >= 65 && ch <= 90){
if( ch + shift < 65){
ch = ch + shift + 26;
}
else if( ch + shift > 90){
ch = ch + shift - 26;
}
else{
ch = ch +shift;
}
caesar[i] = ch;
}
}
}
printf("%s", caesar);
return 0;
}
here is some examples which have correct output
here is what my program did. the program ignored shift = num%26 and i can't figure out why

Conversion of hexadecimal string constant to decimal value using C

The following program gives the result as 0 instead of the expected decimal equivalent of the hexadecimal string constant.
#include <stdio.h>
int my_htoi(char[]);
int main(void) {
printf("%d", my_htoi("0xABC"));
return 0;
}
int my_htoi(char str[]) {
int i, num = 0;
for (i = 0; i != '\0'; ++i) {
if (str[i+1] == 'x' || str[i+1] == 'X') {
i = i + 1;
continue;
}
if (str[i] >= '0' && str[i] <= '9') {
num = num * 16 + (str[i] - '0');
} else if (str[i] >= 'a' && str[i] <= 'f') {
num = num * 16 + (str[i] - 'a' + 10);
} else if (str[i] >= 'A' && str[i] <= 'F') {
num = num * 16 + (str[i] - 'A' + 10);
}
}
return num;
}
While the following program runs fine and outputs the correct decimal equivalent of the hexadecimal string constant.
#include <stdio.h>
#include <string.h>
int my_htoi(char[]);
int main(void) {
printf("%d", my_htoi("0xABC"));
return 0;
}
int my_htoi(char str[]) {
int i, num = 0;
for (i = 0; i < strlen(str); ++i) {
if (str[i+1] == 'x' || str[i+1] == 'X') {
i = i + 1;
continue;
}
if (str[i] >= '0' && str[i] <= '9') {
num = num * 16 + (str[i] - '0');
} else if (str[i] >= 'a' && str[i] <= 'f') {
num = num * 16 + (str[i] - 'a' + 10);
} else if (str[i] >= 'A' && str[i] <= 'F') {
num = num * 16 + (str[i] - 'A' + 10);
}
}
return num;
}
The only difference is in the way we find the qualifying condition for the loop. Why does it not work with the null byte checking?
Wrong code: i != '\0' checks if the index is 0.
for(i = 0; i != '\0'; ++i) {
Should be the below to check if the element str[i] is the null character.
for(i = 0; str[i] != '\0'; ++i) {
Other issues exists unneeded increment, int overflow (better to use unsigned here), wrong x detection - consider "0x0x0x1", leading - or +, char str[] --> const char str[], ...
There are some problems in your code:
the loop index i is compared to '\0' instead of str[i], causing immediate termination of the loop with a return value of 0.
the test for x is incorrect: it would cause "1x2" to convert to 2 instead of 1.
you accept letters beyond f and convert them to digits. The function should instead stop parsing at the first character that is not a hex digit.
Here is a corrected version:
#include <stdio.h>
int my_htoi(const char[]);
int main(void) {
printf("%d", my_htoi("0xABC"));
return 0;
}
int my_htoi(const char str[]) {
int i = 0, num = 0;
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
i += 2;
for (; str[i] != '\0'; ++i) {
if (str[i] >= '0' && str[i] <= '9') {
num = num * 16 + (str[i] - '0');
} else if (str[i] >= 'a' && str[i] <= 'f') {
num = num * 16 + (str[i] - 'a' + 10);
} else if (str[i] >= 'A' && str[i] <= 'F') {
num = num * 16 + (str[i] - 'A' + 10);
} else {
break;
}
}
return num;
}

Caesar Cipher Negative Numbers Issue

I'm trying to write a caesar cipher program that takes an argument, converts it into an integer, and uses that as to shift the letters in a certain direction (positive numbers shift it forward and negative numbers shift it backwards. So far all the program works for all positive numbers but does not for negative numbers.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int encrypt(int character, int shift);
int main(int argc, char * argv[]) {
int shift = atoi(argv[1]);
if (shift >= 26) {
shift = ((shift + 26) % 26);
}
int character = getchar();
while (character != EOF) {
int new_character = encrypt(character, shift);
putchar(new_character);
character = getchar();
}
return 0;
}
int encrypt(int character, int shift) {
int ch = character;
int negShift = shift;
if (ch >= 'a' && ch <= 'z') {
ch = ch + shift;
if (ch > 'z') {
ch = ch - 'z' + 'a' - 1;
}
} else if (ch >= 'A' && ch <= 'Z') {
ch = ch + shift;
if (ch > 'Z') {
ch = ch - 'Z' + 'A' - 1;
}
}
return ch;
}
You could just add the 26 to ch when ch < 'a' or ch <'A'.
Consider below example.
if(ch < 'a')
{
ch = ch + 26;
}
Full code.
int encrypt(int character, int shift) {
int ch = character;
int negShift = shift;
if (ch >= 'a' && ch <= 'z') {
ch = ch + shift;
if (ch > 'z') {
ch = ch - 'z' + 'a' - 1;
}
else if(ch < 'a')
{
ch = ch + 26; //Here
}
} else if (ch >= 'A' && ch <= 'Z') {
ch = ch + shift;
if (ch > 'Z') {
ch = ch - 'Z' + 'A' - 1;
}
else if(ch < 'A')
{
ch = ch + 26; // Here
}
}
return ch;
}

Get whole number from input using only getchar() and convert to int

For a school assignment i have to make a C program that reads a whole number, that may be preceded by a '+' or '-'. i can only use getchar().
I can convert a single char to an int using int i = ch - '0' but I want to read in multiple chars. besides that I need to check if the input is correct (eq. no not-numerical charachters)
I have this so far:
int main(void) {
int i;
char ch;
printf("voer een getal in: ");
while ((ch = getchar()) != '\n') {
i = ch - '0';
}
printf("het ingevoerde getal is: %d\n", i);
return EXIT_SUCCES;
}
Edit: I get that this isn't really the place for problems like this (I should learn to fix it myself, not get others to fix it for me) but I didn't know what to do anymore. thanks you for guiding me to the right path
This should get you started:
int main(void) {
int i = 0;
int ch;
printf("voer een getal in: ");
while ((ch = getchar()) != '\n') {
if (ch > '9' || ch < '0')
continue; // or print an error and exit
i *= 10;
i += ch - '0';
}
printf("het ingevoerde getal is: %d\n", i);
return EXIT_SUCCES;
}
I'll leave detecting the potential + / - sign as an exercise.
If your school allows you to use shift operators then here is a quick way to get integer from the user and as per their requirements you can show the + or - sign preceding the integer. But remember not to just copy paste it. Understand the code first.
int main(){
int i = 0;
char c;
char sign = 43;
printf("voer een getal in:\n");
c = getchar();
if(c == 45)
sign = 45;
for(; (c<48 || c>57); c = getchar());
for(; c>47 && c<58 ; c = getchar()){
i = (i<<1) + (i<<3) + c - 48;
}
printf("het ingevoerde getal is: %c%d\n",sign, i);
return 0;
}
Reading in multiple characters, and determine whether positive, negative, and value:
int sign = 1;
ch = getchar(); //look at first char (might be a sign indicator)
if((ch == '-') || (ch == '+')) //consume first char if either `-` or `+`
{
if(ch == '-') sign = -1;
}
else //first char non-sign - handle as digit
{
if (ch > '9' || ch < '0')
continue; // or print an error and exit
i *= 10;
i += ch - '0';
}
while ((ch = getchar()) != '\n') //get remaining chars (assume no embedded sign chars)
{
if (ch > '9' || ch < '0')
continue; // or print an error and exit
i *= 10;
i += ch - '0';
}
i *= sign; //apply sign to value
I think this will work.
while ((ch = getchar()) != '\n') {
i = ch - '0' + i * 10;
The problem in your code is that you are overwriting i every time you read a new character. You need to store the digit you read, and then add to it.
You should take care about not number characters :
while((ch=getchar()) != '\n')
if(ch >= '0' && ch <= '9')
i += 10* i + (ch - '0');
For the '-' or '+' at the begining you could store the first getchar(). A solution could be :
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int i = 0;
char ch,first_ch;
printf("voer een getal in: ");
ch = first_ch = getchar();
while (ch != '\n') {
if(ch >= '0' && ch <= '9')
i = 10* i + (ch - '0');
ch = getchar();
}
if(first_ch == '-')
i *= -1;
printf("het ingevoerde getal is: %d\n", i);
return EXIT_SUCCESS;
}

Resources