Sprintf, how much do you know?

xiaoxiao2021-03-05  25

Selected from "9CBS community e-magazine --C / C magazine" http://emag.9cbs.net January 2005, a total of --93-- author: steedhorse (Morningstar) printf may be the start of many programmers to learn The second function that came into contact with the C language (I guess the first is main), saying, naturally the old friend, but have you learned how much to this old friend? Do you know how much your 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, then output on the command line. This also causes sprintf to be much useful than Printf. So this paper focuses on Sprintf, sometimes inserting 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: format strings. Both PRINTF and SPRINTF use formatted strings to specify the format of the string, and use some format spectrial specifence (Format Specifications) at the beginning of the format string to provide corresponding variables in the backward parameters of the rear. The final function will replace the specifier in the variable of the corresponding position, generate a buffer you want. One of the most common applications that format digital string sprintf is to print integers into the string, so spritnf can replace ITOA in most cases. If you print an integer 123 into a string saved in S. Sprintf (s, "% d", 123); // Generate "123" to specify the width, insufficient left resilience: Sprintf (S, "% 8D% 8D", 123, 4567); // Generate: "123 4567 "Of course, you can also align: Sprintf (S,"% -8d% 8D ", 123, 4567); // Generate:" 123 4567 "can also be printed in 16 credits: Sprintf (s,"% 8x ", 4567); / / lowercase 16 yuan, the width accounts for 8 positions, right aligned Sprintf (s, "% -8x", 4568); // uppercase 16-based, width accounts for 8 positions, left alignment

In this way, an integer's 16-enrich string is easy, but when we print 16 credit content, we usually want to have an equivalent format of the left to supplement 0. What should I do? Very simple, add 0 in front of the number indicating the width. Sprintf (s, "% 08x", 4567); // Generate: "000011D7" 10-based printing in "% D" is also used to use this way to supplement 0. Here, you should pay attention to a symbol extension problem: For example, if we want to print a short integer (short) -1 memory 16 credit representation, on the Win32 platform, a short type occupies 2 bytes, so we naturally hope to use 4 A 16-way number to print it: short si = -1; Sprintf (s, "% 04x", si); generate "ffffffffff", what is going on? Because spritnf is a variable-gate function, in addition to the two parameters, the back parameters are not type security, and the function can not know how only one "% X" can know when the first function call before the parameter stack is pressed. In the end, it is a 4-byte integer or a short integer of 2 bytes. Therefore, the unified 4-byte processing method is taken, causing the parameter stack to make a symbol extension, expanded to 32-bit integers -1, printing 4 positions are not enough, print 32-bit integers -1 8-bit bits. If you want to see the original face of Si, you should let the compiler do 0 expansions rather than symbol extensions (扩 二 二 左 0 0): Sprintf (S, "% 04x", (unsigned short) Si ); Or: unsigned short si = -1; sprintf (s, "% 04x", si); sprintf and printf can also press 8-based printing a nutrient string, using "% O". Note that 8 binders and 16 are not printing negative numbers, which are not symbol, which is actually the direct 16-coded or 8 binary representation of the internal encoding of the variable. Controlling the print and format control of floating point print format floating point number is another common function of sprintf, floating point number uses format "% F" control, the default retains 6 digits after the 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 the decimal number, then use: "% m.nf" format, where m represents the width of the print, n represents the decimal point Bit number.

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); // Do not specify the total width, generate:" 3.142 "pay attention to a problem, you guess I = 100; Sprintf (s,"% .2f ", i); what will play? "100.00"? right? I will try it yourself, try the following: Sprintf (s, "% .2f", (double) i); the first one is definitely not the correct result, the reason is the same as mentioned above, parameters When the stack is stack, the caller does not know that the format control with I is a "% f". When the function execution function itself doesn't know that the integer is being pressed into the stack, the four bytes of poor storage integer i are unsolicited as a floating point number format, the whole chaos. However, if someone is interested in using a floating point number, you can use this method to verify that your hand-arranged results are correct. Character / ASCII code controls We know that in the C / C language, Char is also a normal Scalable type, except for the word length, it is not essentially different from Short, int, long, but is used to it. To represent characters and strings. (Perhaps this type is called "byte", and then it can now use Byte or short to define the CHAR through TypeDef according to the actual situation, so more appropriately), using "% D" or "% x" printing A character can derive its 10 credit or 16-based ASCII code; in turn, use "% C" to print an integer, you can see the ASCII characters it corresponds to. The following block prints all visible characters' ASCII code comparison table to the screen (here the Printf, 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);} Connection string Sprintf's format control string can be inserted into various things And eventually "connect into a string", naturally it can connect to the string, so that many occasions can be replaced in Strcat, but the sprintf can connect multiple strings at a time (naturally insert other content in them in them, in short, Very flexible). For example: char * WHO = "i"; char * whom = "9cbs"; sprintf (s, "% s love% s.", WHO, WHOM); // generation: "i love 9cbs." Strcat can only connect String (a character array at the end of '/ 0' or Null-Terminated-string), but sometimes we have two character buffers, they are not ending with '/ 0'. For example, many characters from the third-party library function, read from hardware or network transfers, they do not have a corresponding '/ 0' after each sequence of characters.

If you connect directly, no matter whether sprintf or Strcat will definitely lead to illegal memory operation, and Strncat requires at least the first parameter is a null-terminated-string, what should I do? We naturally think of the previous introduction to print integers and floating point numbers, you can specify the width, 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 this! Ten Eight nine wants to have problems. Whether it can be changed: Sprintf (S, "% 7S% 7S", A1, A2); not yet, correct: sprintf (s, "% .7777", A1, A2) ; // Generate: "Abcdefghijklmn" This can be classified than the "% m.nf" of the printed floating point, in "% m.ns", M represents the occupation width (the string length is insufficient, and the space is exceeded, according to the actual width Print), N represents the number of characters you take from the corresponding string. Usually m is not very large when the string is printed, or there is more than the nodes.

Natural, you can use only some characters before you: Sprintf (S, "%. 6S% .5s", A1, A2); // Generate: "Abcdefhijkl" In many cases, we may also want these format controls. The number of the specified length information is dynamic, not static specified, because many times, the program will be clear when the program needs to take several characters in the character array, this dynamic width / precision setting function in Sprintf The implementation is also taken into account, and the sprintf uses "*" to occupy a position where a constant number of a specified width or accuracy is, and the actual width or accuracy can be provided as other than other variables, Thus, 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 printed 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", "#" generates 0xsPrintf (s, "% *. * f ", 10, 2, 3.1415926); // Generate" 3.14 "print address information Sometimes when we want to view some variables or members of the member, because the address or pointer is not a 32-bit number, you are complete You can print them out using "% u" that print unsigned integers: Sprintf (s, "% u", & i); how often people still like to use 16-based rather than 10 envelopes: Sprintf (s , "% 08X", & i); however, these are indirect methods, for address printing, Sprintf provides special "% P": sprintf (s, "% p", & i); I think it actually Equivalent to: sprintf (s, "% 0 * x", 2 * sizeof (void *), & i); less people with Sprintf pay less attention to the return value of the PrintF / Sprintf function, but sometimes it is useful, Spritnf returns the number of characters in this function call finally printed into the character buffer. That is to say, every time the Sprinf call is over, you have no need to call a Strlen that has already known the length of the result string. Such as: int Len = Sprintf (s, "% d", i); for positive integers, LEN is equal to the 10-en-bits 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'; // Put the last comma Change to a newline. Printf (s); Return 0;} Item Vision When you take a record from the database, you can use this method when you connect their various fields into a string, in theory, he It should be higher than the constant STRCAT efficiency, because Strcat needs to find the last '/ 0' position, and in the example given above, we use the sprintf return value to record this location. . The common problem using sprintf is a variable gate function. It is often problematic when used, and as long as the problem is usually possible, it is usually possible to cause the program crash, but it is very serious, it is easy to find out the problem caused by the Sprintf. It is nothing more than a few situations, usually use the eyes to look at the wrong code. ?? The length of the buffer overflows the first parameter is too short, no, give a big place. Of course, it may also be the problem of the back parameters. 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 level can not be low-level issues, use Printf to use it too used to. // I will do it. :. (?? The change of the parametric corresponds to the problem is usually forgotten to provide a variety of parameters that correspond to a format, causing the future parameters to dislocation, check the check. Especially those parameters corresponding to "*", don't put An integer corresponds to a "% s", the compiler will think that you bully it too much (the compiler is OBJ and EXE mother, it should be a woman,: p). StrfTimeSprnitf still has a good cousin: strftime, specifically used The formatted time string, the usage is very similar to her, and it is also a lot of format control, but after all, the little girl is inserted. She also wants to call the maximum length of the buffer, which may be in order to appear Shift responsibility. Here, 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 voice in the MFC: cstring :: format, StrFTIME naturally has her in MFC The same way: ctime :: Format, this pair of sponsored from the object-oriented object, the code used to write more elegant. After all of these features introduced in this article, you can easily find it in MSDN, the author Just based on your own experience, combined some examples, put some common, useful, and may introduce the usage of many beginners, I hope everyone should not joke, and I hope everyone criticizes. Some people think this band change The function of the paragraph will cause various problems and is therefore not advocated.

转载请注明原文地址:https://www.9cbs.com/read-38722.html

New Post(0)