Selected from "9CBS Community Electronic Magazine - C / C Journal"
Http://emag.9cbs.Net January 2005 Total No. 1 - 93 -
Author: steedhorse (Morningstar)
Printf may be the second function that many programmers get in touch with the C language (I guess the first is main), say
Get up, naturally the old friend, but have you learned how much to this old friend? You have a lot of twins brothers sprintf.
? When constructing various types of data into a string, the powerful feature of Sprintf rarely disappoints you.
Since sprintf is almost the same as the Printf, only the destination of print is different, the former prints into the string,
The latter is output directly on the command line. This also causes sprintf to be much useful than Printf. So this article focuses on Sprintf, sometimes
Also inserted with PRITNF.
Sprintf is a variable-gate function, defined as follows:
INT Sprintf (Char * Buffer, Const Char * Format [, Argument] ...);
In addition to the first two parameter types, you can pick up any multiple parameters. And its essence, obviously in the second parameter:
Formatted on strings.
Both PRINTF and SPRINTF use formatted strings to specify the format of the string, and use some "%" inside the format string.
Format Specifications to occupy a location, providing the corresponding variables in the backward parameters of the rear, eventually
The function will replace the specifier with the variable of the corresponding position and generate a string you want.
Formatted numeric string
One of the most common applications of sprintf is too much to print integers into the string, so spritnf can be replaced in most occasions.
ITOA. Such as:
// Print the integer 123 into a string saved in s.
Sprintf (s, "% d", 123); // Generate "123"
You can specify the width, insufficient left resilience:
Sprintf (S, "% 8D% 8D", 123, 4567); // Produce: "123 4567"
Of course, you can align the left:
Sprintf (s, "% -8d% 8D", 123, 4567); // generation: "123 4567"
You can also print according to 16-based printing:
Sprintf (s, "% 8x", 4567); // lowercase 16-based, the width accounts for 8 positions, right alignment
Sprintf (s, "% -8x", 4568); // uppercase 16-based, the width is 8 positions, left alignment
In this way, an integer's 16 credit string is easy, but we usually want one when printing 16 credit content.
What should I do if I have a equivalent format of the left? Very simple, add 0 in front of the number indicating the width.
Sprintf (s, "% 08x", 4567); // generation: "000011d7"
10% of "% D" is also used as well as this left to supplement 0.
Here you should pay attention to a symbol extension problem: For example, if we want to print short integer (short) -1 memory 16 enrollment table
In the form of the Win32 platform, a short type occupies 2 bytes, so we naturally want to print it with 4 16 credits:
Short Si = -1;
Sprintf (s, "% 04x", si);
Generate "ffffffffff", what is going on? Because spritnf is a variable-gate function, in addition to the front two parameters, behind
The parameters are not type safe. There is no way to function only by a "% x" to know the parameter stack of the initial function call.
When it is pressed in the end, it is a 4-byte integer or a short integer of 2 bytes, so it has taken a unified 4 byte processing method.
The symbol extension is made when the parameter stack is expanded into 32-bit integers-1. When printing, 4 positions are not enough, and 32-bit integers
-1's 8-bit 16 enrichment is printed. If you want to see the original face of Si, you should make the compiler do 0 expansions rather than
Symbol extension (补 二 二 二 0 0 0 而 位:):
Sprintf (S, "% 04x", (unsigned short) si);
Yes. or:
UNSIGNED SHORT SI = -1;
Sprintf (s, "% 04x", si);
Sprintf and Printf can also press 8-based printing a nutrient, using "% O". Pay attention to 8 credits and 16 credits will not play
The negative number is not a symbol, which is actually a direct 16-encoded direct 16-encoded direct 16 binary representation of the variable.
Control floating point number print format
Print and format control of floating point numbers is another common function of sprintf, floating point number uses format "% F" control, default security
6 digits after a decimal point, such as:
Sprintf (s, "% f", 3.1415926); // Generate "3.141593"
But sometimes we want yourself to control the width of the print and decumeration, then you should use: "% m.nf" format, where M table
Show the width of the print, n represents the number of digits after the decimal point. such as:
Sprintf (s, "% 10.3f", 3.1415626); // produces: "3.142"
Sprintf (s, "% -10.3f", 3.1415626); // generation: "3.142"
Sprintf (s, "% .3f", 3.1415626); // does not specify the total width, produce: "3.142"
Pay attention to a problem, you guess
INT i = 100;
Sprintf (s, "% .2f", i);
What will play Dongdong? "100.00"? right? I will try it yourself, and try it below:
Sprintf (s, "% .2f", (double) i);
The first one is definitely not a correct result, the reason is the same as mentioned above, the caller when the parameter stack does not know with I
The corresponding format control is a "% f". When the function execution, the function itself does not know that the incorporated in the stack is an integer.
So the four bytes of poor storage integer i were unable to be intended to be in the floating point in the floating point, and the whole chaos.
However, if someone is interested in using a floating point number, then you can use this method to check your hand.
Whether the results of the engineering row are correct. ?
Character / ASCII code control
We know that in the C / C language, Char is also a normal scalable type. In addition to the word length, it does not essentially difference from Short, int, long, but is used to represent characters and strings. Yes. (Maybe this year
This type is called "Byte", and then it can now use Byte or Short to set the char through Typedef according to the actual situation.
Righteousness, this is more suitable)
Thus, using "% D" or "% x" to print a character, it can derive its 10 credit or 16-based ASCII code;
Come, use "% C" to print an integer, you can see the ASCII character it corresponds. The following blocks put all visible characters
The ASCII code control table is printed onto the screen (here the Printf is used, pay attention to "#" and "% X" is used to add "0x".
Prefix):
For (int i = 32; i <127; i ) {
Printf ("[% C]:% 3D 0x% # 04x / n", i, i, i);
}
Connection string
Since the Sprintf's format control string can insert a variety of things, and ultimately "connect them into a string", naturally
String, thereby replacing Strcat in many occasions, but Sprintf can connect multiple strings at a time (naturally, you can simultaneously
Insert other content in them, in short, very flexible). such as:
Char * who = "i";
Char * whom = "9cbs";
Sprintf (s, "% s love% s.", WHO, WHOM); // generation: "i love 9cbs."
STRCAT can only connect to the string (a character array ending with '/ 0' or called character buffer, null-tERMINATED-STRING),
But sometimes we have two character buffers, they are not ending with '/ 0'. For example, many characters returned from third-party library functions
Group, the character stream read from hardware or network transmissions, they don't have to have a corresponding '/ 0' after each character sequence.
tail. If you are directly connected, no matter whether Sprintf or Strcat will definitely cause illegal memory operation, and Strncat also requires at least the first
What should I do if a parameter is a null-terminated-string. What should I do? We will naturally think of the previous introduction of print integers and floating point numbers.
You can specify the width and the string is the same. such as:
CHAR A1 [] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
CHAR A2 [] = {'h', 'I', 'J', 'K', 'L', 'M', 'N'};
in case:
Sprintf (S, "% S% S", A1, A2); // Don't do this!
Ten eight nine must have problems. Can it be modified:
Sprintf (S, "% 7S% 7S", A1, A2);
Nothing, where is it, the right thing should be:
Sprintf (s, "% .77% .7s", A1, a2); // Generate: "Abcdefghijklmn" This can be classified than the "% M.NF" of the number of floating point, in "% m.ns", M Treasing the width (the string length is not enough
The grid is exceeded, then print according to the actual width), and N represents the number of characters from the corresponding string. Usually print word
When the string is m, it is not very large, or it is much used behind the neck. Natural, you can take only some characters before you:
Sprintf (S, "%. 6S% .5s", A1, A2); // Generate: "Abcdefhijkl"
In many cases, we may also hope that the numbers of these format controls to specify length information are dynamic, not
Static specified, because many times, the program will be clear when the program needs to take a few characters in the character number, this
The dynamic width / precision setting function is also taken into account in the implementation of the sprintf, and the sprintf uses "*" to take up one.
The location of the constant number of the specified width or accuracy, the same, and the actual width or accuracy can be one of the other printed variables
The sample is provided, so, the above example can becomes:
Sprintf (s, "%. * s%. * s", 7, A1, 7, A2);
or:
Sprintf (s, "%. * s%. * s", sizeof (A1), A1, SIZEOF (A2), A2);
In fact, the print characters, integers, floating point numbers, etc., which are described earlier, can dynamically specify those constant values, such as:
Sprintf (s, "% - * d", 4, 'a'); // Generate "65"
Sprintf (s, "% # 0 * x", 8, 128); // Generate "0x000080", "#" generated 0x
Sprintf (s, "% *. * f", 10, 2, 3.1415926); // Generate "3.14"
Print address information
Sometimes when you debug a procedure, we may want to view the address of certain variables or members, because the address or pointer is just a 32-bit number, you can print them out with "% u" that prints unsigned integers:
Sprintf (s, "% u", & i);
But usually people still like to use 16 credits rather than 10 credits to display an address:
Sprintf (s, "% 08x", & i);
However, these are indirect methods, for address printing, Sprintf provides special "% P":
Sprintf (s, "% p", & i);
I think it is actually equivalent to:
Sprintf (s, "% 0 * x", 2 * sizeof (void *), & i);
Return value using Sprintf
Someone pays attention to the return value of the PrintF / Sprintf function, but sometimes it is useful, and the spritnf returns this function call.
Finally print the number of characters in the character buffer. That is to say, every time the Sprinf call is over, you don't need to call once.
Strlen already knows the length of the result string. Such as:
INT LEN = Sprintf (S, "% D", i);
For positive integers, LEN is equal to the 10-encyclopedia number of integer i.
The following is a complete example, generates a random number between [0, 100), and print them into a character array S, separated by a comma.
#include
#include
#include
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'; // convert the last comma to a newline character.
PRINTF (S);
Return 0;
}
Imagine When you take a record from the database, I hope to connect their various fields into one word according to some rules.
When string, you can use this method. From theory, he should be higher than the constant STRCAT efficiency because Strcat is called.
You must first find the last '/ 0' position, and in the example given above, we use the sprintf return value each time.
The position is directly recorded.
Frequently Asked Questions using Sprintf
Sprintf is a variable-gate function, often problematic, and as long as the problem is usually, it is usually possible to cause the program crash.
Question mistakes, but it is very easy to find out by the problem of sprintf, but it is easy to find, nothing more than a few cases.
Commonly used your eyes and then look at the wrong code.
?? Buffer overflow
The length of the first parameter is too short, not to say, give a big place. Of course, it may be asking for the back of the parameters.
Question, it is recommended to change the parameters to be careful, and when the string is printed, try to specify the maximum number of characters in the form of "% .ns".
?? Forgot the first parameter
Low levels can no longer be low-level issues, using Printf to use it too used to. // I will do it. :. (
?? Severe ginseng corresponding problem
It is usually forgotten to provide a variety of parameters corresponding to a format, causing the future parameters to dislocation, check check. especially
It is the parameters corresponding to "*", is it? Don't give an integer to a "% s", the compiler will feel you
Bullying she is too even (the compiler is Obj and Exe mother, should be a woman,: p).
Strftime
Sprnitf has a good cousin: Strftime, specifically used to format the time string, usage is very similar to her, also
It is a large stack of format controls, but after all, the little girl is in peace, she also wants to call the maximum length of the buffer, may be
You can shirk your responsibility when you have problems. Here is an example:
Time_t t = time (0);
/ / Generate a string of "YYYY-MM-DD HH: MM: SS" format.
Char s [32];
Strftime (S, SIZEOF (S), "% Y-% M-% D% H:% M:% S", LOCALTIME (& T));
Sprintf can also find his name in the MFC: CString :: Format, StrFTIME naturally also has her work in the MFC:
CTIME :: Format, this pair of sponsorship from the object-oriented object, the code used to write is more elegant.
postscript
All of this article introduced in MSDN can be easily found in the MSDN, the author only uses some examples according to their own experience, uses some common, useful, and may introduce the usage of many beginners. One point, I hope big
Don't jokes, I hope everyone is criticized.
Some people think that this function of this band-ginseng will cause various problems, so it is not advocated. But the author does not resist every time
The temptation of their powerful features is used in actual work. In fact, C # .NET supports parametery from the beginning, just released
Soon Java5.0 also supports parameters.
Thanks Ericzhangali (another space) carefully reviewed the full manuscript, corrected a lot of small mistakes, and put forward some suggestions.
I also thank Laomai (old) to read the full manuscript and gave suggestions for adding some content.