簡體   English   中英

如何將可變數量的參數傳遞給printf / sprintf

[英]How to pass variable number of arguments to printf/sprintf

我有一個類,其中包含一個“錯誤”函數,該函數將格式化某些文本。 我想接受可變數量的參數,然后使用printf格式化它們。

例:

class MyClass
{
public:
    void Error(const char* format, ...);
};

Error方法應該接受參數,調用printf / sprintf對其進行格式化,然后對其進行處理。 我不想自己寫所有格式,因此嘗試弄清楚如何使用現有格式很有意義。

void Error(const char* format, ...)
{
    va_list argptr;
    va_start(argptr, format);
    vfprintf(stderr, format, argptr);
    va_end(argptr);
}

如果要在顯示字符串之前對其進行操作,並且確實確實需要首先將其存儲在緩沖區中,請使用vsnprintf而不是vsprintf vsnprintf將防止意外的緩沖區溢出錯誤。

看看vsnprintf,因為這會滿足您的要求http://www.cplusplus.com/reference/clibrary/cstdio/vsprintf/

您必須先初始化va_list arg數組,然后再調用它。

該鏈接的示例:/ * vsprintf示例* /

#include <stdio.h>
#include <stdarg.h>

void Error (char * format, ...)
{
  char buffer[256];
  va_list args;
  va_start (args, format);
  vsnprintf (buffer, 255, format, args);


  //do something with the error

  va_end (args);
}

在橢圓上使用函數不是很安全。 如果性能對日志功能不是很關鍵,請考慮像boost :: format那樣使用運算符重載。 您可以這樣寫:

#include <sstream>
#include <boost/format.hpp>
#include <iostream>
using namespace std;

class formatted_log_t {
public:
    formatted_log_t(const char* msg ) : fmt(msg) {}
    ~formatted_log_t() { cout << fmt << endl; }

    template <typename T>
    formatted_log_t& operator %(T value) {
        fmt % value;
        return *this;
    }

protected:
    boost::format                fmt;
};

formatted_log_t log(const char* msg) { return formatted_log_t( msg ); }

// use
int main ()
{
    log("hello %s in %d-th time") % "world" % 10000000;
    return 0;
}

下面的示例演示了橢圓的可能錯誤:

int x = SOME_VALUE;
double y = SOME_MORE_VALUE;
printf( "some var = %f, other one %f", y, x ); // no errors at compile time, but error at runtime. compiler do not know types you wanted
log( "some var = %f, other one %f" ) % y % x; // no errors. %f only for compatibility. you could write %1% instead.

我應該閱讀有關堆棧溢出中現有問題的更多信息。

C ++傳遞可變數量的參數是一個類似的問題。 Mike F有以下解釋:

在不知道要傳遞給它多少參數的情況下,無法調用(例如)printf,除非您想陷入頑皮和不可移植的竅門。

通常使用的解決方案是始終提供另一種形式的vararg函數,因此printf具有vprintf,它使用va_list代替...。...版本只是va_list版本的包裝。

這正是我想要的。 我執行了這樣的測試實施:

void Error(const char* format, ...)
{
    char dest[1024 * 16];
    va_list argptr;
    va_start(argptr, format);
    vsprintf(dest, format, argptr);
    va_end(argptr);
    printf(dest);
}

您正在尋找可變參數函數 printf()和sprintf()是可變參數函數-它們可以接受可變數量的參數。

這基本上包括以下步驟:

  1. 第一個參數必須說明后面的參數數量。 因此,在printf()中,“ format”參數給出了這一指示-如果您有5個格式說明符,則它將查找另外5個參數(總共6個參數。)第一個參數可以是整數(例如“ myfunction” (3,a,b,c)”,其中“ 3”表示“ 3個自變量”

  2. 然后使用va_start()等函數循環遍歷並檢索每個連續的參數。

有很多關於如何執行此操作的教程-祝您好運!

下面的簡單示例。 請注意,您應該傳遞更大的緩沖區,並測試緩沖區是否足夠大

void Log(LPCWSTR pFormat, ...) 
{
    va_list pArg;
    va_start(pArg, pFormat);
    char buf[1000];
    int len = _vsntprintf(buf, 1000, pFormat, pArg);
    va_end(pArg);
    //do something with buf
}

看一下示例http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg/ ,它們將參數數量傳遞給方法,但是您可以忽略該參數並適當地修改代碼(請參見示例)。

暫無
暫無

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

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