If else statement troubles in C - c

I am trying to input a seat number of "15" into this function and get the char value of 'A'. However, for some reason every time I input a number that should be a type 'A'(because its remainder doesn't equal any of the aforementioned values) it gets stuck in the 'M' else if statement. I really do not understand why and would like some help if you have time :)
char whatTypeOfSeat(int seatNumber){
if((seatNumber % 6) == 0 || seatNumber % 6 == 1 || seatNumber == 1) {
typeOfSeat = 'W';
}
else if((seatNumber % 6) == 2 || (seatNumber % 6) == 5|| seatNumber == 5,2 ) {
typeOfSeat = 'M';
}
else {
typeOfSeat = 'A';
}
return typeOfSeat;
}

This does not do what you think it does:
seatNumber == 5,2
If you want to check against both values, you need separate conditionals
else if((seatNumber % 6) == 2 || (seatNumber % 6) == 5|| seatNumber == 5 || seatNumber == 2 ) {

Related

`else if` condition not properly working in my program in c

I am new and I don't know to to resolve this error.
When I give inputs for the third else if statement condition it gives the output as salary =0.
Can anyone explain why this happening?
I want to get the answer as :the salary of the candidate = 7000
but the output shows as : the salary of the candidate = 0
/******************* calculating the salary *********************/
/***** bitwise operator ***********/
#include <stdio.h>
int main()
{
char gen;
int qual, y_o_s, sal = 0 ;
printf ( "Enter Gender, Years of Service and Qualifications ( 0 = G, 1 = PG ):\n" );
printf("enter the gen, y_o_s, qual, \n");
scanf("%c\n%d\n%d", &gen, &y_o_s, &qual);
if (gen == 'M' && y_o_s >= 10 && qual == 1)
sal = 15000;
else if ((gen == 'M' && y_o_s >= 10 && qual == 0) ||
(gen = 'M' && y_o_s < 10 && qual == 1))
sal = 10000;
else if (gen == 'M' && y_o_s < 10 && qual == 0)
sal = 7000;
else if (gen == 'F' && y_o_s >= 10 && qual == 1)
sal= 12000;
else if (gen == 'F' && y_o_s >= 10 && qual == 0)
sal = 9000;
else if (gen == 'F' && y_o_s < 10 && qual == 1)
sal = 10000;
else if (gen == 'F' && y_o_s >= 10 && qual == 0)
sal = 6000;
printf("the salary of the candidat = %d\n", sal);
return 0;
}
I want to get the answer as :the salary of the candidate = 7000
but the output shows as : the salary of the candidate = 0.
Alter your if-else-if ladder like :
#define POST_GRAD 1
#define SEX_MALE 'M'
if (SEX_MALE == gen) {
if (POST_GRAD == qual) {
sal = (y_o_s >= 10) ? 15000 : 10000;
} else { // undergrad
sal = (y_o_s >= 10) ? 10000 : 7000;
}
} else { // not Male
if (POST_GRAD == qual) {
sal = (y_o_s >= 10) ? 12000 : 10000;
} else { // undergrad
sal = (y_o_s >= 10) ? 9000 : 6000;
}
}
It's easier to follow. Notice, that constants like POST_GRAD are on the left side comparator ==, it helps compiler catch unintended typos like = for comparisons.
Also, you may want those salaries at one place like :
#define MALE_PG_EXP_SAL 15000
#define MALE_UG_EXP_SAL 10000
// and so on
#define FEMALE_UG_EXP_SAL 9000
#define FEMALE_UG_INEXP_SAL 6000
When they change, you can find them at one place to modify.
PS: I wouldn't want to work at this place.
You are assigning a value to gen
else if ((gen == 'M' && y_o_s >= 10 && qual == 0) ||
(gen = 'M' && y_o_s < 10 && qual == 1))
^
So when you get to your next line gen is no longer what you expect.
else if (gen == 'M' && y_o_s < 10 && qual == 0)
^^
And then improve the code with SparKots suggestions.

How to make conditional statements more compact in C?

I have a code snippet that uses if-else if-else block. I am wondering any potential ways to shorten the lengthy conditional statement else if (cardLength == 16) && (numberArray[0] == 5 && (numberArray[1] == 1 || numberArray[1] == 2 || numberArray[1] == 3 || numberArray[1] == 4 || numberArray[1] == 5)), for instance, without changing the logic. In python, I can do in this way: if (cardLength == 16) and (numberArray[0:2] in range(51,56)). Are there any specific syntax sugar that I can use fo this purpose in C?
if (cardLength == 15) &&
(numberArray[0] == 3 && (numberArray[1] == 4 || numberArray[1] == 7))
{
printf("AMEX\n");
}
else if (cardLength == 16) &&
(numberArray[0] == 5 && (numberArray[1] == 1 || numberArray[1] == 2 || numberArray[1] == 3 || numberArray[1] == 4 || numberArray[1] == 5))
{
printf("MASTERCARD\n");
}
else if (cardLength == 13) && (numberArray[0] == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
Put it into a (static) function. Dont think about performance/optimisation yet.
static char *card_leng_type2string( unsigned len, int *arr)
{
if (len == 15 && arr[0] == 3 && arr[1] == 4 ) return "AMEX";
if (len == 15 && arr[0] == 3 && arr[1] == 7 ) return "AMEX";
if (len == 16 && arr[0] == 5 && arr[1] == 1 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 2 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 3 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 4 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 5 ) return "MASTERCARD";
if (len == 13 && arr[0] == 4) return "VISA";
return "INVALID";
}
Now your calling code could just do:
printf("%s\n", card_leng_type2string(cardLength, numberArray) );
You could convert the first two digits of the numberArray into a new number like this
num = numberArray[0]*10 + numberArray[1]
and then use that into the conditional statements to make them more readable
int num = numberArray[0]*10 + numberArray[1]
if ((cardLength == 15) && ((num == 37) || (num == 34)))
{
printf("AMEX\n");
}
else if ((cardLength == 16) && ((num >= 51) && (num <= 55)))
{
printf("MASTERCARD\n");
}
else if ((cardLength == 13) && ((num >= 40) && (num <= 49)))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
return 0;
}
Assuming that entries in numberArray are in range 0-9, you could use strchr function. This returns non-NULL if a given string contains a specific character.
Replace:
numberArray[1] == 4 || numberArray[1] == 7 || numberArray[1] == 9
with
strchr("479", '0' + numberArray[1])
If numberArray was an array of character then the check could be simplified to strchr("479", numberArray[1])
If you want the logic intact and only want modification for readbility, you could try adding a preprocessor directive gloabally.
This would replace the text or inline function anywhere you use it in the program.
Example
#define AMEX_CONDITION (cardLength == 15) && (numberArray[0] == 3 && (numberArray[1] == 4 || numberArray[1] == 7))
and use it in your if as
if(AMEX_CONDITION){
printf("AMEX");
}

How can I fix the If and structure problem in C?

My program should ask user for last full moon date, check if data is correct and then ask user does he want to see dates of next or previouse full moons and how many. I have some problems with "if"and "else if". I don't know why but program basiclly acts like it doesn't see that user gave anything in this line scanf_s("%s", &czy_kolejne); and goes straight to else{printf("\nBłędny znak."); }. I'm also not sure if structure for date is the best way to do it, becasue it have some problem with previouse dates. Could someone give me any advice ?
#include<time.h>
#include<stdlib.h>
int main()
{
int rok, miesiac, dzien;
char czy_kolejne;
int kolejne_pelnie;
int poprzednie_pelnie;
printf_s("Kiedy byla ostatnia pelnia ? (DD.MM.YYYY): ");
scanf_s("%d.%d.%d", &dzien, &miesiac, &rok);
if (rok >= 0)
{
if (miesiac >= 1 && miesiac <= 12)
{
if ((dzien >= 1 && dzien <= 31) && (miesiac == 1 || miesiac == 3 || miesiac == 5 || miesiac == 7 || miesiac == 8))
{
printf_s("Poprawna data. %d.%02d.%d", dzien, miesiac, rok);
}
else if ((dzien >= 1 && dzien <= 31) && (miesiac == 10 || miesiac == 12))
{
printf_s("Poprawna data. %d.%d.%d", dzien, miesiac, rok);
}
else if ((dzien >= 1 && dzien <= 30) && (miesiac == 4 || miesiac == 6 || miesiac == 9))
{
printf_s("Poprawna data. %d.%02d.%d", dzien, miesiac, rok);
}
else if ((dzien >= 1 && dzien <= 30) && miesiac == 11)
{
printf_s("Poprawna data. %d.%d.%d", dzien, miesiac, rok);
}
else if ((dzien >= 1 && dzien <= 28) && miesiac == 2)
{
printf_s("Poprawna data. %d.%02d.%d", dzien, miesiac, rok);
}
else if (dzien == 29 && miesiac == 2 && (rok % 400 == 0 || (rok % 4 == 0 && rok % 100 != 0)))
{
printf_s("Poprawna data. %d.%02d.%d", dzien, miesiac, rok);
}
else
{
printf_s("Liczba dni w miesiacu jest bledna.");
}
}
else
{
printf_s("Nie ma tylu miesiecy.");
}
}
struct tm t = { 0 };
t.tm_mday = dzien;
t.tm_mon = miesiac - 1;
t.tm_year = rok - 1900;
int skip = 29;
t.tm_mday += skip;
mktime(&t);
char buffer[30];
printf("\nCzy wyliczyc daty kolejnych pelni ? (T/N)");
scanf_s("%s", &czy_kolejne); //The problem starts right here.//
if ((czy_kolejne=='t') || (czy_kolejne=='T'))
{
printf_s("\nIle dat w przod?");
scanf_s("%d", &kolejne_pelnie);
for (int i = 1; i <= kolejne_pelnie; i++)
{
int skip = 29 * i;
t.tm_mday += skip;
strftime(buffer, 30, "\n%d-%m-%Y", &t);
puts(buffer);
}
}
else if ((czy_kolejne=='n') || (czy_kolejne=='N'))
{
printf_s("\nIle dat w tył wyliczyc?");
scanf_s("%d", &poprzednie_pelnie);
for (int i= 1; i <= poprzednie_pelnie; i++)
{
int skip = 29 * i;
t.tm_mday -= skip;
strftime(buffer, 30, "\n%d.%m.%Y", &t);
puts(buffer);
}
}
else
{
printf("\nBłędny znak.");
}
return 0;
}
At least two things are wrong with scanf_s("%s", &czy_kolejne), when czy_kolejne is of datatype char:
First, %s will read in a 0-terminated string, but you provide a buffer of type char; this is undefined behaviour, very likely just corrupting memory and leading to weird results. For reading in exactly one character use format "%c".
Second, if you make czy_kolejne to a char array, e.g. char czy_kolejne[10], then scanf_s with a format %sis OK, but it requires an additional argument indicating the buffer size. I.e. you'd have to write scanf_s("%s", &czy_kolejne, sizeof(czy_kolejne)).

Testing if a number goes evenly into 6? [duplicate]

This question already has answers here:
modulo operation on negative numbers [duplicate]
(2 answers)
Closed 5 years ago.
I am trying to see if two input numbers (integers) including negative numbers go into 6 evenly (remainder is 0). This is the code I was trying.
if((in1)%6 == 0 && (in2)%6 == 0){
printf("Divisible: both\n");
}
else if((in1)%6 == 0 && (in2)%6 > 0){
printf("Divisible: only %i\n",in1);
}
else if((in1)%6 > 0 && (in2)%6 == 0){
printf("Divisible: only %i\n",in2);
}
else{
printf("Divisible: neither\n");}
This works for all positive integer but for any negatives the printed code is always "Divisible: neither" any help as to how I can show both positive and negative numbers divisible by six with a remainder of 0 would be really helpful
You could use != 0 instead of > 0. In C, % of negative number will give a negative result (or zero).
This is because a / b is defined as truncation-towards-zero since C99 (in C90 it was implementation-defined). And a % b is defined as a - (a / b) * b.
Note that you actually do not need this test at all; you can rely on the behaviour of if...else not entering the else case if the if case was satisfied, e.g.:
if ( in1 % 6 == 0 && in2 % 6 == 0 )
{
// ...
}
else if ( in1 % 6 == 0 )
{
// would not reach here if in2 % 6 == 0
}
else if ( in2 % 6 == 0 )
{
// would not reach here if in1 % 6 == 0
}
else
Another consideration, rather than oblige code to test numbers 3 times, re-write to perform only 2 test on the numnbers.
if (in1 % 6) {
if (in2 % 6) {
printf("Divisible: both\n");
} else {
printf("Divisible: only %i\n",in1);
}
} else {
if (in2 % 6) {
printf("Divisible: only %i\n",in2);
} else {
printf("Divisible: neither\n");}
}
}

'if' statement in C not executing even though conditions are met

I'm a first time programmer trying to complete a simple command line program as part of the first assignment for an online course I am taking, but I seem to have hit a roadblock that I can't figure out with GDB or my own research.
After hours of rewrites, and hours of debugging, I finally got the code below to compile. The program is supposed to take a credit card number as an input, and then check whether it's valid per the specifications of the assignment. I used a test number from here: PayPal Test Credit Cards
The odd thing is, when I enter an AMEX card number, it correctly produces the text "AMEX", but when I try a Visa or a Master Card, it prints "INVALID".
In GDB I broke at the Verify function and it seems to incorrectly skip these two if/else if statements without proceeding to the Checksum function even though conditions appear to be met.
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
...
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
...
The AMEX line of code that correctly executes is:
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
The arguments for all three lines seem to be formatted exactly the same. That is far as I could get in GDB though. I would print totalDigits, firstDigit, and secondDigit in GDB right before stepping through the above two non-executing lines and everything looked correct. So I'm stumped, why is the AMEX line executing, but not the others?
Thanks in advance everyone. This is the first program after hello.c that I've tried to write, so I am open to absolutely any criticism or suggestions if it looks like I'm doing something weird/wrong.
Full code:
checker.c
#include <stdio.h>
#include <stdlib.h>
int MAX = 16;
int* DigitSort(unsigned long long x, int* array);
int Verify(int* array);
int main (void)
{
int* output = malloc (sizeof(int) * (MAX + 2)); // creates a blank array for the individual digits of the card number.
unsigned long long userInput = 0;
do
{
printf("Please enter a credit card number:\n");
scanf("%lld", &userInput);
}
while (userInput <= 0); // checks to make sure the user entered a number.
switch(Verify(DigitSort(userInput, output))) // sorts the user's input into individual digits and verifies the card type and validity.
{
case 1 :
printf("VISA\n");
break;
case 2 :
printf("MASTERCARD\n");
break;
case 3 :
printf("AMEX\n");
break;
case 0 :
printf("INVALID\n");
break;
default :
printf("INVALID\n");
}
free(output);
return 0;
}
int Verify(int* array) // verifies whether or not a card number is valid. Must pass the function a sorted array of individual digits.
{
int* cardNumber = array;
int firstDigit = cardNumber[0];
int secondDigit = cardNumber[1];
int totalDigits = 0;
int Checksum(int* cardNumber, int totalDigits);
int i = 0;
while (firstDigit >= 1 && cardNumber[i] >= 0) // this step counts the number of digits in the array.
{
totalDigits = totalDigits + 1;
i++;
}
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
{
return 1;
}
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
{
return 2;
}
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
{
return 3;
}
else // if the card number doesn't match any of the above conditions or fails the checksum, an 'I' for Invalid is returned.
{
return 0;
}
}
int* DigitSort(unsigned long long x, int* array) // takes a long long as input and sorts it into individual digits
{
int* arrayReversed = malloc (sizeof(int) * (MAX + 2)); // creates a new array to hold the reversed order of digits.
int i = 0;
arrayReversed[0] = 0;
if (i < (MAX - 1) && x >= 10)
{
do
{
arrayReversed[i] = x % 10;
x = x / 10;
i++;
}
while (i < (MAX -1) && x >= 10);
}
if (i < MAX && x >= 1 && x <= 9)
{
arrayReversed[i] = (int) x;
x = (x - x);
}
if (x == 0)
{
int j = 0;
do
{
array[j] = arrayReversed[i]; // sorts the digits from the reversed array and places them into the sorted array.
j++;
i--;
}
while (j < MAX && i >= 0);
array[j] = -1;
}
free(arrayReversed);
return array;
}
int Checksum(int* cardNumber, int totalDigits)
{
int sum1 = 0;
int sum2 = 0;
int i = (totalDigits - 2);
int j = (totalDigits - 1);
while (i >= 0)
{
sum1 = ((cardNumber[i] * 2)%10) + ((cardNumber[i] * 2)/10) + sum1;
i -= 2;
}
while (j >= 0)
{
sum2 = (cardNumber[j] + sum2);
j -= 2;
}
if (((sum1 + sum2) % 10) == 0)
{
return 0;
}
else
{
return 1;
}
}
Your first problem is here:
if (firstDigit == 4 && totalDigits == (13 | 16) && ...
You need to write:
if (firstDigit == 4 && (totalDigits == 13 || totalDigits == 16) && ...
Your first check is looking for 0x1D == 29 as the number of digits (because, as paisanco points out in a comment, the | operator is the bitwise OR operator), and no credit card needs 29 digits (yet, and not for a long time to come). Note the extra parentheses for clarity and accuracy. Don't mess around risking removing them — the code won't work properly again. And in general, be explicit if your condition has both && and || operators and use parentheses to group terms explicitly.
You have similar problems elsewhere. As it happens, (4 | 7) is the same value as 7, so the condition works when the second digit is 7 (but not when it is 4). But it doesn't mean what you intended it to mean.
Computer languages don't work the same as human languages. Get used to writing out the condition somewhat more verbosely. Some other languages provide shorthands for these conditions; C is not such a language.

Resources