how to use multiple input values to call same function? - c

First I have to say that i'm completely new to programming and this is my first program. I've watched a 5 hour tutorial before I started this and now I've run into my first problem I can't solve myself. So I hope someone here can help me!
I've written the following code
void printMainMenu();
void printTourMenu();
void assignment1();
void assignment2();
void assignment3();
void assignment4();
void assignment5();
void assignment6();
int main()
{
int userInput;
printMainMenu();
printf("\n\n");
scanf("%d", &userInput);
if(userInput == 4||6)
{
printTourMenu();
}
if (userInput == 1)
{
assignment1();
}
if(userInput == 2)
{
assignment2();
}
if(userInput ==3)
{
assignment3();
}
if(userInput ==5)
{
assignment5();
}
return 0;
all the functions are just pure printf so I just want the user to be able to print 6 different things depending on what they click on, but instead of making two if-statements to do the very same thing depending on the input, I just try and make an if-statement that works with multiple inputs.
the problem is in the if(userInput == 4||6) which i've tried with both
4, 6 and 4||6 where it keeps printing the printTourMenu no matter what I input and then the function i'm actually calling. With 4&&6 it prints printTourMenu only when I input 4 but not when I input 6
so what am I doing wrong? I hope someone will help this beginning programmer :D

Actually, the answer was simple and provided ASAP by Steve Summit:
if (userInput == 4||6)
doesn't do the expected. The correct would be:
if (userInput == 4 || userInput == 6)
IMHO, you should now ask:
So, if if (userInput == 4||6) is wrong – why didn't the compiler complain? (I assume it didn't although I didn't try.)
There are two reasons for this and IMHO you should know these reasons (as you did not yet learn them from your C book).
There are no special boolean types in C. Instead, every integer ≠ 0 is counted as TRUE but 0 is counted as FALSE. Hence, logic operators compute integers, comparison operators as well.
Thus, userInput == 4 || 6 is just a valid arithmetic expression and it has a precise result.
To understand how userInput == 4 || 6 is evaluated you need to know about C operator associativity and precedence also. Both terms can be found by google very easy (because they probably are searched quite often (at least periodically by me)).
I recommend the reference table of cppreference.com: C Operator Precedence.
Studying this table, we see:
operators == and || are both evaluated from left to right.
operator == has lower precedence as operator ||, i.e. == binds stronger, i.e. == is computed first.
Hence, it's starting with two cases:
userInput contains value 4: ⇒ userInput == 4: 1
userInput contains anything else: ⇒ userInput == 4: 0
These first results are applied to the second operator || 6:
1 || 6: 1 (Remember, logic-or operator just checks whether at least one argument is not 0.)
0 || 6: 1
It shows that anything || 6 results in 1.
That's why it was printing the tour menu regardless what you input.
Don't forget: as well as in school math, it is allowed to use parentheses () to override associativity and precedence. So, if you are in doubt just put parentheses around. Normally, they don't have any impact on run-time performance (at least, not as long as you don't change the order of operator evaluation due to this).

Related

C Integer range must meet 3 different conditions

If I wanted to limit the range of values to be assigned to an integer to three different conditions. eg; Must be between 9 and 95 and also be divisible by 5 would this be the correct way to accomplish this?
I've been told that i can have multiple conditions as long as they are separated by && but I am having little success with my code.
if (input >= 5 && input <= 95 && input %5)
Your code seems fine to me, except for this line.
if (input >= 5 && input <= 95 && input %5)
The expression input % 5 returns the remainder of input/5. You want input to be divisible by 5, which happens when input % 5 returns a remainder of 0. Since C interprets 0 as false, and pretty much all other integers as true, this expression will do exactly the opposite of what you want it to do. Try using
if (input >= 5 && input <= 95 && (input % 5 == 0))
That should do what you want it to do.
There are a number of issues with your code as it stands. First, the outright bugs:
The expression input % 5 will give you the remainder when divided by five. This means you will get zero if it is a multiple, non-zero otherwise. Unfortunately, zero is treated as false so this will only be true if input is not a multiple. The correct expression is (input % 5) == 0.
If you enter something that cannot be interpreted as an integer, the scanf will fail and input will be left at whatever value it was beforehand. This should be caught and acted upon, by checking the return value - this gives you the number of items successfully scanned so should be one.
Your code seems to return the value if okay but return nothing if it's invalid.
Next, while not bugs, these things are my personal preferences which can make code easier to read and maintain:
I prefer to explicitly separate sub-expressions so I never have to worry about precedence rules (provided it doesn't make the expression unreadable in the process). To that end, I would make the full if statement if ((input >= 5) && (input <= 95) && ((input % 5 == 0)).
I'm not a big fan of the if (condition) transferControl else ... construct since the else is totally superfluous.
I also prefer error catching to be done in a localised fashion at the start, catching problems early. Only after all checks are passed do you do the success portion.
A function (assuming it is a function, which seems likely) should generally do one thing, such as check if the value is valid. Writing issues to standard output is probably best left to the caller so that the function is truly re-usable. It would be better to have a function do the check and return some value to indicate whether or not there was a failure, along with the value if valid.
It's usually better to use puts("something") rather than printf("something\n"). The printf call is best left to where you actually need to do argument formatting.
Taking that all into account, the code that I would posit would be along the lines of:
#include <stdbool.h>
bool InputValidRangeAndMultiple(
unsigned *pValue,
unsigned minVal,
unsigned maxVal,
unsigned multVal
) {
unsigned input;
// If no unsigned int available, error.
if (scanf("%u", pValue) != 1) return false;
// If value invalid in any way (range or multiple), error.
if ((*pValue < minVal) || (*pValue > maxVal)) return false;
if ((*pValue % multVal) != 0) return false;
// Value is now deemed okay.
return true;
}
Calling that function can be done thus, with the prompts and errors handled outside the "input and check" function:
#include <stdio.h>
unsigned value;
puts("Enter Value.\nValue must be divisible by 5 and within 5 and 95...");
if (! InputValidRangeAndMultiple(&value, 5u, 95u, 5u)) {
puts("Invalid input...");
returnOrDoSomethingIntelligent();
}
// The 'value' variable is now valid.

Some confusion with regards to parenthesis in C

Please bear with me, I am trying to learn C as my first programming language and am only 15 minutes in.
Why must parenthesis be used here:
while ((number1 = number2))
...when they do not need to be used here?
while (number1 <= number2)
Thanks in advance.
In:
while (number1 = number2)
number2 is being assigned to number1.
This is optically very similar to comparing number1 and number2, i.e.:
while (number1 == number2)
So a warning is produced in the former case. In order to suppress that warning you need to place the parentheses around the assignment, i.e.:
while ((number1 = number2))
It is a very common mistake to write
if ( a = b ) // assign b to a, branch if result is non-zero
when you meant to write
if ( a == b ) // *compare* b to a, branch if equal
leading to all kinds of mayhem.
It's such a common mistake that most compilers will issue a warning if they see an assignment in a conditional like that. To tell the compiler, "no, I really know what I'm doing", you surround the assignment in an additional set of parentheses:
if ( ( a = b ) )
This basically means, "yes, I intend to assign b to a and branch on the result, shut up."
If I could time travel back to Bell Labs in 1970, this is one of several decisions I'd slap Ritchie over. An entire class of bugs would never have existed if the assignment operator had been := or something equally dissimilar to comparison.
Who said there is a must? You can omit it too.
while (number1 = number2)
yes this would generate compiler warning because you are assigning and checking the assigned value without parentheses. But this is legal and bad practice.
So the reason they did this is to avoid the warning about which the compiler complained. (You shouldn't skip warning to follow a bad practice - rather allow compiler warnings and try to solve them diligently).
Though as you are beginner - aware of the statement, here the while statement is basically
while(number2)
Point: The most common to use would be to while(number1 == number2).
Also does the same thing as the previous one. Who said in the second one you can't? You can.
while ((number1 <= number2))
This is a matter of opinion. Many programmers will still wrap a comparison in parentheses for clarity. That's to make them more legible. For instance:
while(i == 0) //comparison
while(i = 0) //assignment (and therefore, infinite loop)
but more commonly, because chains of conditions can become very hard to read, and getting into the habit of parenthesizing your comparisons makes complex comparisons easier to understand:
//whiskey tango foxtrot
while(i == 0 || j == i && k == 5 || f == "pancakes")
//oh, now it's clear that we're not checking "i && k". Easier to read!
while((i == 0) || (j == i) && (k == 5) || (f == "pancakes"))
//now I've guaranteed i and j both have the value "0" by using parentheses,
//or we get false; but everything is still clearly separated.
while(((i == 0) || (j == i)) && (k == 5) || (f == "pancakes"))
First off, the first example is extremely bad practice. It's not comparing number1 and number2, it's setting the value of number1 to the value of number2. See https://freedom-to-tinker.com/2013/10/09/the-linux-backdoor-attempt-of-2003/ for some more information.
That said, both forms are allowed; you can always add extra parenthesis. In the case you have above, there is no difference.
That said, odds are good that you're simplifying from an example where multiple conditions are chained together, like
while ((number1 == number2) || (number3 == number4))
As you can see, it makes it a bit easier to see what the code is doing. Technically it's not really necessary here, either (though it's generally considered to be good practice), but it can be necessary for more complicated expressions because different expectations about operator precedence can result in your code doing things you might not expect. To take an example from that page, for something like
e = a < d ? a++ : a = d;
It can take a few moments even for an expect to figure out what is going on, and someone less familiar with C will probably need much longer. On the other hand, if you add parenthesis:
e = ( ((a < d) ? (a++) : a) = d );
Things become much easier to read.

Do-while loop not observing truth assignment (C) [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
My C project is a Windows console app that takes the time signature and BPM from a user's musical project and returns the length of a bar in seconds.
I am trying to use a do-while loop to add a "continue/exit?" prompt at the end of each successful calculation
Here is the source code for that function. It performs one calculation based on user input, then terminates.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char timeSignature[6];
float BPM;
float beatsPerBar;
float barLength;
printf("Enter the working time signature of your project:");
scanf("%s",timeSignature);
beatsPerBar = timeSignature[0]-'0';
printf("Enter the beats per minute:");
scanf("%f", &BPM);
barLength = BPM / beatsPerBar;
printf("%f\n", barLength);
return 0;
}
After each successful calculation, I want to prompt the user to choose "y" to return to the initial input prompt or "n" to end the program and exit the command prompt.
This later update includes a do-while loop that is intended to add the feature.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <unistd.h>
int main()
{
do{
char timeSignature[6];
char anotherCalculation;
float BPM;
float beatsPerBar;
float barLength;
printf("Enter the working time signature of your project:");
scanf("%s",timeSignature);
beatsPerBar = timeSignature[0]-'0';
/*
* Subtracts the integer value of the '0' character (48) from the integer value
* of the character represented by the char variable timeSignature[0] to return
* an integer value equal to the number character itself.
*/
printf("Enter the beats per minute:");
scanf("%f", &BPM);
barLength = BPM / beatsPerBar;
printf("%f\n", barLength);
Sleep(3);
printf("Would you like to do another calculation? (Y/N)");
scanf(" %c", &anotherCalculation);
}while((anotherCalculation = 'Y'||'y'));
if((anotherCalculation != 'Y'||'y'))
{
printf("Goodbye!");
return 0;
}
return 0;
}
When I compile, there are no errors, but when I run it, the program loops after ANY input. Why is the code ignoring my truth assignment? What can I do to fix this?
Change this:
while (anotherCalculation = 'Y'||'y')
To this:
while(anotherCalculation == 'Y'|| anotherCalculation == 'y')
Otherwise you're doing:
while (anotherCalculation = ('Y'||'y'))
Note I also changed the assignment = to comparison ==.
Same goes for your if later:
if (anotherCalculation != 'Y'||'y')
Should be:
if (anotherCalculation != 'Y'|| anotherCalculation != 'y')
The if is redundant by the way, you've already left the while loop, so the user does not want any more calculations.
Convert your value to an upper-case letter before doing the comparison:
while(toupper(anotherCalculation) == 'Y');
That will accept either a lower-case or upper-case 'Y', and keep your code simple and straightforward.
Your problem is with the following line of code:
while((anotherCalculation = 'Y'||'y'));
Your first problem is that you are assigning to the variable anotherCalculation and then testing that value. This is because in C the = (assignment) operators can be used in test statements and the value that was set will be returned into the statement basically making your test statement the following:
while('Y'||'y');
Also there is a fault in the logic within your test statement even after substituting the = for ==,
What you are actually doing there is the same as:
TRUE if anotherCalculation == 'Y' or if 'y'.
Since 'y' actually has a value and FALSE is 0 in standard C, your loop will continuously run because it will always have a TRUE value.
To fix all errors, what that line actually needs to be is:
while(anotherCalculation == 'Y'|| anotherCalculation == 'y');
Finally, if you want to make this code more readable and avoid double testing, you can convert the input to uppercase and test that:
while(toupper(anotherCalculation) == 'Y');
First, you're using a mathematical notation for your logical checks that makes no sense in C, and you're using the assignment = operator instead of the "test for equivalence" == operator.
}while((anotherCalculation = 'Y'||'y'));
Should be:
}while((anotherCalculation == 'Y'|| anotherCalculation == 'y'));
Second, save yourself some hassle down the road, and use fgets() to get a line of a text, and parse it.
Finally, read into things like "trailing newlines" with scanf() and fgets(). The scanf() function, for example, won't "eat up" the newline at the end of your input, and you'll get unexpected behavior. This very question appears on SO once per month at least.
Logical operators don't work like that. x == a || b doesn't evaluate as "x is equal to one of a or b"; instead, it evalutes as "x is equal to the result of the Boolean expression (a OR b)". If you want to compare x against different values, you must write it as
x == a || x == b
But you have another problem, you've used the assignment operator = where you meant to use the comparison operator ==1:
while((anotherCalculation = 'Y'||'y'))
^
|
ooops
You're performing a logical-OR of two non-zero values, which evaluates to 1 (true), and assigning the result to anotherCalculation. The result of the expression is the value of anotherCalculation after the assignment (1), so you've effectively written
while( true )
You need to use the == operator for equality comparison, and you must do an explicit comparison on each side of the || operator:
while ( anotherCalculation == 'Y' || anotherCalculation == 'y' )
You can clean this up a bit by converting your input to a specific case before doing a comparison, getting rid of the need for the || operator altogether:
while ( tolower( anotherCalculation ) == 'y' )
or
while ( toupper( anotherCalculation) == 'Y' )
1. A bright young coder named Lee
wished to loop while i was 3
When writing the =
He forgot its sequel
And thus looped infinitely
This is not doing what you expect:
}while((anotherCalculation = 'Y'||'y'));
Nor is this:
if((anotherCalculation != 'Y'||'y'))
You should be doing this:
}while((anotherCalculation == 'Y') || (anotherCalculation =='y'));
And this:
if((anotherCalculation != 'Y') && (anotherCalculation !='y'))
TLDR; Change your condition to
while( anotherCalculation == 'Y' || anotherCalculation == 'y' );

scanf(parameter) == 1 vs 1 == scanf(parameter) makes no difference?

I am really confused that when this like 1 == scanf("%lg", &entry) is swapped to scanf("%lg", &entry) == 1 makes no difference. My lab book says the former, while I feel latter is comprehensible.
1 == scanf("%lg", &entry) means 1 MUST be equal to scanf("%lg", &entry)Can anyone explain this? I understand the latter, that the evaluation of scanf("%lg", &entry) must equal 1
I tried passing lots of different values and it makes no difference.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
double entry = 0.0;
double total = 0.0;
int number_of_entries = 0;
while (scanf("%lg", &entry) == 1 ) {
total += entry;
number_of_entries++;
}
/* print the average of all the entries */
printf("%f\n", total / number_of_entries);
return EXIT_SUCCESS;
}
Generally speaking, you should not be surprised by (1 == scanf(...)) behaving the same as (scanf(...) == 1), since equality is symmetric. However, this is so because one of the operands is idempotent (in particular, the literal constant 1). scanf() is the only expression with a side effect, so there is no possibility of a different interpretation of the code when the arguments of == are reversed.
However, the evaluation order of the arguments to == is unspecified. So, if on side of == has a side effect that can affect the other side, then the evaluation order will impact the result of the == operation, and reversing the arguments could cause a different behavior. Such a program will thus have undefined behavior.
As a silly example, consider:
a = 0;
if (scanf("%d", &a) == a) {
...
}
The snippet has undefined behavior, because it is unspecified whether the a on the right hand side of == will be the old value it was initialized to in the statement above, or the new value that the scanf() call may have supplied. Changing the order of the arguments may cause the program to behave differently, but the behavior is still undefined.
scanf("%lg", &entry) == 1
is the same as
1 == scanf("%lg", &entry)
However, I once had a friend who preferred the
1 == scanf("%lg", &entry)
because it caught the potential typo
1 = scanf("%lg", &entry)
whereas
scanf("%lg", &entry) = 1
would go through the compiler ok.
They are the same. And it's not limited to scanf. Usage like
if (5 == x)
is called Yoda Conditions. It's a method to prevent forgetting to use double = to compare equality. If one mistakenly write:
if (5 = x)
Then the compiler will report the error. On the other hand
if (x = 5)
is valid C (it will assign x with the value of 1, and return the value 5, i.e, true) so the compiler may not warn your about it.
It's just a coding-style, many modern compilers will warn you if you write if (x = 5). If that is true in your case, I suggest not using Yoda Conditions since it's bad for readability.

What is the meaning of '==' in C?

What is the meaning of == and how does it differ from =?
How do I know which one to use?
== is a test for equality. = is an assignment.
Any good C book should cover this (fairly early on in the book I would imagine).
For example:
int i = 3; // sets i to 3.
if (i == 3) printf("i is 3\n"); // prints it.
Just watch out for the heinous:
if (i = 4) { }
which is valid C and frequently catches people out. This actually assigns 4 to the variable i and uses that as the truth value in the if statement. This leads a lot of people to use the uglier but safer:
if (4 == i) {}
which, if you accidentally use = instead of ==, is a compile-time error rather than something that will bite you on the backside while your program is running :-)
The logical-or operator is two vertical bar characters, one after the other, not a single character. Here it is lined up with a logical-and, and a variable called b4:
||
&&
b4
No magic there.
a == b is a test if a and b are equal.
a = b is called an assignment, which means to set the variable a to having the same value as b.
(You type | with Shift-\ in the US keyboard layout.)
== tests equality
= assigns a value
neither are related to ||
I might add that in Finnish and Swedish keyboards. Pipe symbol; |; of OR is AltGr (the right alt) and < key. IF you are using Mac on the other hand it is Alt-7 key.
Gave me a lot of sweat when I first started typing on these keyboards.
Now that you know the difference between '==' and '=", let me put you some words of caution. Although '==' is used as a standard test of equality between comparable variables and '=' used as an internally type-casted assignment, the following programming error is quiet common.
In the below example and similar codes, '=' is know as "Always true" conditional operator.
#include<stdio.h>
int main()
{
int i = 10, j = 20;
if ( i = j )
printf("Equal\n");
else
printf("NOT Equal\n");
return 0;
}
So, the word of caution is "Never use '=' in if statements, unless you have something evil in your mind."

Resources