Detailed description of C ++ string formatting sprintf

Source: Internet
Author: User
Tags 04x control characters

When constructing various types of data into strings, the powerful features of sprintf seldom disappoint you. Since sprintf and printf have almost the same usage, but the printing destination is different, the former is printed into the string, and the latter is directly output on the command line. This also makes sprintf much more useful than printf.

Sprintf is a variable parameter function, which is defined as follows:
Int sprintf (char * buffer, const char * Format [, argument]...); in addition to the first two parameter types, you can take over multiple parameters later. Its essence is obviously on the second parameter: Format String.

Both printf and sprintf use formatted strings to specify the string format. Some format specifiers (format specifications) starting with "%" are used inside the format string to occupy a position, the variable is provided in the variable parameter list, and the function will replace the specifier with the variable at the corresponding position to generate the string that the caller wants.

1. Format a numeric string

One of the most common applications of sprintf is to print Integers to strings. Therefore, spritnf can replace ITOA in most cases. 

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, left fill space:
Sprintf (S, "% 8d % 8d", 123,456 7); // generate: "123 4567", of course, it can be left aligned:
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, a hexadecimal string of an integer can be easily obtained, but when we print hexadecimal content, we usually want an equal-width format with 0 on the left. How can we do this? Simply add 0 to the number that represents the width.
sprintf (S, "% 08x", 4567); // generate: "201711d7"
the above 10-digit printing with" % d "can also use this left-side fill 0 method.


pay attention to a symbol extension problem: for example, if we want to print the short INTEGER (short)-1 memory hexadecimal representation, on the Win32 platform, A short type occupies 2 bytes, So we naturally want to print it with 4 hexadecimal numbers:
short Si =-1;
sprintf (S," % 04x ", Si);
production" ffffffff ", what's going on? Because spritnf is a Variable Parameter Function, except the first two parameters, the following parameters are not of type security, there is no way for a function to know whether a 4-byte integer or a 2-byte short integer is pressed in the parameter stack before the function call through a "% x "., therefore, a 4-byte processing method is adopted, which leads to the symbol extension during parameter pressure stack, which is a 32-bit integer-1. When printing, the four locations are insufficient, print out the 8-bit 16 hexadecimal values of 32-bit integer-1.

If you want to see the original form of Si, you should let the compiler do 0 extension instead of symbol extension (during expansion, the left side of the binary complement 0 instead of the 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 format, 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.

Ii. Control the floating point printing format

printing and format control of floating point numbers is another common function of sprintf. Floating Point Numbers are controlled by the format character" % F ". The default value is
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, we should use: "% m. NF "format, where M Table
shows 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. As mentioned above, the caller does not know that the format controller corresponding to I is "% F ". During function execution, the function itself does not know that the number of integers pushed into the stack in the 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 whether the result of manual editing is correct.

3. Character/ASCII code comparison

We know that in C/C ++, char is also a common scalable type. In addition to the word length, it has no essential difference with short, Int, and long, it is used to represent characters and strings. (Maybe this type is called "Byte" in the past, and now we can use byte or short to define char through typedef according to the actual situation, which is more appropriate, print a character using "% d" or "% x" to obtain its 10-or 16-digit ASCII code. Conversely, print an integer using "% C" to see its ASCII characters. BelowProgramTo print the ASCII code table of all visible characters to the screen (printf is used here, note: "#" and "% x" are automatically prefixed with "0x" in hexadecimal notation ):
For (INT I = 32; I <127; I ++ ){
Printf ("[% C]: % 3d 0x % # 04x \ n", I, I );

Iv. connection string

Since the sprintf format control strings can insert various things and finally "connect them into a string", it can naturally connect strings, which can replace strcat in many occasions, but sprintf can connect multiple strings at a time (it can also insert other content in them at the same time, in short, it is very flexible ). 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 ''or a character buffer, null-terminated-string), but sometimes we have two character buffers, they do not end. For example, for many character arrays returned from third-party library functions and the sequence streams read from hardware or network transmission, they may not end with a corresponding ''after each character sequence. If you connect directly, whether sprintf or strcat will certainly lead to illegal memory operations, and strncat also requires at least the first parameter to be null-terminated-string. What should we do? We naturally remember that the width can be specified when we first introduced printing integers and floating-point numbers, and the strings are 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 ", in" % m. in NS, M indicates the width occupied (when the length of the string is insufficient, fill in space. If the length exceeds the limit, print according to the actual width). N indicates the maximum number of characters used from the corresponding string. Generally, M is useless when printing strings, but n is usually 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 than static, because many times, when the program is running, it will know exactly how many characters in the character array need to be taken. This dynamic width/precision setting function is also taken into account in the implementation of sprintf, sprintf uses "*" to occupy a position that originally requires a constant number with a specified width or accuracy. Similarly, the actual width or accuracy can be provided like other printed variables, 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"

5. Print the 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 by printing the unsigned integer "% 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 number of characters that the function call finally prints to the character buffer. That is to say, after each sprinf call ends, you do not need to call strlen again to know the length of the result string. For example: int Len = sprintf (S, "% d", I); for a positive integer, Len is equal to the 10th digit of the integer I. The following is a complete example, which generates a random number between 10 [0,100) and prints them into an array of characters (s) separated by commas.
# 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'; // 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 string according to certain rules, you can use this method. Theoretically, it should be more efficient than the continuous strcat, because each call to strcat needs to first find the final location, and in the example given above, every time we use the sprintf return value to write down this position directly.

Vi. FAQs 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 a memory access error that can cause the program to crash, but fortunately the problems caused by sprintf misuse are serious, but it is easy to find out. It is nothing more than the following situations.CodeYou can see it with a few more eyes.

 

  1. 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 a problem with the following parameters. We recommend that you be careful with the corresponding parameters. When printing a string, try to use the "%. Ns" format to specify the maximum number of characters.
  2. I forget that the first parameter is too low-level to avoid low-level issues. I am too familiar with printf. // It is common.
  3. 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. Are all parameters corresponding to "*" provided? Do not map an integer to a "% s". The compiler will think that you are deceiving her too much (the compiler is the mother of OBJ and exe, which should be a female: P ).
VII. Others

Strftime
Sprnitf also has a good cousin: strftime, which is specially used to format the time string. Its usage is very similar to that of her cousin. It is also a lot of format control characters, but after all, the girl's family is fine, she also needs the caller to specify the maximum length of the buffer, probably to shirk responsibility in case of problems. 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 ));

Select from csdnCommunityElectronic Magazine-C/C ++ magazine

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.