The preceding statement (January 1, March 19, 2006 ):
When I got on the machine three times, I had multiple rounds in the data center. Because no one asked a question, I took the initiative to observe how many students wrote the program, some of my classmates sat in front of the machine and saw me jump to the keyboard right away and "made" The way I was programming. So I also paid attention to the following screen to see how many lines I had written, after a while, I turned around again to see if my classmates made programming, but there was no change in the program on the screen. I was embarrassed when I saw the pretending classmates. So I chatted with a few students and asked them what the idea of programming was. After a few words, I understood that they had no idea about the problem, I do not know how to design algorithms.
After several computers, I realized that my students did not know how to think after getting a complicated question!
I felt very sad at the time. The first is the sorrow of the Teachers. If they fail to teach well, they only give the students "fish" instead of "fish ". Then the sorrow of the students has been instilled into the point where "no", too lazy to think independently.
The process of thinking is really difficult to express. It is really not easy to understand. As a teacher, the results are the simplest, but it is also difficult to explain the process of thinking and exploration. So I tried to record the main process of a program to reflect the process of thinking, it is how to design appropriate algorithms from known perspectives, compile appropriate programs, and debug them.
The following describes how to watch TV at on Saturday, record the thinking process, and write programs. The first five steps took six hours, and the sixth step (program optimization) took two hours on Sunday morning. Haha, the efficiency is a little lower. Later, I spent an hour reading all the text and modified the obvious text error. However, I didn't add any modification to the text, nor did I correct what proved to be wrong during the thinking process, add this text.
Here, I think of one of my university teachers talking about what students should learn at the university, saying, "Learn to live, learn to learn, and think ". The University is the happiest four years of life, so that we can live up to this wonderful spring. In this way, I finally wrote such a question for the following text --
I think so.
Calculate the sum (subtraction) of two integers of no more than 500 digits)
The first thing that comes to mind is that regular operations are not allowed. The key to solving this problem is:
1. How do I represent an extra-long integer?
2. How do I perform addition and subtraction on the designed data structure?
Step 1: Design the data structure and basic program structure
Obviously, you must first design the data structure:
The most direct representation is an array, and the data type can be Int or char.
L if the char type is used and an element in the array is used to save one of the integers, the char type should be converted to the int type during the intermediate operation.
L if int is used and an element in the array is used to save one of the integers, data type conversion is not required during the intermediate operation, however, you must convert the input/output values into integers.
Taking into consideration, we decided to use Char to store integer data. Therefore, you can simply use the following statement when entering:
Char string [1024]; scanf ("% s", string); the data format string stored in the array string "12345 + 678 ". Design algorithms after determining the data structure. The basic structure of the program is as follows: {input expression; returns integer 1 => array a; operator number => operator; returns integer 2 => array B; if (operator = '+') add (A, B, C); // assume that the calculation result is put into the character array C, elsesub (A, B, C ); output result array C ;}
In this way, two functions add and sub are formed to complete the addition and subtraction Operations respectively.
In this case, we need at least four arrays:
char string[1024];char a[512], b[512], c[512] ; // c = a op b
Step 2: design the core algorithm -- add
Here, there are two core algorithms. We first design addition and Add. What we are most familiar with addition operations is the method we will learn from elementary school. So we will study the addition Process in elementary school and then simulate it with a program. The manual addition process is as follows:
L vertical column, single-digit alignment;
L from the beginning of a single bit, add to the high bit by bit,
L if carry appears, carry is involved in the previous high operation.
If you use a program to simulate this process, you must first align the two integers. You can design the Add algorithm as follows:
Add1 (char a [], char B [], char C []) {one-bit alignment integer; add to the high bit by bit from the beginning ;}
Let's consider the "alignment integer bit" algorithm. Since the data input enters the array string, the highest bit is before the Array (the highest bit of the integer is before the array a [0]), therefore, we should put the forward bit at the beginning of the array (the forward bit is put into a [0]). This algorithm is actually a reverse string.
We will add the following two add algorithms:
Add2 (char a [], char B [], char C []) {reverse the array a string; // you can use the database function strrev to reverse the array B string; // alignment the single digits of an integer. The forward digits start from the single digit to the high bitwise place at the position of the array subscript 0 and add the result to array C. Reverse the array C string; // place the high position in array C at the position of array subscript 0}
Next, we will gradually refine the process of adding the intermediate values to obtain algorithm 3:
Add3 (char a [], char B [], char C []) {reverse the array a string; // you can use the database function strrev to reverse the array B string; // alignment the digits of an integer. The bitwise places are at the position of 0 in the array subscript. // The bitwise places are added to the higher bitwise places, and the result is placed in array C; I = 0; while (not the highest bit) {A [I] and B [I] corresponding bits and the preceding carry add => C [I]; I ++;} reverse the array C string; // place the high position in array C at the position of array subscript 0}
Due to the carry problem, we need to introduce a variable carry with a flag carry. The initial value is 0. Algorithm 3 can be further subdivided into algorithm 4. We can easily rewrite some of them into programs or pseudo programs.
Add4 (char a [], char B [], char C []) {int I, carry = 0; // carry bit carry strrev (); // reverse strrev (B) of string a in array; // reverse strrev (B) of string B in array // The bitwise addition starts from a bit to the high bit by bit, and the result is placed in array C; I = 0; while (not the highest bit) {If (carry + A [I] + B [I]> = 10) {carry = 1; c [I] = A [I] + B [I]-10; // here the conversion from Char to int needs to be completed} else {carry = 0; c [I] = A [I] + B [I]; // here the conversion from Char to int needs to be completed} I ++;} strrev (C ); // set the direction of the array C string}
When thinking about the while loop in the middle, I think of another problem, that is, what should I do if there are two addition integer steps with the same length? Obviously, it is not the addition of two corresponding bits. Another special case is "9999 + 1". Starting from 10 digits, the carry produced by a single digit will continue to generate a carry until one more result is produced. Therefore, the middle part of algorithm 4 is only suitable for the case of two integers with equal lengths, not for the case of unequal lengths. Therefore, we need to modify the algorithm to obtain algorithm 5.
Add5 (char a [], char B [], char C []) {int I, carry = 0; strrev (); // reverse strrev (B) of string a in array; // reverse strrev (B) of string B in array // The bitwise addition starts from a bit to the high bit by bit, and the result is placed in array C; I = 0; while (string a and string B are not over) {If (carry + A [I] + B [I]> = 10) {carry = 1; c [I] = A [I] + B [I]-10; // here the conversion from Char to int needs to be completed} else {carry = 0; c [I] = A [I] + B [I]; // here the conversion from Char to int needs to be completed} I ++;} If (string a is not over) processing the remaining high part of string a // you can call a function addcarry (A, C, int carry) else to process the remaining high part of string B // you can call a function addcarry (B, c, int carry) strrev (c); // reverse the array C string}
For the newly generated function addcarry, to process the rest of the high part, we also need to add the carry band obtained from the preceding addition. If the processing of the maximum bit of the number is complete, A new carry is generated, and a new bit is added to the result as the highest bit of the result. Therefore, we can get the addcarry algorithm.
Addcarry (char a [], char C [], int carry) {While (string a is not over) {If (carry + A [I]> = 10) {carry = 1; C [I] = A [I]-10; // the conversion from Char to int needs to be completed here} else {// No carry, then you can stop processing carry = 0; C [I] = A [I];} I ++;} If (carry! = 0) {// process the last carry C [I] = carry; C [I + 1] = '/0 '; else C [I] = '/0 ';}
Sort out the algorithm add and describe it using statements in the C language as much as possible. Obtain the Add function.
Add (char a [], char B [], char C []) {int I, carry = 0; strrev (); // reverse strrev (B) of string a in array; // reverse strrev (B) of string B in array // The bitwise addition starts from a bit to the high bit by bit, and the result is placed in array C; I = 0; while (A [I]! = '/0' & B [I]! = '/0 ') {// neither string a nor string B ends if (carry + A [I]-'0' + B [I]-'0'> = 10) {carry = 1; C [I] = A [I] + B [I]-'0'-10;} else {carry = 0; c [I] = A [I] + B [I]-'0';} I ++;} if (a [I]! = '/0') // addcarry (A, C, int carry); else if (B [I]! = '/0') // process the remaining high part of string B addcarry (B, c, int carry); strrev (c); // reverse the array C string}
Sort out the algorithm addcarry and use C-language statements to describe it. Get the addcarry function.
Addcarry (char a [], char C [], int carry) {int I = 0; while (A [I]! = '/0') {If (carry + A [I]> '9') {carry = 1; C [I] = '0 ';} else {// without carry, you can no longer process carry = 0; C [I] = A [I];} I ++;} If (carry! = 0) {// process the last carry C [I] = carry; C [I + 1] = '/0 '; else C [I] = '/0 ';}
Step 3: Prepare for data input
The expression input has been completed in step 1. The following describes how to split integers and identify operators. This algorithm is relatively simple. You only need to process characters one by one. We can simply write the following process segment:
Char string [1024], a [512], B [512], C [512], operator; int I; scanf ("% s", string); I = 0; while ('0' <= string [I] & string [I] <= '9') {// returns the integer 1 => array; A [I] = string [I]; I ++;} operator = string [I]; while ('0' <= string [I] & string [I] <= '9') {// convert integer 2 => array B; B [I] = string [I]; I ++ ;}
Step 4: design the core algorithm-sub function
.
Step 5: Merge the entire main program and complete the addition operation
Int main () {char string [1024], a [512], B [512], C [512], operator; int I; scanf ("% s ", string); I = 0; while ('0' <= string [I] & string [I] <= '9 ') {// convert the integer 1 => array A; A [I] = string [I]; I ++;} operator = string [I]; while ('0' <= string [I] & string [I] <= '9') {// convert integer 2 => array B; B [I] = string [I]; I ++;} If (operator = '+') add (A, B, C ); // assume that the calculation result is put into the character array C, elsesub (A, B, C); printf ("% s", c );}
Step 5: Debug
Write the sub function as follows:
sub (){ return;}
1. Make sure there are no syntax errors through compilation. The initial program has at least 22 errors. Added variable J.
2. Start to run the program. Input: 123 + 12. The program is running, but the displayed result is garbled. This result is very normal, because we are not a fairy, and the programmed program cannot be instantly incorrect.
3. Start running in one step to track the changes of arrays A, B, and C in the program. We found that when designing the algorithm, we didn't consider how to handle the final carry when the two integers are equal in length, so we made a small "patch ". Get the correct running result.
4. After preliminary troubleshooting, we can see that it is a system operation test case.
L 12 + 1234 // test without any carry length
L 1234 + 12 // same
L 1234 + 2341 // testing and other non-carry-long conditions
L 1089 + 8011 // test if there is an increment in the middle
L 1 + 9 // The simplest test result is an increment of 1 bit.
L 99999 + 1 // test the most common limits
L 11 + 99999 // same as above
L 0 + 88
L 88888 + 0
Note: In this process, no arbitrary long data is used, because the test data should be able to predict the running result in advance. If the running result cannot be predicted, the actual running result is displayed, the right and wrong results of the program cannot be determined, and the meaning of running the test case is lost.
Through debugging, We can find n multiple errors in the program. by tracking the value of the variable in the program, we can correct the errors and get the correct program as follows.
#include <stdio.h>int main (){ char string[1024], a[512], b[512], c[512], operator;int i, j;scanf("%s", string);i=0;while ( '0'<=string[i] && string[i]<='9' ) {a[i] = string[i];i++;}a[i]='/0';operator = string[i];i++;j=0;while ( '0'<=string[i] && string[i]<='9' ) {b[j] = string[i];i++;j++;}b[j]='/0';if ( operator=='+' )add( a, b, c);elsesub( a, b, c);printf("%s/n", c);return 0;}add ( char a[], char b[], char c[] ){ int i, carry=0;strrev(a);strrev(b);i = 0;while ( a[i]!='/0' && b[i]!='/0' ) {if ( carry + a[i]-'0' + b[i]-'0' >= 10 ) {c[i] = carry + a[i] + b[i]-'0'-10;carry = 1;}else {c[i] = carry + a[i] + b[i]-'0';carry = 0;}i++;}if ( a[i]!='/0' )addcarry( &a[i], &c[i], carry);else if ( b[i]!='/0' )addcarry( &b[i], &c[i], carry);else if ( carry!=0 ) {c[i] = carry+'0';c[i+1]='/0';}else c[i]='/0';strrev(c);}addcarry (char a[ ], char c[ ], int carry ){ int i=0;while ( a[i]!='/0' ) {if ( carry + a[i] > '9' ) {carry = 1;c[i] = '0';}else {carry = 0;c[i] = a[i];}i++;}if ( carry != 0 ) {c[i] = carry+'0';c[i+1] = '/0';}else c[i] = '/0';}sub (){ return;}
Step 6: optimization program
Obviously, this program is not an Optimized Program and should be optimized.
Possible optimizations include:
1. array A and array B can be eliminated. You can use the string space.
2. In the Add process, the reverse process of string a and string B can be avoided.
3. You can use pointers to complete string operations.
4. There is a duplicate between the Add process and addcarry where the last carry is processed.
The Optimized Program is as follows:
#include <stdio.h>int main (){ char string[1024], c[512], operator;int i;scanf("%s", string);i=0;for ( i=0; '0'<=string[i] && string[i]<='9'; i++ ) ;operator = string[i];string[i++]='/0';if ( operator=='+' )add( string, &string[i], c);elsesub( string, &string[i], c);printf("%s/n", c);return 0;}add ( char *a, char *b, char *c ){ int i, carry=0;char *p, *q, *r, *s ,*end;for ( p=a+strlen(a)-1,q=b+strlen(b)-1,r=c; a<=p && b<=q; p--,q--,r++ ) {*r = carry + *p + *q - '0';if ( *r > '9' ) {*r = *r - 10;carry = 1;}else carry = 0;}s = (a>p) ? q : p;end = (a>p) ? b : a;for ( ; s >= end; s--, r++ ) {*r = *s + carry;if ( *r > '9' ) {carry = 1;*r = '0';}else carry = 0;}if ( carry != 0 )*r++ = carry+'0';*r = '/0';strrev(c);}sub (){ return;}
Re-run the previous test cases to ensure that the test cases are completely correct.
At this time, this program is a bit like a C language program compiled by a professional.
Step 7: Re-optimize the program
In fact, this program is very wasteful in the use of array space, because an element of the array only saves one number, the efficiency is very low. We can use an array of the int type to store data, and we can also use an integer representation. This requires a new algorithm.
For the new addition algorithm, see question 10.17 and question 10.18 In the C language programming exercise set (second edition.