Programing

가변 개수의 인수를 printf / sprintf에 전달하는 방법

lottogame 2020. 10. 16. 07:03
반응형

가변 개수의 인수를 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 ++ Passing Variable Number of Arguments 는 비슷한 질문입니다. Mike F의 설명은 다음과 같습니다.

당신이 장난스럽고 이식 불가능한 속임수를 쓰길 원하지 않는 한, 당신이 얼마나 많은 인수를 전달하고 있는지 알지 않고는 printf를 호출 할 방법이 없습니다.

The generally used solution is to always provide an alternate form of vararg functions, so printf has vprintf which takes a va_list in place of the .... The ... versions are just wrappers around the va_list versions.

This is exactly what I was looking for. I performed a test implementation like this:

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);
}

You are looking for variadic functions. printf() and sprintf() are variadic functions - they can accept a variable number of arguments.

This entails basically these steps:

  1. The first parameter must give some indication of the number of parameters that follow. So in printf(), the "format" parameter gives this indication - if you have 5 format specifiers, then it will look for 5 more arguments (for a total of 6 arguments.) The first argument could be an integer (eg "myfunction(3, a, b, c)" where "3" signifies "3 arguments)

  2. Then loop through and retrieve each successive argument, using the va_start() etc. functions.

There are plenty of tutorials on how to do this - good luck!


Simple example below. Note you should pass in a larger buffer, and test to see if the buffer was large enough or not

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
}

Have a look at the example http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg/, they pass the number of arguments to the method but you can ommit that and modify the code appropriately (see the example).

참고URL : https://stackoverflow.com/questions/1056411/how-to-pass-variable-number-of-arguments-to-printf-sprintf

반응형