Math operation trouble - c

This might seem like a very simple solution to some people but I have been trying to figure it out for a while now and its bugging me.
int sum = (p[i] - 'A') + (s2[i % keyLen] - 'A');
char c = 'A' + sum%26;
I am having trouble coming up with the solution math has never been a strong point of mine. the value of char c should equal 79 at the end of it all if p[i]=72 or 'H' and s2[i]=5.
This operation works wonderfully but I am trying to understand what is going on so I have tried to do it with a normal calculator and keep coming up with the wrong answer. What exactly is the correct order of operations and what should the values be?
Here is the complete source code that I have so far that works:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char s2[25];
strcpy(s2, argv[1]);
int keyLen = strlen(s2);
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])){
int sum = (p[i] - 'A') + (s2[i % keyLen] - 'A');
char c = 'A' + sum%26;
printf("%c", c);
}
}
printf("\n");
printf("%d\n", keyLen);
}
The way I am doing this operation is:
int sum = (p[i] - 'A') + (s2[i % keyLen] - 'A');
//int sum = (72-65) + (72 % 5) - 65) sum= -56
char c = 'A' + sum%26;
//char c = 65 + -56 %26 char c = -8
I obviously know my math is off but I thought I was doing it right when I run the operation through the debugger sum = 14 and char c = 79 or 'O' like it should.

int sum = (p[i] - 'A') + (s2[i % keyLen] - 'A');
//int sum = (72-65) + (72 % 5) - 65) sum= -56
Your misunderstanding is here.
What the code is doing
(s2[i % keyLen] - 'A')
means
(char_from_s2 - 'A')
where char_from_s2 is the character in s2 at index i % keyLen, i.e. the character at position i wrapped around to fit in the length of the string.
What your calculation shows
Your calculation is doing something different:
(char_from_p % keyLen) - 'A'
You're taking the character from p instead of from s2, and applying the % operator to the character value instead of the index.

Related

C program that sums a char with int

I have a given exercise that wants me to find the uppercase letter that is K places from the letter in this case char variable that is named C. The range is uppercase letters from A to Z.
For example if the input is B 3 the output should be E. For this specific input its simple you just sum the values and you get your answer but for example what if we go out of the range. Here is one example F 100 the program should output B because if the value is > than Z the program starts from A.
If there are some confusions I will try to explain it more here are some test cases and my code that only work if we don't cross the range.
Input Output
B 3 E
X 12345 S
F 100 B
T 0 T
#include <stdio.h>
int main(){
int K;
char C,rez;
scanf("%c %d",&C,&K);
int ch;
for(ch = 'A';ch <= 'Z';ch++){
if(C>='A' && C<='Z'){
rez = C+K;
}
}
printf("%c",rez);
return 0;
}
Think of the letters [A-Z] as base 26 where zero is A, one is B and 25 is Z.
As we sum of the letter (in base 26) and the offset, it is only the least significant base 26 digit we have interest, so use % to find the least significant base 26 digit much like one uses % 10 to find the least significant decimal digit.
scanf(" %c %d",&C,&K);
// ^ space added to consume any white-space
if (C >= 'A' && C <= 'Z') {
int base26 = C - 'A';
base26 = base26 + K;
base26 %= 26;
int output = base26 + 'A';
printf("%c %-8d %c\n", C, K, output);
}
For negative offsets we need to do a little more work as % in not the mod operator, but the remainder. This differs with some negative operands.
base26 %= 26;
if (base < 0) base26 += 26; // add
int output = base26 + 'A';
Pedantically, C + K may overflow with extreme K values. To account for that, reduce K before adding.
// base26 = C + K;
base26 = C + K%26;
We could be a little sneaky and add 26 to insure the sum is not negative.
if (C >= 'A' && C <= 'Z') {
int base26 = C - 'A';
base26 = base26 + K%26 + 26; // base26 >= 0, even when K < 0
base26 %= 26; // base26 >= 0 and < 26
int output = base26 + 'A';
printf("%c %-8d %c\n", C, K, output);
}
... or make a complex one-line
printf("%c %-8d %c\n", C, K, (C - 'A' + K%26 + 26)%26 + 'A');
This can be accomplished by using 2 concepts.
ASCII value
Modulus operator (%)
In C every character has an ASCII value. Basically it goes from 0-127.
The character 'A' has the value of 65
The character 'B' has the value of 66 (65 + 1)
and so on...
Until Z which is 65 + 25 = 90
And the 2nd concept I want to highlight in math is modulo arithmetic where if you always want to map a number to certain range, you can use a modulus operator.
Modulus is the reminder that you get after dividing a number by another number.
In our case, we have 26 alphabets so we can always get a number between 0 to 25
For the example you took
100 % 26 = 22
But you have to consider the starting point too.
So, we always subtract the initial alphabet by the value of 'A', i.e. 65 so that 'A' maps to 0 and 'Z' maps to 25
So, if we start with 'F' and need to go 100 places..
Subtract 'A' value from 'F' value. Characters behave like numbers so you can actually store 'F' - 'A' in an integer
In this case 'F' - 'A' = 5
Next we add the offset to this.
5 + 100 = 105
Then we perform modulus with 26
105 % 26 = 1
Finally add the value of 'A' back to the result
'A' + 1 = 'B'
And you are done
Get the remainder of input number with 26 using modulo operator. If sum of input character and remainder is less than or equal to Z then its the answer otherwise again find the remainder of sum with 26 and that will be answer (take care of offset because the ASCII decimal value of letter A is 65).
Roughly the implementation will be:
#include <stdio.h>
int main(){
int K;
char C, rez;
scanf("%c %d",&C,&K);
// Validate the user input
int ch;
int rem = K % 26;
if ((rem + C) - 'A' < 26) {
rez = rem + C;
} else {
rez = ((rem + C - 'A') % 26) + 'A';
}
printf("%c\n",rez);
return 0;
}
Note that, I know there is scope of improvement in the implementation. But this is just to give an idea to OP about how it can be done.
Output:
# ./a.out
B 3
E
# ./a.out
X 12345
S
# ./a.out
F 100
B
# ./a.out
T 0
T

Brute force function for decrypting string in C (Caesar cipher )

I found this problem interesting, as it is given that you need to use the alphabet as an array in C. Task is to brute force every possible K value, in basic Caesar's cipher manner.
However, code I come up with compile non-true values after K = 1. For example, a letter C is turned to Z instead of A etc. Can anyone spot what I did wrong?
#include <stdio.h>
#include <string.h>
void bruteforce (char*);
int main() {
char cyphertext[] = "kyvtrmrcipnzccrkkrtbwifdkyvefikynvjkrkeffe";
bruteforce(cyphertext);
return 0;
}
void bruteforce (char *cyphertext) {
char alphabet[26] = "abcdefghijklmnopqrstuvwxyz";
long int size = strlen(cyphertext);
for (int k = 0; k < 26; k++){
for (long int i = 0; i < size; i++){
for (int j = 0; j < 26; j++){
if (alphabet[j] == cyphertext[i]){
cyphertext[i] = alphabet[j - k];
if (k > j){
cyphertext[i] = alphabet[26 + j - k];
}
break;
}
}
}
printf("%s\n ", cyphertext);
}
}
For Caesar Cypher shifting, you don't need to use the alphabet string. You can just shift the character in ASCII code. ASCII codes of 'a' - 'z' are 97 - 122. Thus if decode with + 1. If the characters are a - z, you can just add one to each character. If after adding the shift value to the character value and the character value become larger than 122 then take the character value and subtract it to 122 then add 96 to that.
For shifting negative, if character value become smaller than 97. Take 97 subtract to character's value. Then subtract 123 to the previous equation value. Nonetheless, I built the code so that negative shift will be convert to positive shift. If the shift is negative we take 26 and add to that. Example is, shifting -1 will make a become z. So that is similar to shifting 26 + -1 = 25.
Shift value can be larger than +25 or smaller than -25. Nonetheless, if it is, it will be modulus to 26.
If you want to bruteforce all the possible combinations for a string. Just use the function below and run it in a loop from 1 to 25. But your function modify the original string. Thus, when doing bruteforce, you would have to copy the string of your function to a temporary string and let the function work on that. The examples are below.
#include <stdio.h>
#include <string.h>
void bruteforce (char *cyphertext, int shiftBy);
int main() {
char cyphertext[] = "kyvtrmrcipnzccrkkrtbwifdkyvefikynvjkrkeffe";
char cyphertext2[] = "yvccf wifd bvmze";
bruteforce(cyphertext, -17);
puts("");
bruteforce(cyphertext2, 9);
/* Bruteforce example */
puts("");
puts("Bruteforce section:");
// +9
char cyphertext3[] = "kyzjkvokzjkfsvtirtb nyrk tre kyzj sv zj zk yvccf nficu";
char temp[50];
for (int i = 1; i < 26; i++){
printf("Trying to crack by shifting %d \n", i );
strcpy(temp, cyphertext3);
bruteforce(temp, i);
puts("");
}
/* End Bruteforce example */
return 0;
}
// If there is no shift i.e 0, 26, 52, -26
// It won't print
void bruteforce (char *cyphertext, int shiftBy){
size_t size = strlen(cyphertext);
if ( shiftBy > 25){
shiftBy = shiftBy % 26;
} else if ( shiftBy < 0 ) {
shiftBy = 26 + (shiftBy % 26);
// If shiftBy is 26
// there is no need to shift.
if ( shiftBy == 26 ) return;
}
// If there is no shift return.
if ( shiftBy == 0 ) return;
for ( size_t i = 0; i < size; i++){
// 97 - 122 is a - z
// if char is a - z
if ( cyphertext[i] > 96 && cyphertext[i] < 123 ){
// add shift by
cyphertext[i] += shiftBy;
// if char > z
// then take char - z then add to the ascii code that just before 'a'.
// Since shiftBy is converted fomr negative to positive.,
// There will not be a negative shiftBy.
if ( (unsigned char)cyphertext[i] > 122 )
cyphertext[i] = ((unsigned char) cyphertext[i]) - 122 + 96;
}
// If want to do A - Z
// ASCII code are 65 - 90.
}
printf("%s\n", cyphertext);
}

C programming : String calculation Using ASCII code [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
If I get the numbers in character string like this and store them in array x[100] and y[100],
x[100] '1' '0' '0' '0' '\0'
y[100] '9' '9' '\0'
The added result should be stored as string, too.
result[100] '1' '0' '9' '9' '\0'
I have tried to use ASCII code to solve this problem, for example:
char number[2] = {'1','2'};
char result;
result = (number[0] - '0') + (number[1] - '0') + '0';
But I am having trouble adjusting digits of x[100] and y[100].
I really need your help :(
You may insist on avoiding the library functions to convert strings to numbers and vice versa, as mentioned by #sjsam.
If you think about it, numbers really start at the LSD (least significant digit, not acid), or on the right side. So start your loop at the last character of each array before the closing \0 and iterate backwards. It won't be trivial, but that's how atoi() works too.
It's rather unfortunate that the Romans started writing from left to right, but that's the root cause of this problem. Otherwise integration of right-to-left Arabic numbers would have been much easier.
Discussing the idiocy of Roman numerals is out of the scope of this answer, let's suffice it to say that their lack of zero prevented any of their programs to finish with a successful exit status, which in turn led to the collapse of the Roman Empire.
Instead of adding byte by byte you may use the functions atoi to convert a string to integer and once you calculate the sum, you may use itoa/snprintf to convert the sum(integer) to its string representation.
See an example below :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char buffer[100];
int no1,no2,no3;
char number1[] = {'1','0','0','0','\0'};
char number2[] = {'9','0','0','\0'};
/* Converting strings to respective integers */
no1=atoi(number1);
no2=atoi(number2);
no3=no1+no2;
/* Convert integer to a null terminated string
* You could also use itoa(no3,buffer,10);
*/
snprintf(buffer,99,"%d",no3);
printf("no1 : %d\n",no1);
printf("no2 : %d\n",no2);
printf("no3 : %s\n",buffer); // printing the string
return 0;
}
itoa is not supported by some compilers, so the best bet is to use snprintf.
Output
Here buffer is a null terminated array
{'1','9','0','0','\0'}
which we have printed using the %s format specifier.
References
itoa manaul.
snprintf manual.
Note
I have set the buffer size to 100 for this example. However, the maximum value of number of bytes that buffer can hold is the depends upon the maximum value an integer(signed in your case) can contain in your system. (Thanks #BLUEPIXY for reminding this stuff. :) )
Sum ASCII numbers while avoiding converting to binary/decimal:
#include <stdio.h>
#include <string.h>
#include <libc.h>
char *sum(char *x, char *y) {
size_t x_idx = strlen(x);
size_t y_idx = strlen(y);
size_t z_idx = MAX(x_idx, y_idx) + 1;
char *z = malloc(z_idx + 1);
char carry = '0';
while (x_idx > 0 || y_idx > 0 || carry == '1') {
char digit = carry;
if (x_idx > 0 && y_idx > 0) {
digit = (x[--x_idx] + y[--y_idx] + carry) % '0' + '0';
} else if (x_idx > 0) {
digit = (x[--x_idx] + carry) % '0' + '0';
} else if (y_idx > 0) {
digit = (y[--y_idx] + carry) % '0' + '0';
}
carry = (digit > '9') ? '1' : '0';
if (carry == '1') {
digit -= 10;
}
z[--z_idx] = digit;
}
while (z_idx > 0) {
z[--z_idx] = ' '; // pad for now; for production, shift array
}
return z;
}
int main(int argc, char* argv[]) {
char *x = argv[1];
char *y = argv[2];
char *z = sum(x, y);
printf("%s + %s = %s\n", x, y, z);
free(z);
}
USAGE
> ./a.out 1000 99
1000 + 99 = 1099
>
> ./a.out 999 999
999 + 999 = 1998
>
#include <stdio.h>
#include <string.h>
int main(void) {
char x[100] = "1000";
char y[100] = "99";
char result[100+1] = " ";
int x_i = strlen(x)-1;
int y_i = strlen(y)-1;
int r_i = 1 + ((x_i > y_i) ? x_i + 1 : y_i + 1);
int carray = 0, sum;
result[r_i] = 0;
while(--r_i>0){
if(x_i >= 0 && y_i >= 0)
sum = x[x_i--] - '0' + y[y_i--] - '0' + carray;
//else if(x_i < 0 && y_i < 0)
// sum = carray;
else if(y_i < 0)// && x_i >= 0){
sum = x[x_i--] - '0' + carray;
else// if (x_i < 0 && y_i >= 0){
sum = y[y_i--] - '0' + carray;
carray = sum > 9;
result[r_i] = sum % 10 + '0';
}
if(carray)
result[0] = '1';
printf("%s\n", result);
return 0;
}
Here's some code that should give you a good idea.
This begins to handle carrying, but doesn't cover all cases.
It should be a good start.
#include <stdio.h>
#include <string.h>
int main(void) {
char y[100] = "1032";
char x[100] = "2399";
int carry = 0;
char* b = (strlen(x) > strlen(y))? x : y;
char* s = (strlen(x) <= strlen(y))? x : y;
for(int i=strlen(s)-1, j=strlen(b)-1; i>=0; --i,--j)
{
b[j] = (b[j]+s[i]+carry-'0');
carry = 0;
if (b[j] > '9')
{
b[j] = (b[j]-'0')%10+'0';
carry = 1;
}
}
puts(b);
return 0;
}

Vigenere Cipher Black Hawk Down

I cannot figure out why this thing doesn't scramble correctly. I read some other posts on this cipher and as far as I can tell I'm using the exact same algorithm as they are...
The areas commented out are tests I tried to make sure everything was passing through correctly. I believe it all goes through correctly then fails in the algorithm.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
string get_message(void);
string scramble(string key, string message);
int main(int argc, string argv[])
{
if(argc == 2)
{
string key;
string message;
key = argv[1];
//printf("KEY: %s<<",key);
message = get_message();
scramble(key, message);
}
else
{
printf("Please enter 2 arguments.\n");
return 1;
}
}
string get_message(void)
{
string message = "";
do
{
message = GetString();
}
while(strlen(message) < 1);
return message;
}
string scramble(string key,string message)
{
for(int i = 0, len = strlen(message), key_len = strlen(key); i < len; i++)
{
int letter = message[i];
//int Tkey = atoi(key[i % key_len]);
//printf("KEY: %d<<\n",Tkey);
if(islower(letter))
{
//printf("KEY(%d)",(key[i % key_len]-97));
letter = (((letter - 97) + (key[i % key_len])) % 26 + 97);
//printf("(%d)",(letter - 97) + (key[i % key_len])%26);
printf("%c",letter);
}
else if(isupper(letter))
{
//printf("(%d)", key[i]);
//printf("(%c)",letter); WE HAVE CORRECT LETTER
letter = (((letter - 65) + (key[i % key_len])) % 26 + 65);
printf("%c",letter);
}
}
printf("\n");
return 0;
}
I think your calculation is wrong:
You currently have
encryptedLetter = (letter - firstLetterOffset) + key[position % keyLength] % 26 + firstLetterOffset
by check the C operator precedence table we notice that % is evaluated before - or +, meaning that your code actually mean :
encryptedLetter = (letter - firstLetterOffset) + ( key[position % keyLength] % 26 ) + firstLetterOffset
Where you wanted :
encryptedLetter = ( (letter - firstLetterOffset) + key[position % keyLength] ) % 26 + firstLetterOffset
Conclusion : you need to put more parenthese to specify in which order you which to evaluate your expression.
In addition you took the letter number for the text character but not for the key !
Correct expression
encryptedLetter = ( (letter - firstLetterOffset) + key[position % keyLength] - firstLetterOffset ) % 26 + firstLetterOffset
Demonstration in javascript

Shift a letter down the alphabet?

I.E., you enter the number 5, and the character A and the output would yield F. I have no idea how to even start to go about this, any give me a push in the right direction?
Individual characters are represented by numbers according to the ASCII code (usually). In C, if you add a number to a character, you're shifting the character down. Try:
char c = 'A';
int n = 5;
printf("%c\n", c + n);
Look at the ASCII table and note the values of the characters.
Try this:
#include <stdio.h>
char shift_char(char val, char shift)
{
val = toupper(val);
assert(isupper(val));
char arr[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return arr[ ( (toupper(val) - 'A' + shift) % 26) ];
}
You can get a little fancier if you want to preserve the case of the character. It also assumes, but does not verify shift is non-negative. That case may cause problems with the modulus operation you will need to guard against... or better yet prevent. Still, since this is tagged as homework, that's the sort of thing you should work through.
If you can assume ASCII, it is easier.
Characters are no more than simple numbers: only the interpretation of said numbers changes. In ASCII all letters are sequential; so the number for 'A' + 5 is the number for 'F'; 'F' - 1 is 'E' ..., ...
int ch = 'J';
ch -= 2; putchar(ch);
ch -= 3; putchar(ch);
ch += 7; putchar(ch); putchar(ch);
ch += 3; putchar(ch);
puts("");
Just pay attention to wrapping!
If you can't assume ASCII, you need to convert characters yourself. Something like:
char charr[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int ndx = 9; /* charr[9] is 'J' */
ndx -= 2; putchar(charr[ndx]);
ndx -= 3; putchar(charr[ndx]);
ndx += 7; putchar(charr[ndx]); putchar(charr[ndx]);
ndx += 3; putchar(charr[ndx]);
puts("");
Do not forget the wrapping
Other people have pointed out that you can use ASCII.
An easy way to handle wrapping is with modulus arithmetic:
char result, ch;
int offset;
... // Populate ch with the letter to be changed and offset with the number.
result = ch - 'a';
result = (result + offset) % 26; // 26 letters in the alphabet
result += 'a';
char shift_char(char c, char shift)
{
if(isalpha(c)) {
if (c>='A' && c<='Z') {
return 'A' + ( (c - 'A' + shift) % 26);
} else if(c>='a' && c<='z') {
return 'a' + ( (c - 'a' + shift) % 26);
}
}
return c;
}

Resources