- Introduction to C Programming Decision and Branching Concepts
- Boolean Variables and Data Type ( or lack thereof in C )
- Relational Operators
- Logical Operators
- if-else
- switch
- The Conditional Operator
- Related Topics
- Операторы true и false — обрабатывают объекты как логическое значение.
- Логические выражения
- Пользовательские условные логические операторы
- Пример
- См. также раздел
- true and false operators — treat your objects as a Boolean value
- Boolean expressions
- User-defined conditional logical operators
- Example
- See also
Introduction to C Programming
Decision and Branching Concepts
Boolean Variables and Data Type ( or lack thereof in C )
- A true boolean data type could be used for storing logical values, and would only have two legal values — «true», and «false».
- C does not have boolean data types, and normally uses integers for boolean testing.
- Zero is used to represent false, and One is used to represent true.
- For interpretation, Zero is interpreted as false and anything non-zero is interpreted as true.
- To make life easier, C Programmers typically define the terms «true» and «false» to have values 1 and 0 respectively.
- In the old days, this was done using #define:
- #define true 1
- #define false 0
- const int true = 1;
- const int false = 0;
- The type «bool» is the same as a newly defined type «_Bool»
- _Bool is an unsigned integer, that can only be assigned the values 0 or 1
- Attempting to store anything else in a _Bool stores a 1. ( Recall that C interprets any non-zero as true, i.e. 1 )
- Variables can now be declared of type «bool».
Relational Operators
- Relational operators are binary operators that evaluate the truthhood or falsehood of a relationship between two arguments, and produce a value of true ( 1 ) or false ( 0 ) as a result.
- The following table shows the 6 relational operators and their meaning, by example:
- ( Note: There should not be a space between the two equals signs in = =. I am adding one in these HTML notes so the two signs do not run together, as ==. )
- DANGER DANGER: Do not confuse the equality test operator, = =, with the assignment operator, =. It is a VERY common error to use the wrong number of equals signs, ( either too many or too few ), and the resulting code will usually compile and run but produce incorrect ( and often unpredictable ) results.
- Example: «while( i = 5 )» is an infinite loop, because i is given the value 5 by the assignment, and since this is non-zero, it is always true. The programmer probably meant to use «while( i = = 5 )», which will test whether or not i is equal to 5, and will only continue to loop as long as this is true.
- double x, y, tolerance = 1.0E-6;
- BAD: if( x = = y )
- GOOD: if( fabs( x — y ) < tolerance )
- This is particularly important when testing the stopping condition of an iterative algorithm, because otherwise the roundoff error could cause the program to run forever. WRONG: while( estimatedError != 0.0 )
Logical Operators
- Logical operators are used to combine and evaluate boolean expressions, generally in combination with the relational operators listed above.
- The following table shows the 3 logical operators and their meaning, by example:
- Note: There should not be a space between the | characters in | |, but one is being added here for clarity.
- DANGER DANGER: If you only use a single & or | instead of the double && or | |, then you get valid code that is beyond the scope of this course, but which will not do what you want.
- ! has a very high precedence, higher than the relational operators listed above. && and | | have lower precedence than the relational operators, with && having higher precedence than | |.
- Example: To determine whether x is between 5.0 and 10.0:
- INCORRECT: 5.0 < x < 10.0
- CORRECT: 5.0 < x && x < 10.0
- Question — What is the value of the incorrect expression ( regardless of the value of x ), and why?
int year; bool leap_year; leap_year = ( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) || ( ( year % 400 ) == 0 ) ); // Or equivalently: leap_year = !( year % 4 ) && year % 100 || !( year % 400 );
- In a complex logical expression, the computer will stop evaluating the expression as soon as the result is known.
- «A && B» will not evaluate B if A is already false.
- «A | | B» will not evaluate B if A is already true.
- Example: «if( x != 0.0 && 1.0 / x < 10.0 )" will never divide by zero.
if-else
- «if» blocks and «if-else» blocks are used to make decisions, and to optionally execute certain code.
- The general syntax of the if-else structure is as follows:
if( condition ) true_block else false_block
- If the condition evaluates to true ( non-zero ), then the true_block of code is executed.
- If the condition evaluates to false ( zero ), then the false-block of code is executed if it is present.
- After one or the other block is executed, then execution continues with whatever code follows the if-else construct, without executing the other block.
- When an if-else construct is used in the true block of another if-else, that is termed nested ifs.
switch
- In many cases, an integer valued expression must be compared against a number of possible choices, such as the following:
const int left = 1, right = 2, up = 3, down = 4; // For improved readability int direction; . . . printf( "Please enter a direction, 1 for left, 2 for right, . " ); scanf( "%d", &direction ); if( direction = = left ) x--; else if ( direction = = right ) x++; else if ( direction = = up ) y++; else if ( direction = = down ) y--; else printf( "Error - Invalid direction entered.\n" );
const int left = 1, right = 2, up = 3, down = 4; // For improved readability int direction; . . .
printf( "Please enter a direction, 1 for left, 2 for right, . " ); scanf( "%d", &direction ); switch( direction ) < case left: x--; break; case right: x++; break; case up: y++; break; case down: y--; break; default: printf( "Error - Invalid direction entered.\n" ); break; >/* End of switch on direction */
- If the break statement is omitted from the end of a case, then execution will continue into the next case, and so on until a break is eventually encountered, or until the end of the switch is reached.
- Omitting the break statement is a common mistake.
- Sometimes the break is omitted intentionally, in order to combine cases:
bool done = false; // Assumes stdbool.h has been #included char choice; while ( ! done ) < // Code to print out a menu and ask for choice omitted scanf( "%c", &choice ); switch( choice ) < case 'E': case 'e': /* Code here to handle Entering data */ break; case 'C': case 'c': /* Code here to handle Calculations */ break; case 'H': case 'h': case '?': /* Code here to deliver Help */ break; case 'Q': case 'q': done = true; break; default: printf( "Error - Invalid choice: %c\n", choice ); printf( "Choose 'H' for help.\n"; break; >/* End of switch on menu choices */ > /* End of infinite while loop */
The Conditional Operator
Earlier we looked at unary and binary operators under C. In addition, the C language contains one ternary operator, known as the conditional operator, ?:
- The conditional operator functions very much like an if-else construct, and the two constructs can often be used interchangeably.
- However, due to its operator status, the results of the conditional operator can also be used as part of a larger expression and/or be assigned to a variable.
- The syntax of the conditional operator is:
condition ? true_clause : false_clause
- The condition is first evaluated, ( along with any side effects. ) Then, either the true clause or the false clause will be executed, ( along with any side effects ), depending on whether the condition evaluates to true ( non-zero ) or false ( zero ) respectively. The value of the conditional operator as used in a larger expression is the value of whichever clause gets executed.
- Examples:
max = i > j ? i : j; abs = x > 0 ? x : -x; printf( "X is %s.\n", ( x < 0 ? "negative" : "non-negative" ) );
// Parentheses needed in the last example because + and * higher than > and ?: pay = base + ( sales > quota ? 1.5 : 1.0 ) * bonus;if( error < tolerance ) step *= 2.0; else step = 1.0; if( x != 0.0 ) z /= x; else z = infinite; if( x >0.0 ) sign = 1.0; else if ( x = = 0.0 ) sign = 0.0; else sign = -1.0;
Related Topics
The following topics are not covered here, but may be found in many books on C/C++;
- Bitwise logical operators, | and &, ^, and ~
- Bit shift operators, >
- Combinations of these with assignment, e.g. |=, &=, >=, and ^=.
Операторы true и false — обрабатывают объекты как логическое значение.
Оператор true возвращает значение bool true , указывая, что его операнд имеет значение true. Оператор false возвращает значение bool true , указывая, что его операнд имеет значение false. Операторы true и false не обязательно дополняют друг друга. То есть оба оператора true и false могут вернуть значение bool false для одного операнда. Если тип определяет один из двух операторов, он должен также определять другой оператор.
Используйте тип bool? , если вам нужно использовать трехзначную логику (например, при работе с базами данных, которые поддерживают трехзначный логический тип). В C# предоставляются операторы & и | , которые поддерживают троичную логику с операндами bool? . См. подробнее о логических операторах, поддерживающих значение NULL в описании логических операторов.
Логические выражения
Тип с определенным оператором true может быть типом результата управляющего условного выражения в операторах if, do, while и for и условном операторе ?: . Дополнительные сведения см. в описании логических выражений в спецификации языка C#.
Пользовательские условные логические операторы
Если тип с определенными операторами true и false перегружает логические операторы OR | или AND & определенным образом, условные логические операторы OR || или AND && соответственно могут вычисляться для операндов этого типа. Дополнительные сведения см. в разделе Пользовательские условные логические операторы в Спецификации языка C#.
Пример
В следующем примере представлен тип, который определяет операторы true и false . Этот тип также перегружает логический оператор И & таким образом, что оператор && может быть вычислен для операндов этого типа.
public struct LaunchStatus < public static readonly LaunchStatus Green = new LaunchStatus(0); public static readonly LaunchStatus Yellow = new LaunchStatus(1); public static readonly LaunchStatus Red = new LaunchStatus(2); private int status; private LaunchStatus(int status) < this.status = status; >public static bool operator true(LaunchStatus x) => x == Green || x == Yellow; public static bool operator false(LaunchStatus x) => x == Red; public static LaunchStatus operator &(LaunchStatus x, LaunchStatus y) < if (x == Red || y == Red || (x == Yellow && y == Yellow)) < return Red; >if (x == Yellow || y == Yellow) < return Yellow; >return Green; > public static bool operator ==(LaunchStatus x, LaunchStatus y) => x.status == y.status; public static bool operator !=(LaunchStatus x, LaunchStatus y) => !(x == y); public override bool Equals(object obj) => obj is LaunchStatus other && this == other; public override int GetHashCode() => status; > public class LaunchStatusTest < public static void Main() < LaunchStatus okToLaunch = GetFuelLaunchStatus() && GetNavigationLaunchStatus(); Console.WriteLine(okToLaunch ? "Ready to go!" : "Wait!"); >static LaunchStatus GetFuelLaunchStatus() < Console.WriteLine("Getting fuel launch status. "); return LaunchStatus.Red; >static LaunchStatus GetNavigationLaunchStatus() < Console.WriteLine("Getting navigation launch status. "); return LaunchStatus.Yellow; >>
Обратите внимание на поведение сокращенного вычисления оператора && . GetFuelLaunchStatus Когда метод возвращает LaunchStatus.Red значение , правый операнд && оператора не вычисляется. Это обусловлено тем, что LaunchStatus.Red имеет значение false. Результат логического оператора И не зависит от значения правого операнда. Выходные данные примера могут быть следующими:
Getting fuel launch status. Wait!
См. также раздел
true and false operators — treat your objects as a Boolean value
The true operator returns the bool value true to indicate that its operand is definitely true. The false operator returns the bool value true to indicate that its operand is definitely false. The true and false operators aren’t guaranteed to complement each other. That is, both the true and false operator might return the bool value false for the same operand. If a type defines one of the two operators, it must also define another operator.
Use the bool? type, if you need to support the three-valued logic (for example, when you work with databases that support a three-valued Boolean type). C# provides the & and | operators that support the three-valued logic with the bool? operands. For more information, see the Nullable Boolean logical operators section of the Boolean logical operators article.
Boolean expressions
A type with the defined true operator can be the type of a result of a controlling conditional expression in the if, do, while, and for statements and in the conditional operator ?: . For more information, see the Boolean expressions section of the C# language specification.
User-defined conditional logical operators
If a type with the defined true and false operators overloads the logical OR operator | or the logical AND operator & in a certain way, the conditional logical OR operator || or conditional logical AND operator && , respectively, can be evaluated for the operands of that type. For more information, see the User-defined conditional logical operators section of the C# language specification.
Example
The following example presents the type that defines both true and false operators. The type also overloads the logical AND operator & in such a way that the && operator also can be evaluated for the operands of that type.
public struct LaunchStatus < public static readonly LaunchStatus Green = new LaunchStatus(0); public static readonly LaunchStatus Yellow = new LaunchStatus(1); public static readonly LaunchStatus Red = new LaunchStatus(2); private int status; private LaunchStatus(int status) < this.status = status; >public static bool operator true(LaunchStatus x) => x == Green || x == Yellow; public static bool operator false(LaunchStatus x) => x == Red; public static LaunchStatus operator &(LaunchStatus x, LaunchStatus y) < if (x == Red || y == Red || (x == Yellow && y == Yellow)) < return Red; >if (x == Yellow || y == Yellow) < return Yellow; >return Green; > public static bool operator ==(LaunchStatus x, LaunchStatus y) => x.status == y.status; public static bool operator !=(LaunchStatus x, LaunchStatus y) => !(x == y); public override bool Equals(object obj) => obj is LaunchStatus other && this == other; public override int GetHashCode() => status; > public class LaunchStatusTest < public static void Main() < LaunchStatus okToLaunch = GetFuelLaunchStatus() && GetNavigationLaunchStatus(); Console.WriteLine(okToLaunch ? "Ready to go!" : "Wait!"); >static LaunchStatus GetFuelLaunchStatus() < Console.WriteLine("Getting fuel launch status. "); return LaunchStatus.Red; >static LaunchStatus GetNavigationLaunchStatus() < Console.WriteLine("Getting navigation launch status. "); return LaunchStatus.Yellow; >>
Notice the short-circuiting behavior of the && operator. When the GetFuelLaunchStatus method returns LaunchStatus.Red , the right-hand operand of the && operator isn’t evaluated. That is because LaunchStatus.Red is definitely false. Then the result of the logical AND doesn’t depend on the value of the right-hand operand. The output of the example is as follows:
Getting fuel launch status. Wait!
See also
- In the old days, this was done using #define: