想象一下,创建更新后的标签是x次/秒。标签的文本以格式说明符文本(ala printf)的形式给出,格式说明符的任何参数都在重绘时更新,因为格式说明符的参数是指向它们各自值的指针。 sprintf的任何变体都是这样的吗?
代码可以这样工作:
/* client */
createLabel("Value is %f", &myFloatValue);
我还没有找到办法做到这一点,有没有人有任何想法?我想可以解析格式文本,检索指针(和类型),并将它们存储为列表中的某个对象,稍后您可以重新打印文本,也可以将格式委托给对象本身,只传递文本缓冲区。 .hmmm
顺便说一下,接口是C,但主机是C ++。
好的,我有一个“工作”的原型,但它主要是用汇编程序编写的。无论如何,它演示了api的假设使用。任何人都可以看到一种可移植的方式来实现这个/有更好的实现想法吗? 它非常大,所以我将它发布在pastebin上: http://pastebin.com/H8ZpWb4u
答案 0 :(得分:0)
因此,您的createLabel
接口将存储格式字符串,以及您希望在字符串中显示的变量的地址。然后只需使用标准的旧sprintf
重新格式化文本。请注意那些指向数据的指针,并确保在必要时使它们无效。
我不确定问题是什么。你还在寻找什么? sprintf
能够做你想做的事情,但你必须自己跟踪格式字符串和变量地址。
答案 1 :(得分:0)
好吧我突然有了一个想法.. stringstream +模板化多态。我最终在5分钟内用C ++编写了这个东西,至少它是一个巨大的进步。
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
class CBaseValue
{
public:
virtual void toString(std::stringstream & buf) = 0;
};
template< typename T >
class CValue : public CBaseValue
{
typedef T type;
typedef T * ptr_type;
type * val;
public:
CValue(void * val)
{
this->val = reinterpret_cast<ptr_type>(val);
}
CValue(type * val) : val(val) {}
virtual void toString(std::stringstream & buf) {
buf << *val;
}
};
class CLabel
{
std::stringstream ss;
std::vector<CBaseValue *> valueList;
std::string format;
public:
CLabel() {};
void reset() {
format.clear();
ss.str("");
for(unsigned i = 0; i < valueList.size(); i++) {
delete valueList[i];
}
valueList.clear();
}
void setFormat(const char * fmt, ...) {
reset();
format = fmt;
va_list args;
va_start(args, fmt);
for(unsigned i = 0; i < format.size(); ++i) {
if(format[i] == '%') {
++i;
switch(fmt[i])
{
case 'd':
valueList.push_back(new CValue<unsigned int>( va_arg(args, void *) ));
break;
case 'f':
valueList.push_back(new CValue<float>( va_arg(args, void *) ));
break;
}
}
}
va_end(args);
}
std::string get() {
ss.str("");
unsigned count(0);
for(unsigned i = 0; i < format.size(); i++) {
if(format[i] == '%') {
i++; // ignore type specifiers, already polymorphically solved
valueList[count++]->toString(ss);
} else {
ss << format[i];
}
}
return ss.str();
}
~CLabel() {
reset();
}
};
int main() {
int test = 2;
float val = 3.14f;
CLabel myLabel;
myLabel.setFormat("Stringstream test, float: %f, and an int: %d \n", &val, &test);
std::cout << myLabel.get();
test = 3;
std::cout << myLabel.get();
system("pause");
}
答案 2 :(得分:0)
您可以使用std::bind
或boost::bind
做一些相对简单的事情。我将把它留作如何按摩C接口的练习。
#include <functional>
int main() {
int test = 2;
float val = 3.14f;
std::function<int()> label = std::bind(
printf,
"Stringstream test, float: %f, and an int: %d \n",
std::ref(val),
std::ref(test));
label();
test = 3;
label();
}