Click to understand Variable length parameter,Variable parameter function
Why can I only implement a simple version of printf, because there are many optimizations involved, such as storage, data structure, output color and so on, and my program only implements an integer module. And there is no improvement, like%d02, and so on, just a design idea, but also the application of variable parameter function
Overall ideas:
1. First implement, print a string of characters, use putchar
2. How to realize the value of the print parameter and use the variable parameter function to get the latter variable
3. Record the number of prints (Fusion 1, 2)
4. Optimizing Code in Continuous Trials and Errors
Let's do it step by step
Function 1: Ability to print a complete string
Here we implement my_based on putchar() Printf, compare with printf
The process generation code is as follows:
#include<stdio.h> //Before const, the value in the frm is constant, the address is allowed to change, and the value is not allowed to change int my_printf(const char *frm,...) { //Receive a String int cnt = 0; //Record the number of characters printed for(int i = 0; frm[i]; i++) { //A value of 0 at the end of the string is false and traverses to the end naturally putchar(frm[i]),++cnt; } return cnt; } int main() { printf("hello word\n"); my_printf("hello word\n"); return 0; }
The function implementation of the program is to overlay the code on the original basis, and the best thing about printf is to be able to print the value of a variable, which is based on the ability of a variable parameter function.
Function 2: Print the value of a variable
Procedure two: Idea: First, to parse the string, encounter%,%d,%c, etc., code is limited, only parse the contents of%d,
->Target to achieve print integer 123
Principal function
int main() { int a = 123; printf("hello word\n"); my_printf("hello word\n"); printf("int (a) =%d\n",a); my_printf("int (a) =%d\n",a); return 0; }
Print results:
Does it look a bit like that? Let's move on to the third step, because of the uncertainty of the data, we need a variety of errors to debug
Process three: adjustment and trial and error
1 Data Flip: First of all, because the number of bits in the data cannot be determined, we use the method of printing the data from the end, which also results in the reversal of the data from the original data, so we need to flip the data before printing.
Modify:
case 'd' : { //Because reshaping cannot be done together, only one bit of output can be in character form int x = va_arg(arg, int); int temp = 0; while(x){ temp = temp*10 + x % 10; x /=10; } while (temp) { PUTC(temp % 10 + '0'); temp /= 10; } }break;
The results show:
2. Optimizing Input 0 and Negative Numbers
Positive and Negative Judgment Introduced
case 'd' : { int x = va_arg(arg, int); if(x == 0) { PUTC('0'); } else { if(x < 0) x = -x, PUTC('-'); int temp = 0; while(x){ temp = temp*10 + x % 10; x /=10; } while (temp) { PUTC(temp % 10 + '0'); temp /= 10; } } }break;
The result is feasible
3, to solve the problem left over by flipping, input 1000, flip becomes 0001, the final output is 1
Modify the flip section to introduce a variable, digit, number of records
4, output 32-bit integer maximum and minimum, introduce header file #include<inttypes.h>
First result:
Error Reason: Maximum flip exceeds the maximum of 32-bit integers (about 2 billion).
Solution 1: Define a 64-bit integer, but all have limitations
Solution 2: Bitwise representation, where each bit is stored in an array
Solution three: divide the integer into two parts, high and low, this time use the high five-digit, low five-digit form of processing
10 bits can represent 10 million, 10 billion sizes
Optimize Code
After optimization
5. Question optimization with 0 between high and low position i.e. input 100500
Look first at the error results
Error analysis: low 00500, or 500, flipped to 5, digit2 = 3,
Passed
if(x1) digit2 =5; //If the top five is not zero, the bottom five will be full, but there may be a gap between the top five and the fifth.
The output process is wrong
Code optimization: 0 for the middle
Function 3: Test if the number of characters printed successfully is correct
The code is as follows: Actually, thanks to having cnt records for each print
int a = 123,n; while(~(scanf("%d",&n))) { //Show number of successful prints printf(" has %d digits!\n",printf("%d",n)); my_printf(" has %d digits!\n",my_printf("%d",n)); } return 0;
The results are as follows:
Whole program (Output data in program, think about direct forward printing?)
#include<stdio.h> #include<inttypes.h> #include<stdarg.h> #include<limits.h> #Define PUTC(a) putchar(a), ++cnt //Parse the following format to encapsulate the macro as a function int revers(int num,int *temp) { int digit = 0; do { digit++; *temp = *temp * 10 + num % 10; num /= 10; }while(num); return digit; } int output_num (int num,int digit) { int cnt = 0; while(digit--) { putchar(num % 10 + '0'), ++cnt; num /= 10; } return cnt; } //Before const, the value in the frm is constant, the address is allowed to change, and the value is not allowed to change int my_printf(const char *frm,...) { //Receive a String int cnt = 0; va_list arg; va_start(arg , frm); for(int i = 0; frm[i]; i++) { //A value of 0 at the end of the string is false and traverses to the end naturally switch(frm[i]){ case '%': { switch (frm[++i]) { case '%' : PUTC(frm[i]); break; //Because reshaping cannot be done together, only one bit of output can be in character form case 'd': { int x = va_arg(arg, int); uint32_t xx = 0; if (x < 0) PUTC('-'), xx = - x; //Negative Edge Positive Number else xx = x; int x1 = xx / 100000, x2 = xx % 100000; //x1 high five digits, x2 low five digits int temp1 = 0, temp2 = 0; int digit1 = revers(x1, &temp1); //Outgoing parameters, the parameters that are passed through the operation; The following temp1,2 is used directly, no longer defining new variables int digit2 = revers(x2, &temp2); //Number of Records int digit3 = 0; //Record 0 in the middle of 5 lower to 5 higher bits if(x1) digit3 = 5 - digit2; //If the high bit is not zero, the low five bit is five else digit1 = 0; //Otherwise, the high quintile is zero cnt += output_num(temp1,digit1); cnt += output_num(0, digit3); cnt += output_num(temp2,digit2); } break; case 's' : { const char *str = va_arg(arg, const char *); for(int i = 0; str[i]; i++){ PUTC(str[i]); } } break; } } break;//First%End default : PUTC(frm[i]) ; break; //Print directly without meeting% } } //#undef PUTC //is a PUTC non-PUTC(a) va_end(arg); return cnt; } int main() { int a = 123,n; while(~(scanf("%d",&n))) { //Show number of successful prints printf(" has %d digits!\n",printf("%d",n)); my_printf(" has %d digits!\n",my_printf("%d",n)); } return 0; char str[] = "I love china"; printf("hello word\n"); my_printf("hello word\n"); printf("int (a) = %d\n",a); my_printf("int (a) = %d\n",a); printf("int (a) = %d\n",0); my_printf("int (a) = %d\n",0); my_printf("int (a) = %d\n",-123); printf("int (a) = %d\n",-123); printf("int (a) = %d\n",INT_MAX); my_printf("int (a) = %d\n",INT_MAX); printf("int (a) = %d\n",INT_MIN); my_printf("int (a) = %d\n",INT_MIN); printf("int (100500) = %d\n",100500); my_printf("int (100500) = %d\n",100500); printf("str = %s\n",str); my_printf("str = %s\n",str); return 0; }