Decryption - Get back the number after splitting C programming - c

I've just did an encryption using a simple C code. The encryption works like this, "Your application should read a 4 digit integer entered by the user and replace each digit with the result of adding 7 to the digit and getting the remainder after diving the new value by 10:
Let say I've entered 1234, the value after encryption will be 8,9,0,1.
I'm doing the encryption with the following code below:
num1 = ((digits/1000) + 7) % 10;
num2 = ((digits/100) + 7) % 10;
num3 = ((digits/10) + 7) % 10;
num4 = ((digits/1) + 7) % 10;
Now I would like to do a decryption, getting back the value I've entered. I'm wondering if I'm able to do a reverse modulo? A backwards calculation for %?
Meaning if a = 3 + 4, a = 7.. So what is 7 = b + 4 which is b = 7-4. I'm
What I've attempted so far is this:
dNum1= (digits/1000) % 10;
dNum2= (digits/100) %10;
dNum3= (digits/10) %10;
dNum4= (digits % 10) ;
The question is now: How do I retrieve the original value from the decrypted value(8,9,0,1)? (Original Value: 1234)

Since you encoded each digit by adding 7, you need to decode by subtracting 7. Then if the value is negative, add 10 to get back the expected value.
num1 = (digits/1000) - 7;
num2 = (digits/100) - 7;
num3 = (digits/10) - 7;
num4 = (digits % 10) - 7;
if (num1 < 0) num1+=10;
if (num2 < 0) num2+=10;
if (num3 < 0) num3+=10;
if (num4 < 0) num4+=10;
EDIT:
Better yet, you can add 3 and then mod by 10, which does the same thing. Thanks to psmears for suggesting this.
num1 = ((digits/1000) + 3) % 10;
num2 = ((digits/100) + 3) % 10;
num3 = ((digits/10) + 3) % 10;
num4 = ((digits/1) + 3) % 10;
EDIT2:
If you're translating the decoded digits directly from the encoded digits without moving the values back to digits first, do this:
dNum1 = (num1 + 3) % 10;
dNum2 = (num2 + 3) % 10;
dNum3 = (num3 + 3) % 10;
dNum4 = (num4 + 3) % 10;

that's an interesting question #stack. One thing I see is that you are using individual statements to assign values to num1,num2,num3,num4
but every encryption follows a defined pattern and implicit is that
every decryption does
And if you are successful in finding such pattern(Which I prefer to say mystery!), then these kind of encryption are near solved!
So I decided to find the pattern and I was successful in finding it for your encryption. ones you find pattern, for loop is very useful to repeat the process and thus encode given number.(same for the decoding too)
Note: I Don't know whether you require such a solution, but this is more useful as there are less number of variables which is a characteristic of any good program. and this code is only for 4 digit numbers... feel free to ask me if you want to extend it to n digited numbers :)
so! Here is my code:
#include<stdio.h>
#include<math.h>
int main()
{
//encryrption
int num,num1,i,e=0,d=0;
printf("enter 4 digit number:\n");
scanf("%d",&num);
num1=num;
for(i=3;i>=0;i--)
{
num1=(num)/(pow(10,i));
num1=(num1+7)%10;
e=(10*e)+num1;
}
printf("encryption = %d\n",e);
//decryption:
for(i=3;i>=0;i--)
{
num1=e/pow(10,i);
num1=((num1-7)%10);
d=(10*d)+num1;
}
printf("decryption = %d",d);
return 0;
}

Related

Attempting to run Luhn's Algorithm in C

So, I'm trying to make Luhn's algorithm in C, but it doesn't return the correct values when running it.
//Luhn's Algorithm
int tsum = 0;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
else
if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
tsum %= 10;
I have spent hours trying to troubleshoot and find the issue, count represents the number of digits in the card number, the rest define themselves.
I would appreciate somebody to tell me what I'm doing wrong, thank you.
EDIT: Apologies, cardNum is a long long. And I am expecitng a value of 0 for tsum when inputting any card number from Paypal's Standard Test Cards. I would also like to add, in my mind what this code should do is: using the checks for even and odd it will start from the rightmost digit and add it to tsum, every other digit will do the same. Then starting from the 2nd rightmost digit, the digit is multiplied by 2 then added to tsum, with every other digit doing the same. Then, the last line will check the rightmost digit of the current tsum and will tell me if the card is valid according to Luhn's Algorithm.
Here is what I usually do if I "try to implement" something I am not sure about: I use an interactive language, such as Common Lisp, tinker and test interactively until it works. Then, I usually have some good template I can use to write it in a less powerful language such as C.
(defun luhn-method (n)
(mod
(loop
for x = n then (floor x 10)
while (> x 0)
for double = nil then (not double)
for digit = (mod x 10)
for factor = (if double 2 1)
for y = (let ((a (* digit factor)))
(if (> a 9) (- a 9) a))
do (format t "~%~a" (list :x x :double double :digit digit :factor factor :y y))
summing y)
10))
I did this just from reading the wikipedia page about Luhn method (the german wiki page is easier to understand because it shows a simple exampple, while being less verbose than the english version).
From your Paypal site, the first number produces
(luhn-method 378282246310005)
(X 378282246310005 DOUBLE NIL DIGIT 5 FACTOR 1 Y 5)
(X 37828224631000 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 3782822463100 DOUBLE NIL DIGIT 0 FACTOR 1 Y 0)
(X 378282246310 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 37828224631 DOUBLE NIL DIGIT 1 FACTOR 1 Y 1)
(X 3782822463 DOUBLE T DIGIT 3 FACTOR 2 Y 6)
(X 378282246 DOUBLE NIL DIGIT 6 FACTOR 1 Y 6)
(X 37828224 DOUBLE T DIGIT 4 FACTOR 2 Y 8)
(X 3782822 DOUBLE NIL DIGIT 2 FACTOR 1 Y 2)
(X 378282 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 37828 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 3782 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 378 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 37 DOUBLE T DIGIT 7 FACTOR 2 Y 5)
(X 3 DOUBLE NIL DIGIT 3 FACTOR 1 Y 3)
0
making it easy to see every single step of the algorithm and convincing yourself it is correct.
To port this to C, first we need to explore, if C has an integer type wide enough for those credit card numbers (lisp has large integers by default - one thing less to worry about in our prototype). Lisp again:
(log 378282246310005 2)
48.426456
So, we need a 64 bit variable and should be good.
Since integers in C are implementation/platform/system specific, we should use some header file, giving us the correct type:
#include <stdint.h>
In there, the 64 bit unsigned integer is defined as uint64_t and if your compiler and your header files are correct for your system, using that makes sure, you do not get it wrong. The native "unsigned long long" etc. are just guesswork and not portable.
With that in place, we can simply port the code above to C:
uint64_t luhn(uint64_t n) {
uint64_t x = n;
uint64_t sum = 0;
uint64_t factor = 1;
while (x > 0) {
uint64_t y = (x % 10) * factor;
if (y > 9)
y = y - 9;
sum += y;
x = x / 10;
if (1 == factor) {
factor = 2;
} else {
factor = 1;
}
}
return sum % 10;
}
Summary:
A proper tool set helps getting stuff done. If you don't know yet, how to use a C debugger and step through code line by line while watching the content of variables, an interactive programming language is probably easier for you for prototyping.
Thank you for your help, I was able to solve this issue as it seems I had missed a step in Luhn's Algorithm.
//Luhn's Algorithm
int tsum = 0;
int luhn;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
else if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
tsum %= 10;
Here, I defined luhn as the next integer to be added to the tsum, in doing this I was able to fill in the missing step by subtracting 9 before adding to tsum if luhn exceeded 9.

How to add product digits rather than products themselves in C?

I am trying to finish an assignment in C for the CS50 course in which I must implement Luhn's algorithm to validate a credit card number. Here is a quick example to elaborate:
credit card number: 4003600000000014.
Now for every other digit, starting with the number’s second-to-last digit:
1-0-0-0-0-6-0-4
Let’s multiply each of the digits by 2:
1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2
That gives us:
2 + 0 + 0 + 0 + 0 + 12 + 0 + 8
Now let’s add those products’ digits (i.e., not the products themselves) together:
2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
Now let’s add that sum (13) to the sum of the digits that weren’t multiplied by 2 (starting from the end):
13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20
Yup, the last digit in that sum (20) is a 0, so the number is valid.
I figured out how to extract each number in the credit card individually (I know my way is boring and probably not practical), so the next step is to multiply every other number by two and add (the products' digits, not the digits themselves) and this is what I need help of how to do it?
MY code:
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
long credit_card_number;
do
{
credit_card_number = get_long("Enter your credit card number: ");
}
while (credit_card_number < 1 || credit_card_number > 9999999999999999);
//American Express uses 15-digit numbers. American Express numbers start with 34 or 37
//MasterCard uses 16-digit numbers. MasterCard numbers start with 51, 52, 53, 54, or 55.
//Visa uses 13- and 16-digit numbers. Visa numbers start with 4.
// checksum
long last_number;
long credit_card_without_last_number;
long second_to_last_number;
long credit_card_without_second_number;
long third_number;
long credit_card_without_third_number;
long fourth_number;
long credit_card_without_fourth_number;
long fifth_number;
long credit_card_without_fifth_number;
long sixth_number;
long credit_card_without_sixth_number;
long seventh_number;
long credit_card_without_seventh_number;
long eighth_number;
long credit_card_without_eighth_number;
long ninth_number;
long credit_card_without_ninth_number;
long tenth_number;
long credit_card_without_tenth_number;
long eleventh_number;
long credit_card_without_eleventh_number;
long twelfth_number;
long credit_card_without_twelfth_number;
long thirteenth_number;
long credit_card_without_thirteenth_number;
long fourteenth_number;
long credit_card_without_fourteenth_number;
long fifteenth_number;
long credit_card_without_fifteenth_number;
long sixteenth_number;
long multiply_digits;
//separating each number starting from the last (right)in its own variable.
last_number = credit_card_number % 10;
credit_card_without_last_number = credit_card_number / 10;
second_to_last_number = credit_card_without_last_number % 10;
credit_card_without_second_number = credit_card_without_last_number / 10;
third_number = credit_card_without_second_number % 10;
credit_card_without_third_number = credit_card_without_second_number / 10;
fourth_number = credit_card_without_third_number % 10;
credit_card_without_fourth_number = credit_card_without_third_number / 10;
fifth_number = credit_card_without_fourth_number % 10;
credit_card_without_fifth_number = credit_card_without_fourth_number / 10;
sixth_number = credit_card_without_fifth_number % 10;
credit_card_without_sixth_number = credit_card_without_fifth_number / 10;
seventh_number = credit_card_without_sixth_number % 10;
credit_card_without_seventh_number = credit_card_without_sixth_number / 10;
eighth_number = credit_card_without_seventh_number % 10;
credit_card_without_eighth_number = credit_card_without_seventh_number / 10;
ninth_number = credit_card_without_eighth_number % 10;
credit_card_without_ninth_number = credit_card_without_eighth_number / 10;
tenth_number = credit_card_without_ninth_number % 10;
credit_card_without_tenth_number = credit_card_without_ninth_number / 10;
eleventh_number = credit_card_without_tenth_number % 10;
credit_card_without_eleventh_number = credit_card_without_tenth_number / 10;
twelfth_number = credit_card_without_eleventh_number % 10;
credit_card_without_twelfth_number = credit_card_without_eleventh_number / 10;
thirteenth_number = credit_card_without_twelfth_number % 10;
credit_card_without_thirteenth_number = credit_card_without_twelfth_number / 10;
fourteenth_number = credit_card_without_thirteenth_number % 10;
credit_card_without_fourteenth_number = credit_card_without_thirteenth_number / 10;
fifteenth_number = credit_card_without_fourteenth_number % 10;
credit_card_without_fifteenth_number = credit_card_without_fourteenth_number / 10;
sixteenth_number = credit_card_without_fifteenth_number % 10;
//Here I need the help to multiply these numbers by two and then add each product's
//digits to the rest of the unused numbers.
multiply_digits = (second_to_last_number*2)+(fourth_number*2)+(sixth_number*2)+(eighth_number*2)+(tenth_number*2)+(twelfth_number*2)+(fourteenth_number*2)+(sixteenth_number*2);
}
Try doing this instead
int main(){
long cNo = 4003600000000014;
int arr[16];
for(int i=0; i<16; i++){
arr[15-i] = cNo % 10;
cNo /= 10;
}
int multipliedSum = 0;
for(int i=0; i<16; i++){
if(i%2==1)
multipliedSum += arr[i];
else{
if(arr[i]*2<10){
multipliedSum += (arr[i]*2);
}else{
int num = arr[i]*2;
while(num){
multipliedSum += num%10;
num/=10;
}
}
}
}
printf("valid = %s\n",multipliedSum%10==0?" True": " False");
}
You will get the following
valid = True
A general algorithm for adding digits (assuming an integer type):
Initialize your sum to 0: sum = 0
Extract the lowest digit from the number using the % modulus operator: digit = number % 10
Add the value of that digit to the sum: sum += digit (shorthand for sum = sum + digit)
Divide the number by 10: number /= 10 (shorthand for number = number / 10
If the number is non-zero after dividing by 10, go back to 2
End
The modulus operator % returns the integer remainder of an integer division - 123 / 10 == 12 rem 3. So the remainder of dividing the number by 10 is the least significant decimal digit of the number. Notice that integer division gives you an integer result - 123 / 10 == 12, not 12.3.
You'll want to put this in a separate function, so you can write something like
int sumdig( int v )
{
...
}
int main( void )
{
int value = 123;
int sum = sumdig( value ); // sumdig will return 1 + 2 + 3, or 6
...
}
When you find yourself creating a bunch of separate variables of the same type with the same name except for some tacked-on ordinal (var1, var2, var3 or first_thing, second_thing, third_thing), that's a real strong hint you want to use an array. You can use an array to store the individual digits of your card number:
int number[16];
and use the % 10 method as described above to extract the individual digits:
long tmp = credit_card_number; // use a temporary so we preserve the original card number
for ( int i = 0; i < 16; i++ )
{
number[i] = tmp % 10;
tmp /= 10;
}
This means that the least significant (rightmost) card number digit will be stored in number[0] and the most significant (leftmost) card number digit will be stored in number[15], so be aware of that. For the purposes of validating the number it doesn't matter, but if you want to display the contents of the array you'll have to take that into account.
Using an array makes it easier to extract subsets of digits:
for ( int i = 1; i < 16; i += 2 ) // hit every other element starting at element 1
{
number[i] *= 2; // multiply these digits by 2
}
That loop above executes the "1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2" portion of your algorithm.
You should be able to figure out the rest from there. Hope this helps.
Hint: to extract one digit from a number, mod it by 10.
So say that you want to figure out the sum of the digits of a number, say 123456, you will do the following:
(pseudocode)
number=123456;
sum=0;
loop if number is not 0{
sum+=number % 10;
number-=number % 10;
number=(int)(number/10);
}
Now try to implement it as a function, say digit(), and when you are trying to add some numbers digit-wise, say 123 and 456, just do digit(123)+digit(456) instead.

Decrypt a 4-digit number

I just made a simple program in C that takes a 4-digit code and encrypts every digit (previously decomposed, that goes from 0 to 9) using this easy algorithm:
new_num1 = (old_num1 + 7) % 10;
new_num2 = (old_num2 + 7) % 10;
new_num3 = (old_num3 + 7) % 10;
new_num4 = (old_num4 + 7) % 10;
Now I want to make a decrypt.c program to decrypt 4-code digit previously encrypted.
In which way I can revert the number?
This is my code for crypter.c (in this example I also revert the first digit with third and second with fourth)
#include <stdio.h>
int main()
{
int codice;
int num1, num2, num3, num4, temp1, temp2, new_num1_temp, new_num2_temp;
printf("\n(LOLCrytter v0.1)\n\nInsert 4-digit code to crypt: -1 to exit ");
scanf("%d", &codice);
if(codice == -1)
return 0;
while(codice < 1000 || codice > 9999) {
printf("\nInsert NUMERIC (!) 4-digit code bru..: ");
scanf("%d", &codice);
}
// Get every digit by logic math and not by strings functions
temp1 = codice;
num1 = temp1 / 1000;
temp2 = temp1 % 1000;
num2 = temp2 / 100;
temp1 = temp2 % 100;
num3 = temp1 / 10;
num4 = temp1 % 10;
// Crypting...
num1 = (num1 + 7) % 10;
num2 = (num2 + 7) % 10;
num3 = (num3 + 7) % 10;
num4 = (num4 + 7) % 10;
// Crypting...
new_num1_temp = num3;
num3 = num1;
num1 = new_num1_temp;
new_num2_temp = num4;
num4 = num2;
num2 = new_num2_temp;
printf("\nNew code: %d%d%d%d\n\n", num1, num2, num3, num4);
return 0;
}
if input restricted to [0..9] (as code shows at the moment of the answer) then it will work: encryption of 8 is (8 + 7) % 10 = 5. Decryption is 10 + 5 - 7 = 8.
your custom algorithm in general: encryption of x is (x + 7) % m == r; decryption is: m + r - 7 == x
But author in question wants to "decrypt a 4-digit number" and just in case I need to make a caution if author considers changing the code: Mod operation is not bijection - it is not reversible: (0 + 7) % 10 = 7; (10 + 7) % 10 = 7.
if algorithm's input is only from range 0..9 then , for instance: 10 % 7 = 3; 7*1 + 3 = 10. That is 7 * (10 / 7) + 3 = 10. Every number a can be represented as a = m * (a/m) + r; where m is modulus, r - remainder. "/" integral devision.
Function of form (k + n) mod m is good for hash functions, used for random numbers generation. If you want to use simple encryption for learning you can achieve better results with minimum efforts - use XOR. Generate key and XOR it with plain text. To decrypt XOR encrypted text with the same key. Read about One-time pad One-time pad - very simple in implementation encryption technique but that cannot be cracked.
UPDATED: As cryptographer I would recommend you (if you are interested in learning basics of cryptography) starting to learn and implement classical simple crypto algorithms like: Caesar cipher, simple substitution, Vigener cryptosystem (they are available in wikipedia).
Your crypto function (t + 7) % 10 is very similar to Caeser educational cipher with some changes:
The encryption can be represented using modular arithmetic by first transforming the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25. Encryption of a letter x by a shift n can be described mathematically as,
Decryption is performed similarly,
Goog luck!

Generating random numbers in conditions

I'm trying to generate three random numbers in three conditions and the three numbers must be from 0 to 100:
an odd number
an even number
a number larger than 50
Here is my code:
#include <stdio.h>
#include <time.h>
int main (void) {
int num1 = 0, num2 = 0, num3 = 0;
srand(time(NULL));
num1 = rand() % 100;
while (num1 % 2 != 0) {
num1 = rand() % 100;
}
num2 = rand() % 100;
while (num2 % 2 == 0) {
num2 = rand() % 100;
}
num3 = rand() % 100;
while (num3 > 50) {
num3 = rand() % 100;
}
printf("your numbers\n%d\n%d\n%d\n", num1, num2, num3);
return 0;
}
the compiler answers me:
warning: implicit declaration of function 'srand' [-Wimplicit-function-declaration]
srand(time(NULL));
and I do have stand in the requirements of the school:
it must be in loops
I cannot use break nor TRUE nor FALSE
Your srand() issue is simply because you haven't included stdlib.h, where that call (and rand() for that matter) is declared.
In any case, there's no real need to use a loop while discarding "invalid" numbers, you can use math for this :-) (a)
Assuming 0 to 100 inclusive:
num1 = rand() % 50 * 2 + 1 // 1, 3, 5, ..., 99
num2 = rand() % 51 * 2 // 0, 2, 4, ..., 100
num3 = rand() % 50 + 51 // 51, 52, ..., 100
For num1, the % gives a value 0..49 which, when doubled and incremented, gives you an odd number in the desired range. The second one is similar but with the range expanded slightly since there are even numbers at both ends. The third simply gives a number 0..49 which maps to 51..100 when 51 is added.
Similar results can be obtained if the range is only half-open (0..99 inclusive):
num1 = rand() % 50 * 2 + 1 // 1, 3, 5, ..., 99
num2 = rand() % 50 * 2 // 0, 2, 4, ..., 98
num3 = rand() % 49 + 51 // 51, 52, ..., 99
If, for some bizarre reason it has to use a loop (despite the inefficiencies), you have some problems with the conditions you use - they're basically all the wrong sense. In other words, you want (for example) the first loop to run while the number is even so that it will eventually produce an odd number.
You should be able to use something like the following. Each block consists of initialising the variable to a value that will force the loop to start then the loop that continues until a value with the desired properties is found:
int num1 = 0; // even forces loop entry
while ((num1 % 2) == 0) // wait for odd
num1 = rand() % 100;
int num2 = 1; // odd forces loop entry
while ((num2 % 2) == 1) // wait for even
num2 = rand() % 100;
int num3 = 1; // 50 or less forces loop entry
while (num3 <= 50) // wait for 51+
num3 = rand() % 100;
All of these limit the range of potential values to 0..99 inclusive, If you want to include 100, simply change the expressions to be rand() % 101.
(a) I'm actually not a fan of these sorts of limitations when set by educators. They're actually teaching inefficient ways to code. It would be far better if it was something that was a lot harder to do with a simple mathematical operation (like ensuring the number was neither 11, 17, 43 nor 97).
I suspect you could find a mathematical way to detect that but it would be far easier just to use a series of conditionals. Now I'm just waiting for someone to show me up by providing the mathematical formula for detecting those four :-)
There are some mistakes in the posted code:
a missing #include <stdlib.h>
the first test should be while (num1 % 2 == 0)
the second test should be while (num2 % 2 != 0)
the third test should be while (num3 <= 50)
Here is a modified version with loops but without looping :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
int num1, num2, num3;
srand(time(NULL)); /* or better randomness with srand(clock()); */
num1 = 1 + rand() % 50 * 2; /* 1, 3, ..., 99 */
while (num1 % 2 == 0) {
num1 = rand() % 100;
}
num2 = rand() % 50 * 2; /* 0, 2, ..., 98 */
while (num2 % 2 != 0) {
num2 = rand() % 100;
}
num3 = 51 + rand() % 49; /* 51, 52, ..., 99 */
while (num3 <= 50) {
num3 = rand() % 100;
}
printf("your numbers\n%d\n%d\n%d\n", num1, num2, num3);
return 0;
}
For those interested, both gcc and clang detect that the first 2 loops can be eliminated, but not the third as they do not make the assumption that rand() return a non negative number: https://godbolt.org/z/ucpV-y
You need to #include <stdlib.h> to get rid of this warning.
However, there's a bigger problem with your code: you have all the conditions inverted.
This will loop until the number is odd:
while (num1 % 2 != 0) {
This will loop until the number is even:
while (num2 % 2 == 0) {
And this will loop until the number is less than or equal to 50:
while (num3 > 50) {
To fix that, simply invert the conditions:
while (num1 % 2 == 0) { /* until we get an even number */
/* ... */
while (num2 % 2 != 0) { /* until we get an odd number */
/* ... */
while (num3 <= 50) { /* until num3 is greater than 50 */

Error code randomly appears when trying to run slot machine program

I am writing a program for a basic slot machine, randomly generating numbers and displaying the corresponding "symbols" for them from an array. The program executes most of the time but randomly I get an error code -1073741819 (0xC0000005). I'm extremely new to C so I'm unfamiliar with a lot of things, including what exactly can be causing this error in my code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(NULL));
char *symbols[] = {"Pineapple", "Kiwi", "Orange", "Lime", "Peach",
"Lemon", "Pear", "Banana", "Cherry", "Grape", "Blueberry",
"Blackberry", "Apricot"};
int num1, num2, num3;
int balance;
printf("Enter initial balance (in cents): ");
scanf("%d", &balance);
num1 = (rand() % (13 - 0 + 1)) + 0;
num2 = (rand() % (13 - 0 + 1)) + 0;
num3 = (rand() % (13 - 0 + 1)) + 0;
printf("%s ", symbols[num1]);
printf("%s ", symbols[num2]);
printf("%s ", symbols[num3]);
printf("\n");
if ((num1 == num2) && (num1 == num3))
{
printf("Congratulations! You have won $1");
balance += 100;
printf("\n");
}
balance -= 5;
printf("Remaining Balance: %d", balance);
return 0;
}
The error as I said happens randomly and I haven't been able to reliably reproduce it. Sometimes only 1/3 fruit names prints and I get the error code, sometimes it's 2 and sometimes none prints.
This:
num1 = (rand() % (13 - 0 + 1)) + 0;
Is the same as:
num1 = rand() % 14;
Which means you're generating a number from 0 to 13. Your symbols array has 13 elements with indexes from 0 to 12. So when you randomly generate the value 13, you're reading past the end of the array. Doing so invokes [undefined behavior]9https://en.wikipedia.org/wiki/Undefined_behavior), which in this case causes your program to crash.
Change that line and the two that follow to:
num1 = (rand() % 13;
num2 = (rand() % 13;
num3 = (rand() % 13;
That way you get a number from 0 to 12.
The statement (rand() % (13 - 0 + 1)) + 0; is equivalent to rand() % 14 which will generate random numbers from 0-13 INCLUSIVE. The problem is that you only have 13 strings, so when the rng spits out a 13, the fruit at index 13 doesn't exist.
This can be fixed by either adding another fruit or by changing your rng to rand() % 13
You are randomly accessing an invalid 14th element of symbols array (which has 13 elements).
When you write
num1 = (rand() % (13 - 0 + 1)) + 0;
you are trying to calculate symbols index. But this could lead to index 13... and symbols[13] does not exist, and it will translate in accessing a memory location you are not supposed to access.
Write simply
num1 = rand() % 13;
and everything will be fine.

Resources