printf 字符串格式化 %6.9s %*.s

14 篇文章 0 订阅


I got a code snippet in which there is a

printf("%.*s\n")

what does the %.*s mean?

share improve this question
 
16 
Without additional arguments, that is not a valid printf call. –  Andrew Marshall  Oct 26 '11 at 5:58

3 Answers

up vote 64 down vote accepted

You can use an asterisk (*) to pass the width specifier/precision to printf(), rather than hard coding it into the format string, i.e.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}
share improve this answer
 
1 
It should be noted that the str_len argument must have type int (or narrower integral type, which would be promoted to int). It would be a bug to pass longsize_t, etc. –  M.M  Jul 7 '15 at 22:03 
 
It's worth mentioning that the likely purpose of this code, especially when used with %s, is to print a sub-string of the original string. In this use case, str would point to somewhere inside the original string (possibly at the beginning), and str_len will specify the length of the sub-string that should be printed. –  Sonic Atom  Jan 25 at 13:37 

I don't think the code above is correct but (according to this description of printf()) the .* means

The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.'

So it's a string with a passable width as an argument.

share improve this answer
 
2 
I've added the URL cross-reference so you can avoid charges of plagiarism. Of course, the correct quote says "The precision is not …" rather than "The width is not…". –  Jonathan Leffler  Mar 30 '15 at 4:52
 
As @MattMcNabb pointed out, every reference to that page must highlight that “an integer value” is exactlyint (or a subset of it) — not just any integral value like more intuitive size_t or its possible aliases, likestd::string::size_type. This is even more confusing, taking into account that the referenced page mentions size_t as one of supported type specifiers. –  Anton Samsonov  Aug 4 '15 at 18:04

See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/

.* The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.

s String of characters

I got a code snippet in which there is a

printf("%.*s\n")

what does the %.*s mean?

share improve this question
 
16 
Without additional arguments, that is not a valid printf call. –  Andrew Marshall  Oct 26 '11 at 5:58

3 Answers

up vote 64 down vote accepted

You can use an asterisk (*) to pass the width specifier/precision to printf(), rather than hard coding it into the format string, i.e.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}
share improve this answer
 
1 
It should be noted that the str_len argument must have type int (or narrower integral type, which would be promoted to int). It would be a bug to pass longsize_t, etc. –  M.M  Jul 7 '15 at 22:03 
 
It's worth mentioning that the likely purpose of this code, especially when used with %s, is to print a sub-string of the original string. In this use case, str would point to somewhere inside the original string (possibly at the beginning), and str_len will specify the length of the sub-string that should be printed. –  Sonic Atom  Jan 25 at 13:37 

I don't think the code above is correct but (according to this description of printf()) the .* means

The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.'

So it's a string with a passable width as an argument.

share improve this answer
 
2 
I've added the URL cross-reference so you can avoid charges of plagiarism. Of course, the correct quote says "The precision is not …" rather than "The width is not…". –  Jonathan Leffler  Mar 30 '15 at 4:52
 
As @MattMcNabb pointed out, every reference to that page must highlight that “an integer value” is exactlyint (or a subset of it) — not just any integral value like more intuitive size_t or its possible aliases, likestd::string::size_type. This is even more confusing, taking into account that the referenced page mentions size_t as one of supported type specifiers. –  Anton Samsonov  Aug 4 '15 at 18:04

See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/

.* The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.

s String of characters


C++ 字符串的格式化(转)

C++ | 2014-01-28 00:45:15 | 4426次阅读 |  0评

C++格式化字符串(续)

2. 一些特殊规定字符

━━━━━━━━━━━━━━━━━━━━━━━━━━ 

   字符                          作用

──────────────────────────

    \n                  换行

    \f                  清屏并换页

    \r                  回车

    \t                  Tab符

    \xhh                表示一个ASCII码用16进表示, 其中hh是1到2个16进制数

━━━━━━━━━━━━━━━━━━━━━━━━━━ 

 

        char c, s[20], *p; 

         int a=1234, *i; 

         float f=3.141592653589; 

         double x=0.12345678987654321; 

         p="How do you do"; 

         strcpy(s, "Hello, Comrade"); 

         *i=12; 

         c='\x41'; 

         printf("a=%d\n", a);     /*结果输出十进制整数a=1234*/ 

         printf("a=%6d\n", a);    /*结果输出6位十进制数a=  1234*/ 

         printf("a=%06d\n", a);   /*结果输出6位十进制数a=001234*/ 

         printf("a=%2d\n", a);    /*a超过2位, 按实际值输出a=1234*/ 

         printf("*i=%4d\n", *i);  /*输出4位十进制整数*i=  12*/ 

         printf("*i=%-4d\n", *i); /*输出左对齐4位十进制整数*i=12*/ 

         printf("i=%p\n", i);     /*输出地址i=06E4*/ 

         printf("f=%f\n", f);     /*输出浮点数f=3.141593*/ 

         printf("f=6.4f\n", f);   /*输出6位其中小数点后4位的浮点数f=3.1416*/ 

         printf("x=%lf\n", x);    /*输出长浮点数x=0.123457*/ 

         printf("x=%18.16lf\n", x);/*输出18位其中小数点后16位的长浮点数x=0.1234567898765432*/

         printf("c=%c\n", c);     /*输出字符c=A*/ 

         printf("c=%x\n", c);     /*输出字符的ASCII码值c=41*/ 

         printf("s[]=%s\n", s);   /*输出数组字符串s[]=Hello,Comrade*/ 

         printf("s[]=%6.9s\n", s);/*输出最多9个字符的字符串s[]=Hello,Co*/ 

         printf("s=%p\n", s);     /*输出数组字符串首字符地址s=FFBE*/ 

         printf("*p=%s\n", p);    /* 输出指针字符串p=How do you do*/ 

         printf("p=%p\n", p);     /*输出指针的值p=0194*/ 

 

   上面结果中的地址值在不同计算机上可能不同。

printf和sprintf 都使用C++格式化字符串来指定串的格式,在格式串内部使用一些以"%"开头的格式说明符(format specifications)来占据一个位置,在后边的变参列表中提供相应的变量,最终函数就会用相应位置的变量来替代那个说明符,产生一个调用者想要的字符串。

sprintf最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf在大多数场合可以替代itoa。

如:

1.  //把整数123 打印成一个字符串保存在s 中。  

2.  sprintf(s, "%d", 123); //产生"123"可以指定宽度,不足的左边补空格:  

3.  sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"当然也可以左对齐:  

4.  sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"  

也可以按照16 进制打印:
 

1.  sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐  

2.  sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐 

这样,一个整数的16 进制字符串就很容易得到,但我们在打印16 进制内容时,通常想要一种左边补0 的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0 就可以了。

1.  sprintf(s, "%08X", 4567); //产生:"000011D7" 

上面以"%d"进行的10 进制打印同样也可以使用这种左边补0 的方式。

这里要注意一个符号扩展的问题:比如,假如我们想打印短整数(short)-1 的内存16 进制表示形式,在Win32 平台上,一个short 型占2个字节,所以我们自然希望用4 个16 进制数字来打印它:

1.  short si = -1; 

2.  sprintf(s, "%04X", si); 

产 生"FFFFFFFF",怎么回事?因为spritnf 是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个"%X"就能得知当初函数调用前参数压栈时被压进来的到底 是个4 字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4 个位置不够了,就把32 位整数-1 的8 位16 进制都打印出来了。

如果你想看si 的本来面目,那么就应该让编译器做0 扩展而不是符号扩展(扩展时二进制左边补0 而不是补符号位):

1.  sprintf(s, "%04X", (unsigned short)si); 

就可以了。或者:

1.  unsigned short si = -1;  

2.  sprintf(s, "%04X", si);  

sprintf和printf 还可以按8 进制打印整数字符串,使用"%o"。注意8 进制和16 进制都不会打印出负数,都是无符号的,实际上也就是变量的内部编码的直接的16 进制或8 进制表示。

C++格式化字符串的具体应用方法就为大家介绍到这里。


I got a code snippet in which there is a

printf("%.*s\n")

what does the %.*s mean?

share improve this question
 
16 
Without additional arguments, that is not a valid printf call. –  Andrew Marshall  Oct 26 '11 at 5:58

3 Answers

up vote 64 down vote accepted

You can use an asterisk (*) to pass the width specifier/precision to printf(), rather than hard coding it into the format string, i.e.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}
share improve this answer
 
1 
It should be noted that the str_len argument must have type int (or narrower integral type, which would be promoted to int). It would be a bug to pass longsize_t, etc. –  M.M  Jul 7 '15 at 22:03 
   
It's worth mentioning that the likely purpose of this code, especially when used with %s, is to print a sub-string of the original string. In this use case, str would point to somewhere inside the original string (possibly at the beginning), and str_len will specify the length of the sub-string that should be printed. –  Sonic Atom  Jan 25 at 13:37 

I don't think the code above is correct but (according to this description of printf()) the .* means

The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.'

So it's a string with a passable width as an argument.

share improve this answer
 
2 
I've added the URL cross-reference so you can avoid charges of plagiarism. Of course, the correct quote says "The precision is not …" rather than "The width is not…". –  Jonathan Leffler  Mar 30 '15 at 4:52
   
As @MattMcNabb pointed out, every reference to that page must highlight that “an integer value” is exactlyint (or a subset of it) — not just any integral value like more intuitive size_t or its possible aliases, likestd::string::size_type. This is even more confusing, taking into account that the referenced page mentions size_t as one of supported type specifiers. –  Anton Samsonov  Aug 4 '15 at 18:04

See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/

.* The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.

s String of characters

`char s[100];` 声明了一个字符数组`s`,它可以存储最多99个字符加上一个空字符`\0`作为字符串结束标志。 `int a = 10, b = 20;` 声明了两个整型变量`a`和`b`,并分别初始化为10和20。 `sprintf(s, "%.*s%.*s%.*s", a, "6", b);` 是一个使用`sprintf`函数格式化字符串的语句。`sprintf`函数的功能是将格式化的数据写入字符串中,它与`printf`函数类似,区别在于`sprintf`将输出写入到字符串数组中而不是标准输出设备。在`sprintf`的格式字符串中,`%.*s`表示字符串的格式,其中`*`会被对应的整数参数替换,指定宽度,`s`表示要打印的字符串。这里的用法中,`a`和`b`两个变量分别用作了两个`%.*s`的宽度参数。 - `%.*s` 中的 `*` 被 `a` 替换,表示第一个字符串的最大宽度是10。 - 第二个 `%.*s` 中的 `*` 被 `"6"` 替换,由于 `"6"` 是一个字符串字面量,这里实际上是将字符串`"6"`视为格式字符串中的占位符,但是这样的使用是错误的,因为`*`应该被一个整数替换,而不是字符串。 - 最后一个 `%.*s` 中的 `*` 被 `b` 替换,表示第三个字符串的最大宽度是20。 由于这段代码中存在语法错误(第二个`%.*s`中的`*`后不应该跟字符串字面量),`sprintf`函数将无法正确执行预期的操作。 为了修正这个错误并清楚地说明这段代码的目的,如果意图是将字符串`s`格式化为三个部分,其中第一部分宽度为10,第二部分宽度为6,第三部分宽度为20,正确的代码应该是: ```c sprintf(s, "%*.*s%*.*s%*.*s", a, 10, "", 6, 6, "6", b, 20, ""); ``` 这里的`%*.*s`表示先根据`*`(即前面整数参数的值)确定宽度,再根据`*`(即后面的整数参数的值)确定精度,然后打印出字符串。`""`表示空字符串,因为这里不需要填充任何字符串,仅需要指定宽度和精度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值