I have a homework assignment in which I believe the professor has made a typo, typing if(!(a=10)) instead of if(!(a==10)). However, when asked if this was typo, she told me to "assume that the equations are correct and give your answer." Specifically, the assignment is to describe the behavior of the program:
#include <stdio.h>
int main() {
int a = 100;
while (1) {
if (!(a=10)) {
break;
}
}
return 0;
}
If the offensive code read (!(a==10)) then the program would enter the if loop, reach the break and exit both loops, which makes sense for a beginner-level course in C programming.
However, if, truly, the code is meant to read (!(a=10)) then I don't know what the compiler will interpret that to mean. I do know that the code compiles, and when you run it in UNIX, it just allows you to input whatever you want using the keyboard, like say the number "7", and then you press enter and it moves to a new line, and you can enter "dog", and move to a new line, and on and on and it never exits back to the command line. So (1) how would the compiler interpret (!(a=10))? And (2) why does the program allow you to just continue to input entries forever?
Thanks!
For the first question,
What's the meaning of if( !(a=10) ){break;},
It's equivalent to
a = 10; if(!a) {break;}
For a value of 10 !a will be 0 and it never breaks the while loop.
In this particular example, if you assign if(!(a=0)), then it will exit the loop;
For the second question, there is no code present in your example.
But first question's answer can be extended here as the loop never breaks it keeps on asking the input values.
From the C Standard (6.5.3.3 Unary arithmetic operators ¶5)
5 The result of the logical negation operator ! is 0 if the value of
its operand compares unequal to 0, 1 if the value of its operand
compares equal to 0. The result has type int. The expression !E is
equivalent to (0==E).
So according to the quote the if statement
if (!(a=10)) {
is equivalent to
if ( ( a = 10 ) == 0 ) {
As the value of the assignment sub-expression, a = 10 is equal to 10 that is it is not equal to 0 then the condition of the if statement evaluates to logical false and the sub-statement of the if statement will not get the control and you will have an infinite while loop.
In fact, you can rewrite this while loop
while (1) {
if (!(a=10)) {
break;
}
}
the following way with the same effect
while ( ( a = 10 ) ) {}
or just
while ( ( a = 10 ) );
or more simply:
while ( a != 0 );
because what is important is that within the while loop the variable a does become equal to 0.
while (1) {
if (!(a=10)) {
break;
}
}
as !(a = 10) is always zero (false) it is equivalent of:
while (1) {
}
Related
So I've seen this used before some of my profs code aswel as in some of my friends who have more experience with programming.
int number = 0;
while(number) {
a bunch of code
}
My understanding is that this while loop is essentially running with no condition, i feel like it should be
while(number = 0) {
Isnt this essentially creating an infinite loop? but in the cases I've seen it used it can break out of the loop somehow.
edit:
do while that uses the argument in question. Note that the 2 functions being called in the switch case will call searchpatientdata again once they have completed.
This code is not currently wokring, but was working in a previous build and this function was the same. They also do not change the selection variable either.
The condition in a while loop can be any expression of scalar (numeric or pointer) type. The condition is treated as false if the result of evaluating the expression is equal to zero, true if it's non-zero. (For a pointer expression, a null pointer is equal to zero).
So while (number) means while (number != 0).
As a matter of style, I prefer to use an explicit comparison unless the variable is logically a Boolean condition (either something of type bool or _Bool, or something of some integer type whose only meaning values are true and false) -- but not everyone shares my opinion, and while (foo) is a very common way to write while (foo != 0).
The same applies to the condition in an if, a do-while, or a for statement.
Note that in your example:
int number = 0;
while(number) {
// a bunch of code
}
the body of the loop will never execute, because number is equal to zero when the loop is entered. More realistically, you might have:
int number = some_value;
while (number) {
// a bunch of code *that can change the value of number*
}
Any place in C where a Boolean value is required, any number will be evaluated like this:
zero → false
not zero → true
From C reference
Executes a statement repeatedly, until the value of expression becomes equal to zero. The test takes place before each iteration.
How it works?
entry control loop
condition is checked before loop execution
never execute loop
if condition is false there is no semicolon at the end of while
statement
Come to point as per OP's question yes
While (Variable_name) evaluated as True
In below Example While loop executes until condition is true
Example:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num=1;
while(true)
{
if(num==5)
{
break;
}
printf("%d\n",num);
num++;
}
return 0;
}
int a = 0;
a = 7 > 2 ? printf("6") : printf("4");
printf ("%d",a);
The ouput of this block is :
61
I tried the code in its expanded form
int a = 0 ;
if(7>2)
{
printf("6");
}
else
{
printf("4");
}
printf("%d",a);
Here I the output was:
60
I would like to get an explanation on why the output differs.
The first statement assigns the return value of printf to a. printf returns the number of bytes that were written. In this case that is 1. In the second expanded version, a is not assigned. Here is an actually equivalent version to the original:
int a = 0;
if(7>2)
{
a = printf("6");
}
else
{
a = printf("4");
}
printf("%d",a);
They are completely different.
To make them identical:
int a = 0 ;
if(7>2)
{
a = printf("6");
}
else
{
a = printf("4");
}
printf("%d",a);
cond?val1:val2 is the ternary operator. It is not supposed to be a control structure (like if, for or while). It is an operator. To build expression (things that have a value) rather than instruction (things that does things).
Frontier is fuzzier in C than in other languages, because instructions have a value (including void) and expression have potential side-effects.
But, well, you use cond?val1:val2 when you want to get the result. As you did, since you assigned the result to a.
And the result here is the result of printf("6"), that is 1, since printf returns the number of printed characters. Note that there is no real doubt, since even if 7 were smaller than 2, result would still have been 1. Since you print that result, it is normal to have a 1 printed after the 6.
(Just to be clear, even if I assume you know that already, what you did is print string "6" and then number 1, which is the result of 1st printf. Exactly as if you did
printf("%d",printf("6"));
which 1st prints "6", then pass the result to the outer printf to print what the inner printf returned, that is 1)
In your second code, you do nothing to change a's value, and you ignore the result of printf.
Your examples aren't equivalent. To be equivalent, the second one should say a=printf(... everywhere. After which a will get assigned the number of characters printed, 1.
The conditional operator (e1 ? e2 : e3) is not a "short version of if condition", although it has some similarities with an if ... else construct. The conditional operator yields a value (which you assign to a in your first example); an if ... else construct does not have a value.
So, your first example assigns a value to a, because it is written in the form of an assignment statement; that value is the 1 returned by the call to the printf function. To get similar behaviour in your second example, as others have said, you need to also assign the value returned by printf inside the if ... else blocks.
Alternatively, to make the first case work like the second, you can skip the assignment and use the conditional operation to determine the argument that is passed to the printf call:
int main(void)
{
int a = 0;
printf(7 > 2 ? "6" : "4");
printf("%d", a);
return 0;
}
I was confused about my assumption as to how the while loop might work ..
I've tried it on my computer, and seen that all cases have been as expected,
am i right, or am i missing out on something ?
while(scanf("%d%d%d",&a,&b,&c) ,a||b||c ) { /* some code */ }
This means that even if one value (either a,b or c ) is non zero , it will loop on
while(scanf("%d%d%d",&a,&b,&c) ,a&&b&&c ) { /* some code */ }
This means whenever any of a, b or c becomes zero, the loop terminates
This is correct, the first loop will go on until all three values turn zero, while the second loop will stop as soon as one of three items becomes zero.
This is because comma operator discards the result of the first expression - essentially, the expression a || b || c or a && b && c become your loop condition.
Note that your loops may not terminated when the input ends prior to reading a stopping combination (all zeros / one zero). When this happens, your loop becomes infinite. To prevent this from happening, change your loops to
while(scanf("%d%d%d",&a,&b,&c) == 3 && (a||b||c) ) { //some code }
or
while(scanf("%d%d%d",&a,&b,&c) == 3 && a && b && c) ) { //some code }
while(true) {//some code} // loop will run
while(false) {//some code} // loop will not run
since any value other than 0 is considered as true so your first while loop will execute until all of them become 0.
and in second while loop if any of them become 0 the loop will not execute.
just basic operators.
How this for loop is working
int main(){
char i=0;
for(i<=5 && i>=-1; ++i ;i>0)
printf("%d \n",i);
printf("\n");
return 0;
}
Ahh thanks for the clarification.
Your asking why the for loop in your example is executing, even though the increment operand and loop condition have been swapped, and the fact that the variable is a char. Lets consider the proper structure of a for loop:
for (initialise variable; for condition; increment variable)
{
//Do stuff
}
The answer to your question is simple:
Your condition increases i by 1, but as you have pointed out, i is a char. Using operands on a char can convert it to another type, including int (refer C comparison char and int)
A loop will continue until its condition == false.
Your loop will continue running until i=0, which means it will continue to increase by 1 until it reaches 128, at which point it will overflow to -128 and continue to increase until it reaches 0 again.
Lets name parts of the for loop:
for( Expr1; Expr2; Expr3 )
DoStuff;
This is how a for loop works:
1. It executes Expr1 first. in your loop does nothing in fact, since it doesn't check the result of this execution.
Then it executes Expr2 and treat it's result as a condition if it's 0 terminates the loop, if it's "not 0" go to step 3. In your loop this means that i will be incremented, thus it's now 1, so result is true.
Then it runs the DoStuff part, in your case print out i value
Next it executes Expr3, no check, just run it, in your case does nothing again, since it's a condition and its result isn't used.
Next it goes back to Expr2 executes it and check it's result. now i is 2, still a true condition.
Again execute the DoStuff part and go to step 4
The loop will stop once i value changes back to 0.
When? since it's type is char, after reaching 127 it will overflow to -128 and then increment back to -1 and then 0. and stop.
Whenever you want to understand for loop in this kind of situation you can convert for loop into while to understand it.
The for syntax is:
for (initialization; condition; operation)
...
It can be converted into while as:
initialization;
while (condition) {
...
operation;
}
So in your case
i <= 5 && i >= -1; // Initialization
while(++i) { //condition
printf("%d \n", i);
i > 0; // operation
}
Initialization part will be execute once it will check for condition.Here in your case it is ++i so increment every time.Here i>0 means if i==0 then loop will stop it does not matter i is positive or negative Thumb rule to remember in this kind of situation is if (i == 0 ) then true else false. i>0 remains true)in every case after that so loop is infinite.
To understand for loop best answer I have seen in SO is this
There's not rule about the order of for loop condition and increment operation, the latter even don't need to be an increment operation. What it's expected to do is determined by you. The code is just same as the following semantically.
char i = 0;
i <= 5 && i >= -1; // Run before the loop and only once. No real effect here.
while (++i) { // Condition used to determine the loop should continue or break
printf("%d \n", i);
i > 0; // Run every time inside the loop. No real effect here.
}
BTW: It'll be an infinite loop (because ++i is a nonzero value until overflow).
I found this piece of code on Wikipedia.
#include <stdio.h>
int main(void)
{
int c;
while (c = getchar(), c != EOF && c != 'x')
{
switch (c)
{
case '\n':
case '\r':
printf ("Newline\n");
break;
default:
printf ("%c",c);
}
}
return 0;
}
I'm curious about expression used as condition for while loop:
while (c = getchar(), c != EOF && c != 'x')
It's quite obvious what it does, but I've never seen this construction before. Is this specific to while loop? If not, how does parser/compiler determine which side of comma-separated expression returns boolean value for while loop?
The comma operator is a binary operator that evaluates its first operand and discards the result, it then evaluates the second operand and returns this value.
It is also a "sequence point", which means that all side effects will be calculated before the next part of the code is executed.
The comma operator is a weird beastie until you get to understand it, and it's not specific to while.
The expression:
exp1, exp2
evaluates exp1 then evaluates exp2 and returns exp2.
You see it frequently, though you may not realize it:
for (i = j = 0; i < 100; i++, j += 2)
You're not actually using the return value from "i++, j += 2" but it's there nonetheless. The comma operator evaluates both bits to modify both i and j.
You can pretty well use it anywhere a normal expression can be used (that comma inside your function calls is not a comma operator, for example) and it's very useful in writing compact source code, if that's what you like. In that way, it's part of the family that allows things like:
while ((c= getchar()) != EOF) {...}
i = j = k = 0;
and so on.
For your specific example:
while (c = getchar(), c != EOF && c != 'x')
the following occurs:
c = getchar() is executed fully (the comma operator is a sequence point).
c != EOF && c != 'x' is executed.
the comma operator throws away the first value (c) and "returns" the second.
the while uses that return value to control the loop.
In many languages the comma is an operator that always results in the value of the second operand. The operands are evaluated sequentially from left to right.
Pseudo-code:
a = 10
print a = 7 + 8, a * 2
Note: print is considered a statement that does not take arguments, so what comes after is considered the single expression a = 7 + 8, a * 2.
Executed like this:
First line
put 10 in a
Second line
evaluate 7 + 8 (15)
put evaluated value (15) in a
evaluate a * 2 (30)
evaluate , operator with operands 15 and 30:
always value of second operand (30)
print evaluated value (30)
To expand a bit on the other answers, in this code:
EXPRESSION_1 , EXPRESSION_2
EXPRESSION_1 is first evaluated, then there is a sequence point, then EXPRESSION_2 is evaluated, and the value of the whole thing is the value of EXPRESSION_2.
The order of operation guarantee and the sequence point are both important to the code you quoted. Together, they mean that we can be certain that the getchar() function gets called and the value of variable c is fully updated before the value of c is tested.
The comma is an operator. It returns the value of the right hand expression by default. The order of evaluation is guaranteed to be left first and then right.
UPDATE (reply to Pax's comment):
Just like most operators, it can be overloaded for user defined types:
#include <iostream>
#include <string>
using namespace std;
enum EntryType { Home, Cell, Address };
class AddressBookEntryReference {
public:
AddressBookEntryReference(const string& name, const EntryType &entry)
: Name(name), Entry(entry) { }
string Name;
EntryType Entry;
};
AddressBookEntryReference operator,(const string& name, const EntryType &type) {
return AddressBookEntryReference(name, type);
}
class AddressBook {
string test;
public:
string& operator[](const AddressBookEntryReference item) {
// return something based on item.Name and item.Entry.
// just to test:
test = item.Name;
return test;
}
};
int main() {
// demo:
AddressBook book;
cout << book["Name", Cell] // cool syntax!
<< endl;
}