변수 개수의 인수를 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);
}
문자열을 표시하기 전에 조작하고 버퍼에 저장해야 하는 경우 대신vsprintf
.vsnprintf
는 우발적인 버퍼 오버플로 오류를 방지합니다.
vsnprintf 를 참조해 주세요.이것에 의해, 원하는 것을 실행할 수 있습니다.http://www.cplusplus.com/reference/clibrary/cstdio/vsprintf/
먼저 va_list array를 초기화하고 호출해야 합니다.
이 링크의 예: /* 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);
}
variadic 함수를 찾고 있습니다. printf() 및 sprintf()는 variadic 함수입니다.변수의 인수를 받아들일 수 있습니다.
여기에는 기본적으로 다음 단계가 포함됩니다.
첫 번째 파라미터는 이어지는 파라미터의 수를 나타내야 합니다.따라서 printf()에서는 "format" 파라미터에 의해 이 표시가 나타납니다.포맷 지정자가 5개일 경우 5개의 인수(총 6개)가 더 검색됩니다.첫 번째 인수는 정수일 수 있습니다(예: "myfunction(3, a, b, c)". 여기서 "3"은 "3개의 인수"를 의미합니다).
그런 다음 va_start() 등의 함수를 사용하여 연속되는 각 인수를 루프하여 가져옵니다.
이 방법에는 많은 튜토리얼이 있습니다.행운을 빕니다!
스택 오버플로의 기존 질문에 대해 더 많이 읽었어야 했습니다.
C++ 변수 수 전달도 이와 유사한 질문입니다.Mike F의 설명은 다음과 같습니다.
장난꾸러기나 휴대하기 어려운 속임수를 쓰고 싶지 않다면, 당신이 얼마나 많은 논쟁을 하고 있는지 모르는 상태에서 printf에 전화를 걸 수 있는 방법은 없습니다.
일반적으로 사용되는 솔루션은 항상 vararg 함수의 대체 형식을 제공하는 것입니다.따라서 printf에는 va_list를 대신하는 vprintf가 있습니다.그...버전은 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);
}
타원형 함수를 사용하는 것은 매우 안전하지 않습니다.로그 기능에 성능이 중요하지 않은 경우 boost:: 형식과 같이 연산자 오버로드를 사용하십시오.다음과 같이 쓸 수 있습니다.
#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.
간단한 예는 다음과 같습니다.더 큰 버퍼를 전달하고 버퍼가 충분히 큰지 여부를 테스트해야 합니다.
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/,에서는 인수 수를 메서드에 전달하지만 이를 생략하고 코드를 적절히 변경할 수 있습니다(예 참조).
언급URL : https://stackoverflow.com/questions/1056411/how-to-pass-variable-number-of-arguments-to-printf-sprintf
'programing' 카테고리의 다른 글
물음표와 콜론(?: 3진 연산자)은 objective-c에서 무엇을 의미합니까? (0) | 2022.07.16 |
---|---|
JEST 유닛 테스트스크립트가 TypeError: this로 실패합니다._environment.runScript는 함수가 아닙니다. (0) | 2022.07.16 |
char*x가 값이 "hello"인 문자열을 가리킬 때 gdb에서 조건부 중단점을 설정하려면 어떻게 해야 합니까? (0) | 2022.07.16 |
Vue.js/Vuex: Getter 호출과 라이프 사이클 생성 후 직접 상태 값에 액세스 (0) | 2022.07.16 |
루트 전환 시 VueJ 메모리누전 (0) | 2022.07.16 |