Transfer statement: Selected from the "CSDN Community Electronic magazine--c/c++ Magazine"
When you construct various types of data into strings, the powerful features of sprintf rarely disappoint you. Because sprintf is almost the same as printf in usage, it's just a different destination for printing, which is printed to a string, and the latter is printed directly on the command line. This also causes sprintf to be much more useful than printf.
sprintf is a variable parameter function, defined as follows:
int sprintf (char *buffer, const char *format [, argument] ...);
In addition to the first two parameter types are fixed, any number of parameters can be followed. And it's the essence, apparently on the second parameter:
Format the string.
Both printf and sprintf use a formatted string to specify the format of the string, using some format specifiers that begin with a "%" (formatted specifications) to occupy a position, and to provide the corresponding variable in the list of arguments in the back. The final function replaces the descriptor with the corresponding position variable to produce a string that the caller wants.
To format a string of numbers
One of the most common applications of sprintf is to print integers to a string, so spritnf can be substituted in most cases
Itoa.
Such as:
Print the integer 123 into a string and save it in S.
sprintf (S, "%d", 123); Produce "123"
You can specify the width, insufficient left fill space:
sprintf (S, "%8d%8d", 123, 4567); Generated: "123 4567"
Of course, you can also align Left:
sprintf (S, "%-8d%8d", 123, 4567); Generated: "123 4567"
You can also print in 16:
sprintf (S, "%8x", 4567); lowercase 16, width to 8 positions, right aligned
sprintf (S, "%-8x", 4568); Uppercase 16, width to 8 positions, left-aligned
In this way, a 16 string of integers is easy to get, but when we print the 16 feed, we usually want an equal-width format with a left complement of 0. Simply put a 0 in front of the number that represents the width.
sprintf (S, "%08x", 4567); Produce: "000011d7"
The 10-in-print printing above with "%d" can also use this left complement of 0.
Notice the problem of a symbolic extension: for example, if we want to print the memory 16 binary representation of a short integer, 1, on the Win32 platform, a shorter type occupies 2 bytes, so we naturally want to print it in 4 16 digits:
Short si =-1;
sprintf (S, "%04x", si);
Produce "ffffffff", what's going on. Because SPRITNF is a variable parameter function, in addition to the preceding two parameters, after the parameters are not type-safe, the function is not only through a "%x" to know the original function call before the pressure stack is a 4-byte integer or a 2-byte short integer, so take a unified 4 byte processing, resulting in the parameter stack when the symbolic extension, expanded into a 32-bit integer-1, printing when 4 position is not enough, the 32-bit integer-1 8-bit 16 into the system are printed.
If you want to see the true nature of SI, then you should let the compiler do 0 extensions instead of symbolic extensions (when extending the binary left complement 0 instead of the complement symbol bit):
sprintf (S, "%04x", (unsigned short) SI);
It's OK. Or:
unsigned short si =-1;
sprintf (S, "%04x", si);
sprintf and printf can also print an integer string in 8, using "%o". Note that 8 and 16 are not going to hit.
A negative number is an unsigned, in fact, a direct 16-or 8-binary representation of the internal encoding of the variable.
Control floating-point printing format
The printing and formatting control of floating point numbers is another common function of sprintf, floating point numbers use the format character "%f" control, default security
Leave 6 digits after the decimal point, such as:
sprintf (S, "%f", 3.1415926); Produce "3.141593"
But sometimes we want to control the width and scale of the print, and then we should use: "%M.NF" format, where M table
Shows the width of the print, and n indicates the number of digits after the decimal point. Like what:
sprintf (S, "%10.3f", 3.1415626); Produced: "3.142"
sprintf (S, "%-10.3f", 3.1415626); Produced: "3.142"
sprintf (S, "%.3f", 3.1415626); Do not specify the total width, resulting in: "3.142"
Pay attention to a question, you guess.
int i = 100;
sprintf (S, "%.2f", I);
What you're going to do. "100.00". Is that right. Try it yourself, and try the following:
sprintf (S, "%.2f", (double) i);
The first one is definitely not the right result, as mentioned earlier, the caller does not know that the format controller corresponding to I is a "%f" when the parameter is pressed. The function is not aware of the execution of the stack in the year was a whole number, so the poor save integer I of the 4 bytes was use robust reporting forced as a floating-point format to explain the whole mess. However, if someone is interested in using a floating-point number to encode manually, you can use this method to verify that the results you have manually choreographed are correct.
Character/ascii Code Control
We know that in C/s + + languages, char is also a common type of scalable, except for word length, which is associated with short,
Int,long These types are not fundamentally different, but are used to represent characters and strings. (Perhaps it was time to
This type is called "byte" and can now be used in terms of byte or short to define char through TypeDef, so it's more appropriate to print a character with "%d" or "%x" so that it can get its 10 or 16 ASCII code. Instead, print an integer using '%c ' to see the ASCII characters it corresponds to. The following section prints the ASCII-code table of all visible characters to the screen (printf here), noting that "#" when combined with "%x" automatically adds a "0X" prefix for the 16 number:
for (int i = i < 127; i++) {
printf ("[%c]:%3d 0x% #04X/n", I, I, I);
}
Connection String
sprintf's format control string can be inserted into a variety of things, and eventually "connected to a string", nature will be able to even
String, which can replace Strcat on many occasions, but sprintf can connect multiple strings at once (naturally
Insert something else in between them, which is very flexible anyway. Like what:
char* who = "I";
char* whom = "CSDN";
sprintf (S, '%s love%s ', who, whom); Produce: "I love CSDN." "
Strcat can only connect strings (an array of characters at the end of a paragraph or called character Buffering, null-terminated-string), but sometimes we have two-character buffers, and they don't end with '. For example, many character arrays that are returned from Third-party library functions, which are read in the form of hardware or network transmissions, do not necessarily have a corresponding ' end ' after each sequence of characters. If the direct connection, whether sprintf or strcat will certainly lead to illegal memory operations, and strncat at least requires the first parameter is a null-terminated-string, then what to do? We will naturally recall the previous description you can specify the width when printing integers and floating-point numbers, as well as strings. Like what:
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!
There's a nine-to-ten problem. Can be changed to:
sprintf (S, "%7s%7s", a1, A2);
is not good to go, the right should be:
sprintf (S, "%.7s%.7s", a1, A2);//produce: "ABCDEFGHIJKLMN"
This can be compared to the "%m.nf" of the printed floating-point number, and in "%m.ns", m indicates the width (the length of the string is insufficient to fill the space, and then the actual width is printed), and N represents the most characters taken from the corresponding string. Usually when the string is printed, M is not much use, or the number of n after the dot is used more. Naturally, you can also take only a subset of the characters before and after:
sprintf (S, "%.6s%.5s", a1, A2);//produce: "ABCDEFHIJKL"
In many cases, we may also want the numbers in these format controllers to specify the length information to be dynamic rather than statically specified, because many times the program will not know exactly what characters to take in a character array until it is run, and this dynamic width/precision setting functions in sprintf Implementations are also taken into account, sprintf uses "*" to occupy a position where a constant number that would otherwise require a specified width or precision, and the actual width or precision can be supplied as other printed variables, so the example above can be:
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, floating-point numbers, and so on are all dynamically assigned to those constant values, such as:
sprintf (S, "%-*d", 4, ' A '); Produce "65"
sprintf (S, "% #0 *x", 8, 128); Produces "0x000080", "#" produces 0X
sprintf (S, "%*.*f", 10, 2, 3.1415926); Produce "3.14"
Print address information
Sometimes when debugging a program, we might want to look at the address of some variable or member, because the address or pointer is just a 32-digit number, you can print them out using "%u" that prints unsigned integers:
sprintf (S, "%u", &i);
But usually people prefer to use 16 instead of 10 to display an address:
sprintf (S, "%08x", &i);
However, these are indirect methods, for address printing, SPRINTF provides a dedicated "%p":
sprintf (S, "%p", &i);
I think it's actually equivalent to:
sprintf (S, "%0*x", 2 * sizeof (void *), &i);
Using the return value of sprintf
Less attention is paid to the return value of the printf/sprintf function, but sometimes it is useful, SPRITNF returns the function call
The number of characters that are eventually printed into the character buffer. That is, you don't need to call again once the Sprinf call is over
Strlen already knew the length of the result string. Such as:
int len = sprintf (S, "%d", I);
For a positive integer, Len equals the 10-digit number of the integer i.
The following is a complete example that generates random numbers between 10 [0, 100) and prints them into a character array s,
separated by commas.
#include
#include
#include
int main () {
Srand (Time (0));
Char s[64];
int offset = 0;
for (int i = 0; i < i++) {
Offset + = sprintf (s + offset, "%d,", rand ()% 100);
}
S[OFFSET-1] = '/n ';//The last comma is replaced by a newline character.
printf (s);
return 0;
}
Imagine when you take a record out of a database, and then want to connect their fields to a single word in some sort of rule.
String, you can use this method theoretically, he should be more efficient than the constant strcat, because strcat each call
All need to find the last "' position, and in the example given above, each time we use the sprintf return value to
A place to write it down directly.
Frequently asked questions about using sprintf
sprintf is a variable parameter function that often goes wrong when used, and as long as the problem is usually a memory visit that can cause the program to crash
Ask the wrong, but fortunately by sprintf misuse caused by the problem, although serious, but very easy to find, nothing but a few cases, pass
Common eyes and then the wrong code to look at a few more eyes to see it.
1 buffer Overflow
The length of the first parameter is too short to say, give it a bigger spot. Of course also may be the back of the argument to ask
, we suggest that the argument should be careful, and when printing a string, try to use the form "%.NS" to specify the maximum number of characters.
2 forgot the first parameter
The low-level can no longer be a low-level problem, used to use printf too accustomed. I often commit. :。 (
3 variable parameter corresponding problem
Usually forget to provide a corresponding format of the variable parameter, resulting in all the wrong parameters, check and check it. Especially
It is the corresponding "*" of those parameters, are provided. Instead of an integer corresponding to a "%s", the compiler will think that you
Bullying her too far (compiler is obj and exe mother, should be a woman,:P).
Strftime
SPRNITF also has a nice cousin: Strftime, which is used to format time strings, is similar to her cousin, and
is a lot of format control characters, just small roomed forestall, she also wants the caller to specify the maximum length of the buffer, possibly for
You can shirk responsibility when a problem arises. Here's an example:
time_t t = time (0);
A string that produces the format "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 his bosom friend in MFC: Cstring::format,strftime in MFC naturally also has her fellow:
Ctime::format, this pair because from object-oriented where get sponsorship, write code is more graceful.