我有一个带有简单打印功能的模板缓冲类。
template <typename valueType, typename sumType, int N>
class IM_buffer
{
public:
IM_buffer()
: bufferValues(), numValues(-1), currentSum() { }
void record(valueType sample)
{
// Set buffer index to be recorded
numValues++;
// Get memory location for oldest element in buffer
valueType& oldest = bufferValues[modIdx(numValues)];
// Add the input value to the current sum and take away the value being replaced
currentSum += sample - oldest;
// And now do the actual replacement in the same memory location
oldest = sample;
}
valueType getCurrent() { return bufferValues[modIdx(numValues)]; }
valueType getNthPrev(int Nprev) { return bufferValues[modIdx(numValues-Nprev)]; }
sumType getCurrentSum() { return currentSum; }
double getAvg() { return (double) currentSum / MIN(numValues+1, N); }
int getNumValues() { return numValues+1; }
int getBufferSize() { return N; }
void printBuff()
{
for (int ii=0; ii<N; ii++)
{
// if it's an integer type I need:
printf("bufferValues[%2d]=%4d\n",ii,bufferValues[ii]);
// but if it's a floating point type I need:
printf("bufferValues[%2d]=%8g\n",ii,bufferValues[ii]);
}
}
void clear()
{
for (int ii=0; ii<N; ii++)
bufferValues[ii] = (valueType) 0.0;
numValues = 0;
currentSum = (sumType) 0.0;
}
private:
valueType bufferValues[N];
int numValues;
sumType currentSum;
int modIdx(int a) { return (a % N + N) % N; }
};
但是,printf
的格式字符串应该取决于数据类型是什么(例如int,vs。float,vs double)。我看过像this这样的讨论,但我并不想打印出数据类型,我只需要根据数据类型更改printf
格式字符串。任何人都可以指出我正确的方向,如何实现一些条件逻辑来选择正确的printf
?
答案 0 :(得分:1)
正如评论中提到的其他人一样,您应该使用对所有内置类型都有重载的std::cout
。但是,如果你真的坚持使用printf
,你可以尝试以下黑客攻击:
#include <typeinfo> // for typeid
std::string printfCmd("I wish to print this: ");
// int myVar = 69; // uncomment to change var type to int
char myVar = 'd';
if (typeid(int) == typeid(myVar)) {
printfCmd += "%d";
} else if (typeid(char) == typeid(myVar)) {
printfCmd += "%c";
} else {
// some warning/error
}
printf(printfCmd.c_str(), myVar);
这不是一个好的解决方案,只有在你真的需要时才使用它。
答案 1 :(得分:0)
如果您不想使用C ++重载的插入运算符,您可以编写自己的重载函数:
void print(int i) {
printf("%4d",i);
}
void print(double d) {
printf("%8g",d);
}
等
现在,您可以在需要时通过print
功能致电printBuff
:
printf("bufferValues["%2d] =",ii);
print(bufferValues[ii]);
printf("\n");
答案 2 :(得分:0)
根据您的情况,另一种可能比其他解决方案更好也可能不会更好,它是使用模板在编译时根据类型对格式说明符进行模板化。
TL;DR 示例程序(链接如下):
cinttypes
无论如何:
template <typename T> static const char *outFormat = ""; // pick a default.
template <> const char *outFormat<float> = "%8.4f";
template <> const char *outFormat<double> = "%8.4lf";
template <> const char *outFormat<long double> = "%8.4Lf";
template <> const char *outFormat<char> = "%c";
并像这样使用它们,例如:
typedef float some_api_type; // some external libraries unknown type
void printAPIValue (some_api_type value) {
printf(outFormat<some_api_type>, value);
printf("\n");
}
// or, for example, printing an stl container...
template <typename Container> void printValues (const Container &c) {
using value_type = typename Container::value_type;
printf("[ ");
for (auto i = c.cbegin(); i != c.cend(); ++ i) {
printf(outFormat<value_type>, *i);
printf(" ");
}
printf("]\n");
}
所以,例如this program:
some_api_type value = 4;
std::vector<float> floats = { 1.0f, 1.1f, -2.345f };
std::vector<char> chars = { 'h', 'e', 'l', 'l', 'o' };
printAPIValue(value);
printValues(floats);
printValues(chars);
会产生这样的输出:
4.0000
[ 1.0000 1.1000 -2.3450 ]
[ h e l l o ]
上述内容有多种形式,因此您必须做一些适合您情况的事情。例如:
为方便起见,我指定了 %
和字段宽度/精度。您可以删除所有这些并根据需要构建它,在这种情况下,使用 std::string
可能会为您节省一些输入时间。 This program:
template <typename T> static string outFormat;
template <> const string outFormat<float> = "f";
template <> const string outFormat<int> = "d";
// graceful handling of unsupported types omitted.
template <typename Container> void printValues (const Container &c) {
using value_type = typename Container::value_type;
int index = 0;
printf("list with format %s:\n", outFormat<value_type>.c_str());
for (auto i = c.cbegin(); i != c.cend(); ++ i, ++ index) {
string format = "item[%d] = %10" + outFormat<value_type> + "\n";
printf(format.c_str(), index, *i);
}
}
int main () {
std::vector<float> floats = { 1.0f, 1.1f, -2.345f };
std::vector<int> ints = { -1, 1, -2, 9 };
printValues(floats);
printValues(ints);
}
输出:
list with format f:
item[0] = 1.000000
item[1] = 1.100000
item[2] = -2.345000
list with format d:
item[0] = -1
item[1] = 1
item[2] = -2
item[3] = 9
您还可以将 cinttypes(C 的 inttypes.h)用于一些与平台无关的内容,例如this program:
#include <cstdio>
#include <cinttypes> // types and PRI* sized format specifiers
template <typename T> static const char *hexFormat = "<unsupported type>";
template <> const char *hexFormat<uint8_t> = "0x%02" PRIx8;
template <> const char *hexFormat<uint16_t> = "0x%04" PRIx16;
template <> const char *hexFormat<uint32_t> = "0x%08" PRIx32;
template <> const char *hexFormat<uint64_t> = "0x%016" PRIx64;
template <typename UIntValue> void printHex (UIntValue value) {
printf(hexFormat<UIntValue>, value);
printf("\n");
}
int main () {
printHex((size_t)0xABCD1234);
printHex(9U);
printHex(9UL);
printHex((unsigned char)'!');
printHex(9.0);
}
在 64 位平台上,可能会输出:
0x00000000abcd1234
0x00000009
0x0000000000000009
0x21
<unsupported type>
您有多种选择来强制使用支持的类型,我不打算列出它们,发挥您的想象力。但;由于您使用的是模板,因此您可以根据需要进行一些编译时检查。例如,this program,使用 static_assert
:
#include <cstdio>
template <typename T> static constexpr const char *format = nullptr;
template <> constexpr const char * format<short> = "%hd\n";
template <> constexpr const char * format<int> = "%d\n";
template <> constexpr const char * format<long> = "%ld\n";
template <typename Value> void print (Value value) {
static_assert(format<Value> != nullptr, "Unsupported type.");
printf(format<Value>, value);
}
int main () {
print<short>(1);
print<int>(1);
print<float>(1); // <-- compilation will fail here
print<long>(1);
}
将无法编译该 print<float>
行:
error: static assertion failed: Unsupported type.
这可以帮助您发现错误。
关于这一切,可能还有很多话要说,但我厌倦了打字,需要回去工作。希望这对某人有帮助。