簡體   English   中英

帶參考參數的printf

[英]printf with reference arguments

想象一下,有一個標簽在創建后更新了x次/秒。 標簽的文本作為格式說明符文本(ala printf)給出,並且格式說明符的任何參數在重繪時都會更新,因為格式說明符的參數是指向其各自值的指針。 sprintf的任何變體都可以這樣工作嗎?

該代碼將像這樣工作:

/* client */
createLabel("Value is %f", &myFloatValue);

我還沒有找到一種解決方法,有人有什么想法嗎? 我猜一個人可以解析格式文本,檢索指針(和類型),並將它們存儲為列表中的某個對象,稍后您可以在其中重新打印文本,還可以將格式委托給對象本身,僅將它們傳遞給文本緩沖區。嗯

順便說一句,接口是C,但是主機是C ++。

好的,我有一個“有效的”原型,但是它主要是用匯編語言編寫的。 無論如何,它演示了api的假定用法。 誰能看到一種便攜式的方法來做到這一點/對實現有一個更好的主意? 它很大,所以我將其發布在pastebin上: http : //pastebin.com/H8ZpWb4u

因此,您的createLabel接口將存儲格式字符串以及要在字符串中顯示的變量的地址。 然后,只需使用標准的舊sprintf重新格式化文本即可。 請注意那些指向數據的指針,並確保在必要時使它們無效。

我不確定是什么問題。 您還在尋找什么? sprintf可以執行您想要的操作,但是您將不得不自己跟蹤格式字符串和變量地址。

好吧,我突然有一個主意.. 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");
}

您可以使用std::bindboost::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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM