From csdn Community Electronic Magazine-C/C ++ magazine
Http://emag.csdn.net January 2005 total period 1st-93-
This article steedhorse (Morning Star)
Printf may be the second function that many programmers encounter when learning C language (I guess the first function is main ),
Naturally, you are an old friend. But do you know more about this old friend? You know more about sprintf.
? When constructing various types of data into strings, sprintf's powerful features rarely disappoint you.
Since sprintf and printf are almost the same in usage, they only print different destinations. The former is printed into strings,
The latter is output directly on the command line. This also makes sprintf much more practical than printf. So this article focuses on sprintf, sometimes
It is also interspersed with pritnf.
Sprintf is a variable struct function, which is defined as follows:
Int sprintf (char * buffer, const char * Format [, argument]...);
In addition to the fixed number types of the first two shards, Multiple shards can be followed. And its essence is obviously in the second vertex number:
Format the string.
Both printf and sprintf use formatted strings to specify the string format. Some strings starting with "%" are used inside the format string.
Format specifications
The function replaces the specifier with the variable at the corresponding position to generate a string that the caller wants.
Format a numeric string
One of the most common applications of sprintf is to print Integers to strings. Therefore, spritnf can replace
ITOA. For example:
// Print the integer 123 into a string and save it in S.
Sprintf (S, "% d", 123); // generate "123"
The width can be specified. If the width is insufficient, spaces are filled on the left:
Sprintf (S, "% 8d % 8d", 123,456 7); // generate: "123 4567"
Of course, it can also be left aligned:
Sprintf (S, "%-8d % 8d", 123,456 7); // generate: "123 4567"
It can also be printed in hexadecimal format:
Sprintf (S, "% 8x", 4567); // lowercase hexadecimal notation, with 8 width positions and right alignment
Sprintf (S, "%-8x", 4568); // in hexadecimal notation, the width occupies 8 positions and is left aligned.
In this way, the hexadecimal string of an integer is very easy to get, but when we print the hexadecimal content, we usually want
In the left side of the fill 0 equal width format, then how to do it? It is very simple. Add 0 to the front of the number indicating the width.
Sprintf (S, "% 08x", 4567); // generate: "201711d7"
The above 10-digit printing with "% d" is the same, so the left side can be filled with 0.
Pay attention to a symbol extension problem: for example, if we want to print the short INTEGER (short)-1 memory 16 into tabulation
Format: On the Win32 platform, a short type occupies 2 bytes, So we naturally want to use 4 hexadecimal numbers
Print it:
Short Si =-1;
Sprintf (S, "% 04x", Si );
Why is "ffffffff" generated? Since spritnf is a variable attention function, apart from the first two arguments
The number of workers is not of type security, and the function cannot simply use a "% x" to know that the number of workers on the stack before the function is called.
Is it a 4-byte integer or a 2-byte short integer, so the bytes adopts a unified 4-byte processing method,
As a result, the number of workers is expanded to a 32-bit integer-1 when the stack is pressed. If the four positions are insufficient, the 32-bit integer is used.
-The 8-digit and 16-digit of 1 are printed. If you want to see the original form of Si, you should let the compiler implement 0 extension instead
Symbol extension (when expansion is performed, the left side of the binary complement 0 instead of the complement sign bit ):
Sprintf (S, "% 04x", (unsigned short) Si );
You can. Or:
Unsigned short Si =-1;
Sprintf (S, "% 04x", Si );
Sprintf and printf can also print integer strings in octal, using "% O ". Note that both hexadecimal and hexadecimal are not supported.
Negative numbers are all unsigned. In fact, they are directly hexadecimal or octal representation of the internal code of the variable.
Control floating point print format
The printing and format control of floating point numbers is another frequently used function of sprintf. Floating Point Numbers are controlled by the format character "% F", which is guaranteed by default.
6 digits after the decimal point, for example:
Sprintf (S, "% F", 3.1415926); // generate "3.141593"
But sometimes we want to control the print width and decimal places, then we should use the format "% m. NF", in which the M Table
The print width. N indicates the number of digits after the decimal point. For example:
Sprintf (S, "% 10.3f", 3.1415626); // generate: "3.142"
Sprintf (S, "%-10.3f", 3.1415626); // generate: "3.142"
Sprintf (S, "%. 3f", 3.1415626); // The total width is not specified, resulting in: "3.142"
Pay attention to one question, you guess
Int I = 100;
Sprintf (S, "%. 2f", I );
What will it do? 100.00 "? Right? You can try the following at the same time:
Sprintf (S, "%. 2f", (double) I );
The first one is definitely not the correct result. As mentioned above, the caller does not know
The corresponding format controller is "% F ". When a function is executed, the function itself does not know that the number pushed to the stack in the current year is an integer,
So the four bytes that saved the integer I were forcibly interpreted as a floating-point number.
However, if someone is interested in manually encoding a floating point number, you can use this method to test your hand.
Is the orchestration result correct .?
Character/ASCII code comparison
We know that in C/C ++, char is also a common scalable type, in addition to the word length, it corresponds to short,
There is no essential difference between int and long types. They are just used to represent characters and strings. (Maybe we should
This type is called "byte", and now we can use byte or short to set char through typedef based on the actual situation.
)
Therefore, print a character using "% d" or "% x" to obtain its 10-or 16-digit ASCII code.
And print an integer using "% C" to see the corresponding ASCII characters. The following sections describe all visible characters
The ASCII code comparison table is printed to the screen (here, printf is used for the watermark. Note that when "#" and "% x" are used, you add "0x" to the hexadecimal number"
Prefix ):
For (INT I = 32; I <127; I ++ ){
Printf ("[% C]: % 3d 0x % # 04x/N", I, I );
}
Connection string
Since the sprintf format control string can insert various things and finally "connect them into a string", it will naturally be able to connect
In many cases, it can replace strcat, but sprintf can connect multiple strings at a time (naturally, it can also
Insert other content among them, which is flexible in short ). For example:
Char * Who = "I ";
Char * Whom = "csdn ";
Sprintf (S, "% s love % S.", who, whom); // generate: "I love csdn ."
Strcat can only connect strings (an array of characters ending with '/0' or a character buffer, null-terminated-string ),
But sometimes we have two character buffers, they do not end with '/0. For example, many characters returned from third-party library functions
Groups, which are read from hardware or network transmission. They may not end with a corresponding '/0' after each character sequence.
Tail. Assuming that direct connection, whether sprintf or strcat will certainly lead to illegal memory operations, and strncat also requires at least
What should I do if the number of partitions is null-terminated-string? We naturally remember the previous sections on printing integers and floating-point numbers.
The width can be specified, and the string is the same. For example:
Char A1 [] = {'A', 'B', 'C', 'D', 'E', 'F', 'G '};
Char A2 [] = {'h', 'I', 'J', 'k', 'l', 'M', 'n '};
Hypothesis:
Sprintf (S, "% S % s", a1, a2); // don't do that!
In, something went wrong. Can it be changed:
Sprintf (S, "% 7 S % 7 s", a1, a2 );
It's not good where to go. The correct one should be:
Sprintf (S, "%. 7 S %. 7 s", a1, a2); // generate: "abcdefghijklmn"
This can be analogous to printing the "% m. NF" of floating point numbers. In "% m. Ns", M indicates the occupied width (when the string length is insufficient, it is null)
If the number is exceeded, it is printed according to the actual width.) n indicates the maximum number of characters that can be used from the corresponding string. Usually printing words
M is useless when it is a string, or N is used after the dot. Naturally, it can only take part of the characters before and after:
Sprintf (S, "%. 6 S %. 5 s", a1, a2); // generate: "abcdefhijkl"
In many cases, we may also want the numbers in these format controllers to specify length information to be dynamic, rather
It is specified statically. In many cases, it is only necessary for the program to obtain several characters in the character array before execution.
The dynamic width/precision setting function is also taken into account in the implementation of sprintf. sprintf uses "*" to occupy
The position of a constant number with a specified width or accuracy, which is the same as that of other printed variables.
The sample is provided, so the above sample can be changed:
Sprintf (S, "%. * S %. * s", 7, A1, 7, A2 );
Or:
Sprintf (S, "%. * S %. * s", sizeof (A1), A1, sizeof (A2), A2 );
In fact, the printed characters, integers, and floating-point numbers described above can all dynamically specify the constant values. For example:
Sprintf (S, "%-* D", 4, 'A'); // generate "65"
Sprintf (S, "% #0 * X", 8,128); // generate "0x000080", "#" generate 0x
Sprintf (S, "% *. * F", 10, 2, 3.1415926); // generate "3.14"
Print address information
Sometimes, when debugging a program, we may want to view the addresses of some variables or members. Because the addresses or pointers are only 32-bit numbers, you can print them out using the "% u" that prints the unsigned integer:
Sprintf (S, "% u", & I );
Generally, people prefer to use hexadecimal instead of hexadecimal to display an address:
Sprintf (S, "% 08x", & I );
However, these are indirect methods. For address printing, sprintf provides a special "% P ":
Sprintf (S, "% P", & I );
I think it is actually equivalent:
Sprintf (S, "% 0 * X", 2 * sizeof (void *), & I );
Use sprintf's Return Value
Few people pay attention to the return values of the printf/sprintf function, but sometimes it is practical. spritnf returns the function call.
The number of characters finally printed to the character buffer. That is to say, after a sprinf call ends, you do not need to call it again.
Strlen knows the length of the result string. For example:
Int Len = sprintf (S, "% d", I );
For a positive integer, Len is equal to the 10-digit digits of the integer I.
The following is a complete example, which generates a random number between 10 [0,100) and prints them to a character array S,
Separated by commas.
# Include <stdio. h>
# Include <time. h>
# Include <stdlib. h>
Int main (){
Srand (time (0 ));
Char s [64];
Int offset = 0;
For (INT I = 0; I <10; I ++ ){
Offset + = sprintf (S + offset, "% d,", Rand () % 100 );
}
S [offset-1] = '/N'; // Replace the last comma with a line break.
Printf (s );
Return 0;
}
Imagine that when you extract a record from the database and want to connect each of their fields into a word according to certain rules
This method can be used when a string is called. Theoretically, it is more efficient than the continuous strcat method.
You must first find the last '/0' position, and in the example given above, we use the sprintf return value
Position.
FAQ about using sprintf
Sprintf is a variable memory function, which often causes problems when used, and only causes problems. Generally, it is the Memory memory that can cause program crash.
Wrong question, but fortunately the problems caused by the misuse of sprintf are very serious, but it is very easy to find out, nothing more than the following situations
I often use my eyes to read the wrong code.
?? Buffer Overflow
The length of the first Shard is too short. If you don't want to say it, just give it a bigger one. Of course, it may also be the question of the number of shards.
We recommend that you be careful when changing the number of characters. When printing a string, use the "%. Ns" format to specify the maximum number of characters.
?? I forgot the first shard number.
Low-level users cannot have low-level problems. They are too familiar with printf. // It is common. :. (
?? A problem occurs when the volume changes.
Generally, you forget to provide a corresponding token to change the token, which leads to misplacement of all future tokens. Check the token. You
Is the number of vertices corresponding to "*" provided? Do not set an integer to "% s". The compiler will think that you
It's so bad (the compiler is the mother of OBJ and exe, it should be a female, P ).
Strftime
Sprnitf also has a good cousin: strftime, which is specially used to format the time string. The method of use is very similar to that of her cousin.
Is a lot of format control operators, just after all, the little girl is careful, she also needs to specify the maximum length of the buffer, may be
In the event of a fault, you can shirk responsibility. Here is an example:
Time_t t = time (0 );
// Generate a string in the format of "YYYY-MM-DD hh: mm: SS.
Char s [32];
Strftime (S, sizeof (s), "% Y-% m-% d % H: % m: % s", localtime (& T ));
Sprintf can also find its Zhiyin: cstring: format in MFC, and strftime naturally has her same path in MFC:
Ctime: format, which is more elegant because of the sponsorship of the object-oriented code.
Postscript
All of the functions described in this article can be easily found in msdn. I only use them based on my own experience,
Some examples are used to introduce some frequently used and practical methods, which may be a little bit confusing for many people who are new to learning.
Don't joke at home, and I hope everyone will criticize and correct it.
Some people think that such a function with variable degrees will cause various problems, so it is not recommended to use it. But I can't resist it
The temptation of their powerful functions has been used in practical work. In fact, C #. Net supports the change from the very beginning, just published
Later, java5.0 also supported failover.
Thanks to ericzhangali for carefully reviewing the entire article, correcting many minor mistakes, and providing some suggestions.
I would also like to thank laomai for reading the entire article and providing suggestions for adding and deleting some content.