我想使用预处理器代码在数字低于10之前打印一个带有'0'的日期。 例如,如果我有数字11,1,2015,则输出应为11 01 2015
我有这个预处理器:
#define getDateFromVar(n) \
( (var##n<10) ? ('0' << var##n) : (var##n ) )
我的C ++代码是这样的:
int var1 = 11, var2 = 1, var3 = 2015;
cout << "The date is: " << getDateFromVar(1)
<< " " << getDateFromVar(2)
<< " " << getDateFromVar(3) << endl;
投入量为:11 96 2015。 96等于48左移1。 在该序列中('0'&lt;&lt; var ## n),&lt;&lt;不被视为cout溪流。
答案 0 :(得分:1)
这是因为首先评估('0' << var##n)
,用括号括起来,只将其结果传递给cout
。
您可以通过更改为:
来避免这种情况#define getDateFromVar(n) \
((var##n<10) ? "0" : "") << (var##n)
// "0" if var < 10, otherwise empty string, followed by var
但作为一般规则,不建议使用宏。根据情况,它可能会使代码更难以阅读/理解,并可能导致难以发现错误。
作为替代方案,代码可以更改为:
#include <iomanip>
cout << "The date is: " << setfill('0')
<< setw(2) << var1 << " "
<< setw(2) << var2 << " "
<< setw(4) << var3 << endl;
答案 1 :(得分:0)
这是因为?:
三元运算符由编译器处理,而不是由预处理器处理。
键入以下代码时,
int var2 = 1;
cout << getDateFromVar(2) << endl;
你认为会发生的事情是:
cout << '0' << var2 << endl;
如果事情以这种方式运作,你最终会按照自己的意愿正确填充输出。但是,预处理器实际上做的是首先替换宏参数,然后基本上将宏的整个主体插入到源文件中。这导致如下:
cout << ( (var2<10) ? ('0' << var2) : (var2 ) ) << endl;
此时,预处理器的工作已完成,C ++编译器接管。首先评估括号内的所有内容,如果选择条件的第一个选项,<<
运算符的两个参数是整数类型('0'
和var2
),因此它执行它是左移的传统功能,将'0'
(48)的ASCII值向左移动一个位置,从而产生您正在观察的96。
我真的不认为有一种使用处理器实现这一目标的好方法。您可能认为删除部分或全部括号可能有所帮助,但这会导致您遇到运算符优先级问题,因为<<
运算符的优先级高于<
运算符。< / p>
如果您正在寻找一种更常规的方法来使用std::cout
来获取带零填充的输出,我建议您查看this post;如果您只是想了解预处理器的一些内容,我希望我已经帮助过了!