plus alphabet kind of - c

first of all, i'm a college freshman. i'd like to help my college task? i would really appreciate if you help my task.
And this task uses C language.
first i need to get two inputs (using scanf; one is alphabet like a or A and the other is arabic number like 1, 2)
and i need to add number on alphabet
ex) if i put
A 3
and the computer indicates D
here is the point, if i put Y 4 i need to get 'C' (using ASCII code and % )
the lower part is what i've tried for this task
int input;
char eng;
scanf("%c %d", &eng, &input);
if (eng >= 'a' && eng <= 'z') {
eng = (eng + input) % ('z' - 'a') + eng -1;
}
it compiles but when i put y 4 it results x however i need c .

You want this:
eng = ((eng - 'a') + input) % ('z' - 'a' + 1) +'a'
(eng - 'a') transforms your input from ['a'..'z'] into the domain [0..25].
+ input adds the offset
% ('z' - 'a' + 1) does the modulo
and finally + 'a' transforms the domain [0..25] back into ['a'..'z']

Related

Is there a way to put multiple ranges in one if statement

I'm new at c and stack overflow please forgive my amateur mistakes if there are some...
I'm trying to accept digits between 0 and 9, uppercase letters and lowercase letters in my code. So ascii codes between 48-57 or 65-90 or 98-122. There is also a previous part of the code containing the menu. I did not include it for brevity.
This is the first thing i tried:
int main()
{
char n;
printf("\n\nWhich code will you use?: ");
scanf("%c",&n);
if (n<=57 && n>=57 || n<=65 && n>=95 || n<=98 && n>= 122)
printf("Binary equivalent..");
/*there is supposed to be a whole another
section here.. however i haven't completed
that yet. I put a print statement to make
sure if the if statement would work...*/
else
printf("Wrong input..");
}
...
This gives the result of "wrong input" whatever i input ( I inputed c, a and 4).
The second thing i tried was to put parenthesis:
...
if ((n<=48 && n>=57 )||( n<=65 && n>=95 )||( n<=98 && n>= 122))
...
Then i tried changing the "%c" to a "%d" which didn't change anything either.
...
printf("\n\nWhich code will you use?: ");
scanf("%d",&n);
...
The only thing that worked was to seperate each relation into three different if statements. However i'm going to be writing the same thing in every if statement which i feel like makes my code unnecessarily long...
You messed up the relations direction, and you could also use the character literals. Try this
if ((n >= '0' && n <= '9') || (n >= 'A' && n <= 'Z' ) || (n >= 'a' && n <= 'z'))
ASCII values
Digits (0-9): 48-57
Uppercase letters (A-Z): 65-90
Lowercase letters (a-z): 97-122
Conditions
c >= 48 && c <= 57: true if c is a digit
c >= 65 && c <= 90: true if c is an uppercase letter
c >= 97 && c <= 122: true if c is a lowercase letter
(c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122): true if c is alphanumeric (a letter or a digit)
But it is much easier to use 'a' instead of 97, because you don't need to learn the whole ASCII table by heart that way.
Notes
n<=48 && n>=57 will always be false. If you pause for a second, you'll realise that no number (in the ASCII table or not) can be less than 48 and greater than 57 at the same time.

How do I use modulo arithmetic to implement caesar cipher

I am trying to perform a wrap around of the ASCII alphabet characters in order to perform a shift from a key. For example, if the key is 2 then shift the letter A to become C. But, how do I wrap around Z in order to get to B using modulus arithmetic?
I am trying to implement the following formula:
ci = (pi + key) % 26;
Where ci is the ith ciphered letter and pi is the ith letter to be ciphered.
I believe you need to work with "relative" values, rather than absolute values.
Use something like
ci = ((pi - 'A' + key) % 26 ) + 'A';
Character integer constants stores the encoded values, in this case, ASCII. Here, 'A' starts from an offset (decimal value of 65), not from 0. So, before you can wrap the result using a % 26 operation, you need to get that offset out. Once the calculation is done, add the offset back to get the proper ASCII representation.
Others have already shown the basic concept of subtracting the offset of ASCII letters, but you have to be careful in when crossing from capital to non capital letters, as there are some symbols in between which I guess you want to avoid. I have added some logic that enables negative shifts and keeps the letter within capital letter or non capital letter space and tests whether it is a letter at all.
#include <stdio.h>
#define ASCII_CAP_LETTER_OFFS 65
#define ASCII_LETTER_OFFS 97
#define NUM_OF_LETTERS 26
char shift_letter (char letter, short shift)
{
char ci;
short shift_lcl = shift % NUM_OF_LETTERS;
if (shift_lcl >= 0)
{ // shift in positive direction
}
else
{ // shift in negative direction
shift_lcl = NUM_OF_LETTERS + shift_lcl;
}
if (letter >= ASCII_CAP_LETTER_OFFS && letter < ASCII_CAP_LETTER_OFFS + NUM_OF_LETTERS)
{// its a capital letter
ci =
(letter + shift_lcl - ASCII_CAP_LETTER_OFFS) % NUM_OF_LETTERS +
ASCII_CAP_LETTER_OFFS;
}
else if (letter >= ASCII_LETTER_OFFS && letter < ASCII_LETTER_OFFS + NUM_OF_LETTERS)
{// its a non capital letter
ci =
(letter + shift_lcl - ASCII_LETTER_OFFS) % NUM_OF_LETTERS +
ASCII_LETTER_OFFS;
}
else
{
printf ("This was not a letter!\n");
ci = 0;
}
return ci;
}
int main ()
{
char test_letter = 'a';
short test_shift = -53;
char shifted_letter = 0;
shifted_letter = shift_letter (test_letter, test_shift);
printf("%c + %d = %c", test_letter, test_shift, shifted_letter);
}
Deeper
ci = ((pi - 'A' + key) % 26) + 'A';
as well answered by #Sourav Ghosh generates the expected encoded A-Z when key is non-negative and not too large. It reduces pi with - 'A' so the value is in the [0...25] range and the re-offsets it after the % calculation.
To work for the full int range of key takes a little more code.
Reduce key range [INT_MIN...INT_MAX] with the functional equivalent range of [-25 ... 25] with key % 26. This step is important to prevent intoverflow with pi - 'A' + key. This can be done once if a number of letters need encoding.
Add 26. This insures negative keys are moved to positive ones.
ci = ((pi - 'A' + key%26 + 26) % 26 ) + 'A';
Note: In C, % is not the mod operator, but the remainder operator. Functional differences occur with a%b when a and/or b are negative. ref

Manipulating array of chars

I'm writing a code in C programming language that receives a string (of chars) as input and each letter advances 3 in the alphabet. E.g. If user types "abc", the program should return "def". The problem is that if the user types 'z' (e.g.), the program returns some char, instead of my goal (which would be this case the letter 'c'). My current algorithm includes this if statement:
if ((text[i]>='a' && text[i]<='w')||(text[i]>='A' && text[i]<='W'))
text[i] = (text[i]) + 3;
But this forces me to write all this lines:
else if (text[i]=='x') text[i]='a';
else if (text[i]=='X') text[i]='A';
else if (text[i]=='y') text[i]='b';
else if (text[i]=='Y') text[i]='B';
else if (text[i]=='z') text[i]='c';
else if (text[i]=='Z') text[i]='C';
How can I optimize my code?
Your problem can be addressed with simple arithmetic logic. The range of char ranges from 0 - 255. Each value corresponds to a separate character. The letters 'A-Z' and 'a-z' range from 65 - 90 and 97 - 122 respectively. So for your problem there are two ranges. You can check with the standard library function that your character falls in upper case or lower case range. then you can set the base for your range. Next you will find the offset of your character from base, add 3 in it. the new value can be made circular using % operator. each range has maximum of 26 characters so you can make your range circular by taking a mod from 26. Now add the resulting value (offset) to the base to get the desired character.
#include <ctype.h>
...
...
...
char c = text[i];
char base = isupper(c)? 'A' : 'a';
text[i] = base + (((c - base) + 3) % 26); // New Desired Character

How can I use the numbers to the right of a decimal point in a double?

My apologies if this question was asked already (I'm assuming that since it's a rather simple question and not because I didn't try to find it first!).
What I was trying to do is build a double number one char at a time.
The numbers to the left were easy with the line num = num * 10 + (c - '0'); /*num being the number built so far and c being the char added*/
but then doing something likenum = (double)((int)num) + ( (num%1)*10 + (c - '0') )/decDigits; //decDigits is the number of digits(including the new one) to the right of the decimal point
wouldn't work because apparently you can't use the % operator on a double.
What'd be the right way to achieve the above?
Are you trying to convert a double to a string, or a string to a double? It looks like the latter, and I don’t think you should be using the % operator in that case at all. Starting at 0.1, multiply each digit’s value by what’s appropriate for its place.
It’s easier to explain in C, though:
char c;
double result = 0.0;
/* The part before the decimal place */
while ((c = *s++) && c != '.') {
result = result * 10.0 + (c - '0');
}
/* The part after the decimal place */
if (c == '.') {
double m = 0.1;
s++;
while ((c = *s++)) {
result += m * (c - '0');
m *= 0.1;
}
}
The modulo operator is not defined for floating points. If you are trying to use num%1 to extract the decimal part of num, you should instead try something like this:
double num_dec = num - floor(num);

Wrapper operation trouble

I am having a terrible time understanding how to get the wrapper to work with these encryption programs. I got a Caesar cipher program to work to both encrypt and decrypt, now I am working on a Vigenere cipher. I have the program working but when I use a key that will cause the letters to wrap around I get odd results. Here is the code I am using:
int main(int argc, char *argv[])
{
char s2[25];
strcpy(s2, argv[1]);
printf("Please enter a string of text to be encrypted!\n");
string p = GetString();
for (int i = 0, n = strlen(p); i < n; i++)
{
if (isupper(p[i])){
char c = (p[i] - 'A' + s2[i]);
printf("%c", c);
}
}
printf("\n");
}
This code will work if the command line input is ./program BACON and I enter BLAH for the text to be encrypted. If for example I use ./program ZZZZZ as the key then I will get all kinds of odd results because it does not wrap back around. I have tried using the modulus operator and have left it out of the code I just posted because I still could not get it to wrap with that. I am just starting to learn programming.
Update
Maybe you can help me understand the math better; your code works perfectly, but I have been trying to figure this out on a calculator manually just to see what's going on. This is what I have so far:
./program HHHHH
keyLen should equal 5 in my understanding and so if I give p[i] a value of "H"
keyLen= 5
p[i]= H //or 72 in ASCII
int sum = (p[i] - 'A') + (s2[i % keyLen] - 'A'); //sum = (72 - '65') + ([72 % 5] - '65');
char c = 'A' + sum%26; // c = 65 + -11
Maybe my math is way off because when I do things in the order I think they should be done sum = negative 63 and so a 26 mod of -63 which gives me negative 11. Which clearly is not right because that equals 54 when you add 65 and negative 11.
Even if I make the negative 11 a positive integer of 11 and add 65 I get 76 which is ASCII character "L" but the right answer is "O". I am clearly doing something wrong but I've been working on the solution for a while now and keep coming up with the same results.
There are two "wrap-around" issues in your program:
Your letters do not wrap around when the key and the current letter combine to produce a value beyond 26, and
You read past the end of the key when the length of the word being encrypted exceeds the length of the key.
Here is how you fix it: right after copying the key into s2, do this:
int keyLen = strlen(s2);
Now inside your loop do this:
int sum = (p[i] - 'A') + (s2[i % keyLen] - 'A'); // Calculate the sum of key+word
char c = 'A' + sum%26; // Wrap around at 26, the number of letters in the alphabet
This will make the output look "normal".
Once you figure out how the last formula works, you should be able to modify it to decode the word.

Resources