Sprintf usage
Printf may be the second function that many programmers encounter when learning C language (I guess the first function is main ),
Naturally, it's 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, the powerful features of sprintf seldom disappoint you.
Since sprintf and printf are almost the same in usage, but the printing destination is different, the former is printed to the string,
The latter is output directly on the command line. This also makes sprintf much more useful than printf. So this article focuses on sprintf, sometimes
It is also interspersed with pritnf.
Sprintf is a variable parameter function, which is defined as follows:
Int sprintf (char * buffer, const char * Format [, argument]...);
In addition to the fixed types of the first two parameters, you can take over multiple parameters later. But its essence is obviously in the second parameter:
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 be replaced in most cases.
ITOA. For example:
// Print the integer 123 into a string and save it in S.
Sprintf (S, "% d", 123); // generate "123"
You can specify the width. If the width is insufficient, spaces are filled on the left:
Sprintf (S, "% 8d % 8d", 123,456 7); // generate: "123 4567"
Of course, you can also align left:
Sprintf (S, "%-8d % 8d", 123,456 7); // generate: "123 4567"
You can also print the data 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 easy to obtain, 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? Simply add 0 to the number that represents the width.
Sprintf (S, "% 08x", 4567); // generate: "201711d7"
You can also use this left-side 0 Complement Method to print the 10-in-hexadecimal format with "% d" above.
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? Because spritnf is a variable parameter function, in addition to the first two parameters
The parameters are not of type security, and the function cannot simply use "% x" to know that the parameter pressure stack before the function is called.
Is it a 4-byte integer or a 2-byte short integer, so a unified 4-byte processing method is adopted,
As a result, the parameter is expanded to a 32-bit integer-1 when the stack is pressed. If the four locations 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 common function of sprintf. Floating Point Numbers are controlled by the format character "% F", which is guaranteed by default.
Keep the six 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", where 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? Try it on your own and try the following:
Sprintf (S, "%. 2f", (double) I );
The first one is definitely not the correct result. The reason is as mentioned above. When the parameter is pressed to the stack, 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 check 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, but they are used to representing characters and strings. (Maybe we should
This type is called "byte", and now we can use byte or short to set char through typedef according to the actual situation.
)
Therefore, print a character using "% d" or "% x" to obtain its 10-or 16-digit ASCII code.
To print an integer using "% C", you can see its ASCII characters. The following section describes
The ASCII code table is printed on the screen (printf is used here. Note that "#" and "% x" are automatically used to 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 a variety of things, and finally "connect them into a string", it will naturally be able to connect
Concatenates strings to replace strcat in many cases, but sprintf can connect multiple strings at a time (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, the number of characters returned by many 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. If you connect directly, whether sprintf or strcat will certainly lead to illegal memory operations, and strncat also requires at least
A parameter is null-terminated-string. What should I do? We naturally remember the previous sections on printing integers and floating-point numbers.
You can specify the width, 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 '};
If:
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, you 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 statically specified, because in many cases, it is only necessary for the program to obtain several characters in the character array at runtime.
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. Similarly, the actual width or accuracy can be the same as that of other printed variables.
The sample is provided, so the preceding example 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, such:
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 the unsigned integers "% u:
Sprintf (S, "% u", & I );
However, people usually 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 useful. spritnf returns the function call.
The number of characters that are 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.
# I nclude
# I nclude
# I nclude
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 constant strcat because strcat calls
We need to first find the last '\ 0' position, and in the above example, we use the sprintf return value every time to write down this position directly.
FAQ about using sprintf
Sprintf is a variable parameter function, which often causes problems when used, and as long as there is a problem, it is usually the memory access that can cause the program to crash.
Wrong, but fortunately, the problems caused by the misuse of sprintf are serious, but it is easy to find out, there are only a few situations
The common eyes can see the error code with a few more eyes.
?? Buffer Overflow
The length of the first parameter is too short. If you don't want to say it, just give it a bigger one. Of course, it may also be the following parameter question.
It is recommended that you be careful when changing parameters. When printing a string, use the "%. Ns" format to specify the maximum number of characters.
?? The first parameter is missing.
Low-level users cannot have low-level problems. They are too familiar with printf. // It is common. :. (
?? An error occurred while changing the parameter.
Generally, you forget to provide variable parameters corresponding to a certain format character, which leads to misplacement of all subsequent parameters. Check the parameters. You
Are all parameters corresponding to "*" provided? Do not map 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. Its usage is similar to that of her cousin.
It is a lot of format controllers, but after all, the girl's family is fine, and she also needs to specify the maximum length of the buffer, which may be
You can shirk responsibility when a problem occurs. 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 just use them based on my own experience,
In combination with some examples, we will introduce some commonly used and useful things that many beginners may not know about. I hope you will not laugh at them, and I hope you will criticize and correct them.
Some people think that this function with variable parameters will cause various problems and therefore 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 variable parameters from the very beginning.
Later, java5.0 also supported variable parameters.