我需要显示一些包含数千个分组的数字(在这种情况下,使用句点作为分隔符)。所以,我正在使用printf标志'
来实现这样的事情。
随着gcc
一切顺利,但如果我使用icc
,那么我得到这个警告:
警告#269:格式字符串转换无效
尽管该数字确实以所需格式打印。
例如,如果我们编译这个简单的程序:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main(int argc, char *argv[]) {
setlocale(LC_NUMERIC, "da_DK");
int i = 12345678;
unsigned long int j = 987654321;
printf("%d \t %'d \n%lu \t %'lu \n", i, i, j, j);
}
然后我们得到这个警告:
% icc -o simple simple.c
simple.c(10): warning #269: invalid format string conversion
printf("%d \t %'d \n%lu \t %'lu \n", i, i, j, j);
^
尽管一切都按预期工作:
% ./simple
12345678 12.345.678
987654321 987.654.321
所以我的问题是:
'
编译器将icc
用作printf和朋友的标志是否安全?更新:
我刚刚意识到抑制269
警告的一个奇怪技巧是用格式定义变量,并将该变量传递给printf
:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main(int argc, char *argv[]) {
setlocale(LC_NUMERIC, "da_DK");
int i = 12345678;
unsigned long int j = 987654321;
const char *strFormat = "%d \t %'d \n%lu \t %'lu \n";
printf(strFormat, i, i, j, j);
}
更新:
因为使用带有printf
的撇号是XSI扩展(如@Dave所述),为了使代码更具可移植性,可能更有用的是遵循C-FAQ, question 12.11的建议并使用它们的commaprint
实现。
要回答第二个问题,编译器实际上并不控制格式字符串的处理;这是你的C库的工作。 icc
无法识别格式字符串,因为它是非标准的,但只要您了解您的代码仅在其c库支持'
标志的平台上有效,您就可以了。
正如opengroup page所示,'
是XSI扩展,因此您的代码将适用于任何符合XSI标准的平台。
所以:
#include <stdio.h>
void punt(int n){
char s[28];
int i = 27;
if(n<0){n=-n; putchar('-');}
do{
s[i--] = n%10 + '0';
if(!(i%4) && n>9)s[i--]=' ';
n /= 10;
}while(n);
puts(&s[++i]);
}
int main(){
int a;
scanf("%d",&a);
punt(a);
}
或者:
#include <stdio.h>
int main() {
char str[50];
int len = 0;
scanf("%48[^\n]%n", str, &len);
int start = len % 3;
for(int i = 0; i < len; i++) {
if(i == start && i != 0) {
printf(" ");
} else if((i - start) % 3 == 0 && i != 0) {
printf(" ");
}
printf("%c", str[i]);
}
return 0;
}