Sscanf and sprintf () Functions

Source: Internet
Author: User
Tags 04x print format

 

Sprintf () Instructions for use

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"

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

Sscanf () function usage

Define the function int sscanf (const char * str, const char * format ,........);

Function Description

Sscanf () converts and formats the str string based on the format string. For more information about format conversion, see scanf (). The converted result is stored in the corresponding parameter.

 

If the return value is successful, the number of parameters is returned. If the return value fails,-1 is returned. The error cause is stored in errno. If the return value is 0, the operation fails. Otherwise, the number of correctly formatted data is displayed, for example, sscanf (str, "% d % s", & I, & i2, & s ); if the three data entries are successfully read, 3 is returned. If the first integer is read-only to I, 1 is returned. The second integer cannot be read from str.

Example # include

Main ()

{

Int I;

Unsigned int j;

Char input [] = "10 0x1b aaaaaaaa bbbbbbbb ";

Char s [5];

Sscanf (input, "% d % x % 5 [a-z] % * s % f", & I, & j, s, s );

Printf ("% d % s", I, j, s );

}

Run 10 27 aaaaa

 

The content in sscanf (stringBuf. c_str (), "% 20 [^ #] # % 20 [^]",...) Statement "" means:

"% [

] Is used to declare a string, which is more specific than "% s" and can be used to set the read style. For example, "% [a-z]" only reads lower-case letters and ends when other characters are read. Note: If the square brackets contain "^", it indicates that a character has been read. For example:

 

"% [^ #]": Reads the string until "#" is displayed.

"% 20 [^ #]": reads a string of 20 bytes and ends when "#" is displayed.

Therefore, the meaning of "% 20 [^ #] # % 20 [^]" is,

Read two 20-byte strings. The first string can end with #, and the second string can end with a carriage return.

For more information, see the "scanf Type Field Characters" section and "scanf Width

Specification "section.

**************************************** **************************************** **************************************** *********************

As we all know, sscanf is a very useful function that can be used to retrieve integers, floating-point numbers, and strings from strings. It is easy to use, especially for integers and floating-point numbers. However, beginners may not know some advanced usage when processing strings. Here is a brief description.

1. Common usage.

The following is a reference clip:

Charstr [512] = {0 };

Sscanf ("123456", "% s", str );

Printf ("str = % s

", Str );

2. Take a string of the specified length. In the following example, a string with a maximum length of 4 bytes is obtained.

The following is a reference clip:

Sscanf ("123456", "% 4 s", str );

Printf ("str = % s

", Str );

3. Obtain the string of the specified character. For example, in the following example, the string is obtained when a space is encountered.

The following is a reference clip:

Sscanf ("123456 abcdedf", "% [^]", str );

Printf ("str = % s

", Str );

4. Take a string that only contains the specified character set. For example, in the following example, take a string that only contains 1 to 9 letters and lowercase letters.

The following is a reference clip:

Sscanf ("123456 abcdedfBCDEF", "% [1-9a-z]", str );

Printf ("str = % s

", Str );

5. Obtain the string of the specified character set. For example, in the following example, a string with uppercase letters is used.

The following is a reference clip:

Sscanf ("123456 abcdedfBCDEF", "% [^A-Z]", str );

Printf ("str = % s", str );

**************************************** **************************************** **************************************** *********************

Name: sscanf ()-read data that matches the specified format from a string.

 

Syntax: int sscanf (string str, string fmt, mixed var1, mixed var2 ...);

Integer sscanf (string str, string fmt, mixed var1, mixed var2 ...);

Usage: interpret the str string in the specified format fmt. in fmt, except % d and % s, other strings can also be included as the format. each % d or % s corresponds to a parameter, in the order of var1, var2... % d reads an integer into the parameter, while % s reads a string. * It can also be used in the format. (% * d and % * s) with an asterisk (*) indicates skipping this data and not reading it. (that is, do not read this data into the parameter) although the sscanf () of LPC is similar to the sscanf () of C, there are still differences. the sscanf () of the LPC does not need or cannot provide the memory address of the variable to sscanf (), but only needs to give the variable name. another difference is that the sscanf () of LPC has the syntax for: sscanf (str, "% s", str1, str2, the first English word (that is, the content before the first blank character) in str will be read into str1, and the remaining content will be read into str2.

Sscanf () returns % d and % s in the correct format.

I have written such a small program before: a text file, each line is a record, each record contains multiple fields, each field is separated by a certain delimiter, for example:

Notebook, IBM, ThinkPad X32, 6,12000

 

(Each field is separated by commas (,). The content is the item name, manufacturer, model, quantity, and price)

If you want to process such a row of records and extract fields, how can this be better?

My previous practice was to use the strtok function in a loop to retrieve a field and save the content to a string array. Although this is feasible, I always feel that the code I wrote is a bit cool.

Recently, I saw a piece of code, using the standard library function sscanf of C to process such data, just one line is needed. I sorted out the code and removed the irrelevant part. The core part is as follows:

Float price;

 

Int quantity;

 

Char category [21], name [21];

 

Char vendor [21], sku [21];

 

Char buf [201];

Fp = fopen (filename, "r ");

 

Fgets (buf, 200, fp );

 

Sscanf (buf,

 

"% 20 [^ #] # % 20 [^ #] # % f # % I # % 20 [^ #] # % 20 [^/n]",

 

Name, sku, & price, & quantity, category, vendor );

The following is a simple explanation:

% 20 [^ #] # Read a maximum of 20 characters until a timestamp # is met, but does not contain a timestamp

 

% F # Read a floating point number until it meets the delimiter #

 

% I # Read an integer until it meets the delimiter #

 

% 20 [^/n] can contain a maximum of 20 characters, ignoring the carriage return at the end of a line

Is it concise and clear?

# Include <stdio. h>

 

Int main ()

 

{

 

Char log [] = "<14> 2002-11-11 12:12:12 11.22.33.44 3 3 aaaa aaaaaa ";

 

// Char log [] = "<1> 2002-11-11 12:12:12 11.22.33.44 3 aaaa aaaaaa ";

 

Char test [] = "<1111> 22 ";

 

Char log2 [200];

Char str1 [20];

 

Char str2 [20];

 

Char str3 [20];

 

Char str4 [20];

 

Char str5 [20];

 

Char str6 [20];

 

Char str7 [20];

 

Int a1, a2, a3, a4, a5, a6;

 

Sscanf (log, "<% d> % s % d % s", & a1, str2, str3, str4, & a5, & a6, str7 );

 

Printf ("% d/n", a1 );

 

Printf ("% s/n", str2 );

 

Printf ("% s/n", str3 );

 

Printf ("% s/n", str4 );

 

Printf ("% d/n", a5 );

 

Printf ("% d/n", a6 );

 

Printf ("% s/n", str7 );

 

Sscanf (test, "<% d> % d", & a5, & a6 );

 

Printf ("% d/n", a5 );

 

Printf ("% d/n", a6 );

 

Sscanf (log, "<% [^>]> % [^] % [^] % [^] % [^] % [^] % [^ $]", str1, str2, str3, str4, str5, str6, str7 );

 

Printf ("% s/n", str1 );

 

Printf ("% s/n", str2 );

 

Printf ("% s/n", str3 );

 

Printf ("% s/n", str4 );

 

Printf ("% s/n", str5 );

 

Printf ("% s/n", str6 );

 

Printf ("% s/n", str7 );

 

Return 1;

 

}

Const char * str = "drw-rw-1 user group 0 Oct 28 2003-=== FTP for pop music ==== -";

 

The above is the source string. I want to obtain the drw-rw-, group,-=== pop music-specific FTP =====-fields respectively.

 

Note: because the values of these fields will change, I need to format the input and store it in the following a B c!

 

Below is my attempt.

 

Char a [20];

 

Char B [50];

 

Char c [20];

 

Int ret = sscanf (str, "% [^ '''] * % [''u''] % [^ ''']"

 

, A, B, c );

 

From: Yan Ming -- To Be a Linux Kernel Hacker

Related Article

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.