使用预处理器定义的日期格式
date format using preprocessor defines
我想使用预处理器代码在小于 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' << var##n) 中,<< 不被视为 cout 流。
发生这种情况是因为 ('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;
发生这种情况是因为 ?:
三元运算符由编译器处理,而不是由预处理器处理。
当键入以下代码时,
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。
我真的不认为有使用处理器实现此目的的好方法。您可能认为去掉部分或全部括号可能会有所帮助,但这会导致您 运行 陷入运算符优先级问题,因为 <<
运算符的优先级高于 <
运算符。
如果您正在寻找一种更传统的方法来使用 std::cout
使输出填充零,我建议您查看 this post;如果您只是想了解有关预处理器的知识,希望我对您有所帮助!
我想使用预处理器代码在小于 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' << var##n) 中,<< 不被视为 cout 流。
发生这种情况是因为 ('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;
发生这种情况是因为 ?:
三元运算符由编译器处理,而不是由预处理器处理。
当键入以下代码时,
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。
我真的不认为有使用处理器实现此目的的好方法。您可能认为去掉部分或全部括号可能会有所帮助,但这会导致您 运行 陷入运算符优先级问题,因为 <<
运算符的优先级高于 <
运算符。
如果您正在寻找一种更传统的方法来使用 std::cout
使输出填充零,我建议您查看 this post;如果您只是想了解有关预处理器的知识,希望我对您有所帮助!