Learning programming involves not only knowing that there are errors in the program and how to correct them, but also understanding where the errors are and why the computer produces such erroneous outputs. The behavior of computers is always explainable; one must understand the underlying execution logic rather than simply correcting the program. This is similar to learning mathematics, where one must not only know the solution is wrong but also understand where the mistake lies.
In a previous article, I summarized thirteen common errors encountered by beginners learning C language.
Common Errors in C Language Programming (Part One): Confusions of Beginners
This time, I will continue to summarize several errors made by students in class.
1. Forgetting to write break in the case part of the switch statement
For example, in the simple calculator program below.
When inputting 13-5, it not only outputs 13-5=8 but also outputs all subsequent statements.
The reason is that the code above forgot to write break at the end of each case handling. If break is not written, the program will not match the subsequent constant expressions but will execute the following statements one by one until it encounters a break statement or the end of the switch statement.
Modification method: Add break; at the end of the corresponding case.
2. Incorrect constant type in the case part
The case must be followed by a constant, not a variable, and the type of the constant must match the type in switch(). If the types do not match, an error will occur. For example, in the program that outputs the number of days in the current month based on the input year and month.
If compiled, a Warning will appear, but no Error.
If the warning is ignored, the program can run. For example, inputting April 2023 results in an output of Invalid Input.
The problem is that month is of type int, while the single quotes around the case are of type char. Since char is essentially an integer from 0 to 255, the system can automatically convert char to int, so the compiler does not report an error. If there are no ’10’, ’11’, ’12’, the compiler will not even give a warning.
However, the character ‘4’ corresponds to the integer value 52 in the ASCII table. Therefore, inputting 4 for the month does not yield the output “30 days”. Instead, if inputting 2023 52, it will output “30 days.”.
Another type of error is using double quotes directly. The compiler will report an error because string types cannot be automatically converted to integers.
Modification method: Remove the single or double quotes and use integer constants directly.
3. Missing space between case and constant
The compiler will not report an error, and the program can run, but the execution result will be incorrect.
Why does the compiler not report an error? This is somewhat strange. In fact, the compiler interprets “case1:” as a statement label, which can be used with the goto statement, hence it does not report an error.
Modification method: Add a space after case.
4. Errors related to logical operators
Some students attempt to use if statements to write the program that outputs the number of days based on the year and month.
This program will compile without errors, but it will always output 31 days.
Why? Because the expression month==1||3 does not check if month is equal to 1 or 3; instead, it evaluates the value of the relational expression month==1 and performs a logical OR operation with the integer constant 3. Since 3 is a non-zero value, the result of the logical OR is always true.
Modification method: Add month== before each month constant, for example, if(month==1||month==3||…)
5. Confusing == and =
This error was mentioned in a previous article, and I bring it up again because the error message is somewhat different.
This is a typical error where == is mistakenly written as =. Fortunately, this time the compiler reported an error. Generally, if the left side is a variable name, the compiler will not report an error, and such errors can be hidden deeply. The compiler’s error message tells us that the left operand of the assignment operator = must be an lvalue, while the left side of the expression year%4=0 is not an lvalue. An lvalue represents an object that occupies a recognizable position in memory, and further, its address can be taken. The left operand in an assignment statement must be an lvalue, as the assignment operation essentially updates memory, so we must find the memory address to perform the update. Note: Constants cannot be used as lvalues.
6. Adding a semicolon after the if condition expression:
It has been mentioned before that forgetting to add a semicolon at the end of a statement is a common error for beginners. However, adding an extra semicolon can also cause problems, for example:
At this point, the compiler interprets if(op==’+’); as a complete statement, meaning that when op==’+’, nothing happens, and the subsequent printf() is independent of the if statement, so printf() will execute regardless of whether op equals ‘+’.
Modification method: Remove this semicolon.
7. Writing else if() as else()
Note that else cannot be followed directly by a conditional expression; only else if can be followed by a conditional expression.
Modification method: Change else to else if.
8. Forgetting to change the loop variable’s value in while or do-while loops
For example, in the program below, the expectation is to input a series of scores and use a negative number to indicate the end of input, but it results in an infinite loop.
The problem is that the score was only input once, and the value of score was not changed afterward.
Modification method: Add a statement to change the loop variable score inside the loop, such as scanf(“%d”, &score);.
Generally, using a for loop is less likely to result in forgetting to modify the loop control variable, but with while and do-while loops, this is often overlooked, so one must always remember this.
9. Not using break in loops
The compiler will report the following error, indicating that break can only be used within loops or switch statements.
Modification method: Change break to return 0 or simply remove break and change it to:
if(m==1) printf(“%d is not a prime!\n”, m); else { … }
10. Incorrectly placing initialization statements inside the loop
Some beginners are unsure whether initialization statements should be placed inside the loop, leading to errors. For example, in the program below, the intention was to calculate 10!, but the result is product=10.
Modification method: Move the initialization statement product=1 outside the for loop.
In nested loops, similar errors are more common. One must understand whether the initialization statement should be placed outside the first loop, inside the first loop, or inside the second loop.
11. Incorrect loop termination condition
For example, the following code is used to determine if m is a prime number. The original algorithm was to check if m can be divided by any number from 2 to (m-1). If none can divide m evenly, then m is prime.
However, there is a better algorithm that checks divisibility from 2 to √m, so the student modified the code as follows:
But running this code results in incorrect judgment, and the program always outputs that it is not a prime number. The reason is that while the loop termination condition was changed, the if() condition inside did not correspondingly change; it should be modified to if(i>sqrt(m)).
Additionally, when using the break statement in a loop, there are two situations for exiting the loop: one is a normal exit when the loop condition is not met; the other is exiting through the break statement within the loop. After exiting the loop, one can determine which situation caused the exit by checking the value of the loop control variable, allowing for further operations.
12. Function name not defined
Function names, like variable names, must be defined before use.
For example, the following code attempts to output all prime numbers between two natural numbers.
However, compiling will result in an error indicating that isPrime is not defined.
The reason is that when using isPrime in the main() function, isPrime has not yet been defined; its definition appears after the main() function.
Modification methods:
(1) One method is to place the definition of the isPrime() function before the main() function;
(2) Another more universal method is to not change the definition of the isPrime() function but to add a function declaration before the main() function, as shown below.
Here we can see that function declarations and definitions can be separated; declarations are only used to inform the compiler what the function prototype looks like (i.e., what the function name is, what types of parameters it accepts, and what type of return value it has), but without the implementation (i.e., the function body), while function definitions include the function body to implement the function’s functionality. In fact, the function declaration only needs to specify the parameter types; the parameter names can be omitted, written as follows:
13. Inconsistent function names in declaration and definition
This is a low-level spelling error, for example, writing int isPrime(); in the declaration and int isPime(); in the definition.
Then, the compiler will prompt the following error message. This error is a linking error, meaning that the definition of isPrime() cannot be found.
Modification method: Ensure correct spelling.
14. Function parameters and local variable names are the same
The compiler will prompt the following error message:
This error message indicates that int n; definition shadows a parameter. Upon closer inspection, the parameter name in isPrime is n, while a local variable named n is also defined within the isPrime() function. When the operating system handles function calls, it allocates storage space for both parameters and non-static local variables, and both have the same lifetime during this function call, effectively treating them as local variables, hence their names cannot be duplicated.Having read this, please give alike and share it with friends who need it. (End of article)Author: Xuan Ba, PhD in Computer Science from the Chinese Academy of Sciences, university professor, doctoral supervisor, winner of the first prize in the National Mathematics Olympiad for middle and high school, first place in Jiangsu province, full score in mathematics in college entrance examination. Author of bestsellers “Mathematical Thinking Lessons for Children” and “Mathematical Problem-Solving Thinking Lessons for Children”.After years of refinement and practice, Xuan Ba’s thinking course is finally online; scan the code to listen or purchase. For more course introductions, see “Let’s Talk About How I Teach Mathematical Thinking Classes (with complete lecture video)“
After more than six years of establishment, the public account has organized 50 must-read articles for everyone; feel free to browse and share! If you don’t want to read the webpage, you can directly scan the code at the end of the article to purchase the book.Xuan Ba’s comprehensive guide to mathematical learning concepts, ideas, and methods (collection edition)Parents who want to join the learning group can add Xuan Ba’s work WeChat:xuanbazhushou; when adding friends, please note the answers to the following two questions, otherwise, they will not be approved.(Note: Those from Changzhou and Hainan can indicate their region to apply to join the newly opened regional group)(1) What is the decimal equivalent of binary 1.1?(2) What grade is your child in this semester? (For kindergarten, please specify large, middle, or small class)