Chapter 6 branch statements and logical operators
Forced type conversion in test conditions
As long as these true and false judgments are used, the system will forcibly convert them to the bool type. Therefore, the system will automatically complete the conversion of the general value type, however, for our custom class type or structure, we need to overload the bool forced type conversion operator to implement this function. Therefore, it is also feasible to directly place CIN> num in the IF determination, which will perform a forced conversion to show whether the last read was successful.
Conditional budget compliance error prevention
Variable = reversing the value can effectively prevent errors, because the latter assigns a variable to a constant, which will cause errors during compilation.
New sequence point
C ++ requires that, |, and & operators are all sequential points, and the colons and comma operators are also. The sequence point means that all side effects must be generated when the sequence point is encountered, and the other undefined ones must be decided by each compiler.
Other Representation
Not all keyboards provide these logical operators, so c ++ has the and, or, and not reserved words, this means that these three words cannot be expressed as variable names. You can use the C language with iso646.h as an operator.
Use the standard library cctype
Although we can use 'A' <= CH & Ch <= 'Z' to indicate whether an input is a lowercase letter, the ASCII code of these characters is continuous, in addition, we cannot simply imagine 'A' <= CH & Ch <= 'Z' to indicate whether the input is a letter. Therefore, this comparison relies on the encoding method to determine whether it is sometimes unreliable. Therefore, it is much easier to use the library functions that must be implemented by the system.
Isalnum () determines whether it is a letter or number
Isalpha () determines whether it is a letter
Iscntrl () determines whether it is a control character
Isdigit () determines whether it is a number
Isgraph () determines whether to print characters other than Spaces
Islower () determines whether it is a lowercase letter
Isprint () determines whether it is a printed character (including space)
Ispunct () determines whether it is a punctuation mark
Isspace () determines whether it is a standard blank character, such as space, paper feed, line feed, carriage return, horizontal/vertical Tab
Isupper () determines whether it is a capital letter
Isxdigit () determines whether it is a hexadecimal number 0-9, A-F, A-F
If tolower () is an upper-case letter, it is returned in lower-case; otherwise, it is returned in itself.
Toupper () returns uppercase letters if it is a lowercase letter; otherwise, returns itself.
Features of switch statements
Because there is no automatic break processing, you can implement multiple tags for unified statements. If you can use if... if the else if statement can also use the switch statement, the switch statement should be used when there are no less than three options. In terms of code length and execution speed, the switch statement is more efficient.
Chapter 7 functions-C ++ programming module
To use the C ++ function, you must do the following:
Provides function definitions;
Provides a function prototype;
Call a function.
Library functions have been defined and compiled. You can also use the standard library header file to provide its prototype. Therefore, you only need to call this function correctly.
C ++ Return Value
A function can return any type other than the array type.
Integer format Controller
% D is used to read the decimal number, % O is used to read the octal number, % x is used to read the hexadecimal number, and % I is used to automatically identify and read according to the format. For example, if % d is used and 010 is input in real time, the leading 0 is ignored, but % I is treated as the number of octal digits, and the decimal output results are 10 and 8, respectively.
Why prototype?
This can make the compiler work more efficiently. Otherwise, you need to stop the current job to find the definition of a function. This will make the efficiency very low, and these definitions may not be in the same file. The prototype has the following functions:
The compiler correctly processes the function return values;
The compiler checks whether the number of parameters used is correct;
The compiler checks whether the parameter type used is correct. If not, convert to the correct type (if possible ).
Only when it makes sense will prototyping lead to type conversion. For example, the prototype does not convert integers into structures or pointers.
Prototype during compilation is called static type check ). It can be seen that the static type check can capture many errors that are very difficult to capture during the running stage.
We know that the parameter name of the prototype is only a placeholder, but to better understand the parameter nature of the function, it is best to give an easy-to-understand name when the type is the same and it is not easy to figure out a specific parameter. We noticed that most of the database functions use type names after type redefinition, which is indeed a good compromise.
Function parameters are passed in.
Note that when passing an array name, a pointer (array name) is actually passed, just as the function cannot return an array. Of course, an array can be encapsulated using a struct, so an array can be passed.
Here we need to explain again: if we declare a two-dimensional array such as int array [3] [4.
The array address is & array and the type is int (*) [3] [4]. It is a pointer to a two-dimensional array, array + 1 equals to 48 (calculated in four bytes of an int type), that is, adding sizeof (* (& array) to the value )), it can be understood that the current pointer is removed by a pointer, And the sizeof (array) is 48.
So what is array? Its type is int (*) [4], a pointer to a one-dimensional array, array + 1 equals to 16, sizeof (* array) that is, 16.
Determining the dimension of a pointer is determined based on how many times it needs to be removed to obtain the final basic type. Therefore, array is a two-dimensional pointer and & array is a three-dimensional pointer.
How does a function use pointers to process arrays?
The meaning of int * arr and INT arr [] is the same only when the function represents a form parameter. But it is a little different in understanding. The latter tells us that the transfer will be an array, and the former may be a normal pointer to the current value.
In general, if we want to pass an array, we only need to pass an array name. Of course, if it is hard to reflect all the information of the passed parameter, you can take the address of this array name once, so that all the dimension information will be written in detail in the form parameter. In this case, the repeatable utilization of this function is greatly reduced, so the combination of two parameters is very good. For example, for a one-dimensional array, int array [10]:
Void fun (INT arr [], 10) is more versatile than void fun (INT (* ARR) [10. Although the latter gives a more detailed description of the nature of this array, STL uses the starting position and ending position of the array to represent an array.
If the array name is passed, we can only control the maximum dimension of the array. Other dimensions are hidden in this array name.
Application of const in pointer
First, let's talk about why we only use const In the pointer (it doesn't involve references learned later), because all the basic types in the pointer view are in the process of passing values, A copy is generated, and the value of the real parameter is not affected at all. Therefore, it is unnecessary to declare that the variable is read-only.
It is necessary for the pointer type, the addition of const not only enables errors in the Code where the value should not be modified, but can be found in the compilation phase (it is much easier to look for it in the runtime phase ), in addition, it makes it easier for users to read and write code.
Previously, in Chapter 4 composite type, we discussed that the common variable is to take the value as its own amount, and the address as the derived amount. Instead, the pointer uses the address as its own amount, and the value as the derived amount (we will not consider the address of the pointer for the time being ). For const, for value type, the address must be const, so there is no difference between const int num and INT const num. For pointer types, const emphasizes whether the volume itself is a derived volume. The definition is as follows:
Const int * PTR; // indicates the pointer variable pointing to a constant integer. Const emphasizes the derived amount.
Int * const PTR; // indicates the constant pointer variable pointing to an integer. Const emphasizes its own quantity.
In fact, it is to see who the PTR is first combined with. The combination of "first" and "first" is a common pointer. The rest is the description of the derived amount.
One rule: if a level-1 indirect link is involved, it is okay to assign a non-const pointer to the const pointer. However, when two levels of indirect relationships are entered, like a level-1 indirect relationship, assigning values to const and non-const pointers is no longer secure. If you allow this, you can write the code as follows:
Const int ** PP2;
Int * P1;
Const int n = 13;
PP2 = & P1; // not allowed, but if allowed
* PP2 = & N; // allowed, all of which are of the const type
* P1 = 10; // allowed, but changed the value of N
Of course, this situation may also be caused by manually converting the address of the const type value type into a non-const type.
Function pointer
Function pointers are relatively uncommon knowledge points, because they are rarely used in normal times. In fact, every function name is the address of this function, that is, its type is a function pointer, you do not need to take the address. It is a pointer.
To declare a function pointer, copy the pointer according to the prototype of a function and change the function name to (* valname. For example: Double fun (INT, double), the pointer is defined as double (* p_fun) (INT, double); then p_fun = fun; or * p_fun = fun; the two statements are equivalent, but they have different understandings. The former considers that the function name can be directly used as the address, and all pointers can be used directly, the latter thinks that since it is a pointer, of course, it is also a matter of course to remove the reference once.
Here, we use brackets to enclose p_fun because the brackets (write parameter list) are given a higher priority than the * sign. Therefore, p_fun is used in combination with the parameter list, the function pointer declaration is a function declaration that returns a double pointer.
The automatic type inference function provided by C ++ 11 can effectively solve such complicated assignment problems. Auto p_fun = fun; it's much easier than the first two.
Of course, typedef can also solve some problems. For typedef, after defining a variable, you can add a typedef before it, you can use this variable name to define other variables.