Introduction to sprintf usage

Source: Internet
Author: User
Tags 04x print format

 

Introduction to sprintf usage

From csdn Community Electronic Magazine-C/C ++ magazine

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 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 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.

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 printing the hexadecimal content, we usually want an equal-width format with 0 on the left, what should we do? 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 a 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 );
Why is "ffffffff" generated? 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, 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"

 
 
 

 

Sprintf (S, "%. 2f", (double) I );
The first one is definitely not the correct result, because, as mentioned above, the caller does not know that the format controller corresponding to I is "% F" when the parameter is pressed ". 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 whether the result of your manual arrangement is 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". 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. The following section prints the ASCII code table of all visible characters to the screen (printf is used here, note that "#" 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 );
}

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 ''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 string length is insufficient, fill in spaces. If the length exceeds the limit, print it 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"

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.
# 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 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
You must first find the last ''position, and in the above example, we use sprintf to return
Position.

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.

--------------------------------------

 

 

 

 

Sprintf in C language is better than printf. printf directly prints the content to the screen, while sprintf prints the content to the array. The format is as follows:

Sprintf (char * STR, const char * format ,...)

I think it is quite useful, but it is quite difficult to understand it after I write the code. Below is the test code I wrote (running environment vc6.0)

Test code:

# Include <stdio. h>

Int main ()
{
Char buffer [1];
Sprintf (buffer, "% d", 1234 );
Puts (buffer );
Printf ("% s", "hello ");
Return 0;
}

This code can be compiled normally, run properly, and the running results are completely correct, but the code is slightly modified. Although the running results can be obtained, however, a memory error occurs when the program exits. The modified code is as follows (change sprintf (buffer, "% d", 1234) to sprintf (buffer, "% d", 12345)

Test code B:

# Include <stdio. h>

Int main ()
{
Char buffer [1];
Sprintf (buffer, "% d", 12345 );
Puts (buffer );
Printf ("% s", "hello ");
Return 0;
}

Why is there such a result. I thought the test code A should be wrong, but there is no error. Because the sprintf (buffer, "% d", 1234) in Test code A stores four char s in the buffer, while the buffer applies only one char in the stack, so I think it is necessary to overflow, but the results are somewhat unexpected.

Since test code A can run normally, test code B should be correct, but the running result is unexpected.

I checked the information online, discussed it with people, and understood some reasons after reading the VxWorks memory management:

1. The default value of VC is 4 bytes alignment, which explains why test code A runs normally.

2. During the function call process, the function parameters are first pushed to the stack, and then the address to be returned after the function call is completed is pushed to the stack. During the function call process, some local variables will also be pushed into the stack. This also explains why the test code B went wrong. Because char buffer [1] is 4 bytes aligned by default in VC, the actual application is Char buffer [4], so when we put "12345" into buffer, the address to be returned after the function in the stack is called is overwritten, so an error occurs when the program runs and exits.

 

 

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.