我需要一個像 一樣作業的函式printf,但對fmt字串進行了一些更改:例如,在開頭添加一個包含日期時間的字串,但其余的,我將保持相同的printf內容...
void simple_printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
va_end(args);
/* made some changes to fmt, concatenate string,...*/
printf(fmt, ...);
}
這是我正在制作的代碼。如您所見,我希望更改fmt字串,但之后,呼叫“標準”printf或sprintf,傳遞引數 - 一種繞過。
這可能嗎?
uj5u.com熱心網友回復:
有多種方法可以做到這一點。你可以找到我的一些代碼,做這樣的事情在我的SOQ(堆疊溢位問題)在GitHub存盤庫作為檔案stderr.c,并stderr.h在SRC / libsoq子目錄。這是我多年來開發的一個包(最早的版本我仍然有 1988 年的日期記錄)并且我在我的大多數 C 程式中使用它。
現在使用的方案通過將要格式化的資料轉換為字串err_fmtmsg(),然后使用適當的寫入機制(標準 I/O,例如fprintf(), or
write(), or syslog())將訊息發送到輸出,從而確保存在單個寫入操作機制。
static size_t err_fmtmsg(char *buffer, size_t buflen, int flags, int errnum,
const char *format, va_list args)
{
char *curpos = buffer;
char *bufend = buffer buflen;
buffer[0] = '\0'; /* Not strictly necessary */
if ((flags & ERR_NOARG0) == 0)
curpos = efmt_string(curpos, bufend, "%s: ", arg0);
if (flags & ERR_LOGTIME)
{
char timbuf[32];
curpos = efmt_string(curpos, bufend,
"%s - ", err_time(flags, timbuf, sizeof(timbuf)));
}
if (flags & ERR_PID)
curpos = efmt_string(curpos, bufend,
"pid=%d: ", (int)getpid());
curpos = vfmt_string(curpos, bufend, format, args);
if (flags & ERR_ERRNO)
curpos = efmt_string(curpos, bufend,
"error (%d) %s\n", errnum, strerror(errnum));
assert(curpos >= buffer);
return((size_t)(curpos - buffer));
}
正如您所看到的,這可以為由arg0(程式名稱,通過函式設定err_setarg0();它可以添加一個 PID;它可以添加時間戳)的訊息作為前綴(具有整數秒、毫秒、微秒、納秒的選項在控制之下的標志),也可以附加錯誤編號和相應的系統錯誤訊息。
這是隱藏在系統內部的功能。在外部級別,入口點之一是extern void err_syserr(const char *fmt, ...);——這會自動添加系統錯誤,在標準錯誤上列印訊息,然后退出程式。日志記錄還有各種各樣的其他入口點,其中一些退出,一些回傳。還有很多控制元件。
請注意,該err_fmtmsg()函式接受一個引數va_list args。這通常是最好的作業方式。您應該使用此方案撰寫代碼:
void simple_printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
simple_vprintf(fmt, args);
va_end(args);
}
void simple_vprintf(const char* fmt, va_list args)
{
/* … preamble … */
vprintf(fmt, args);
/* … postamble … */
}
您可以使用該va_list函式撰寫 main 函式,并使用...對 main 函式的呼叫提供一個方便的界面,如上所示。
如果您打算多次呼叫標準 I/O 寫入函式(fprintf()等),請考慮使用flockfile()
并funlockfile()保持輸出“原子”。
void simple_vprintf(const char* fmt, va_list args)
{
flockfile(stdout);
/* … preamble — possibly writing to stdout … */
vprintf(fmt, args);
/* … postamble — possibly writing to stdout … */
funlockfile(stdout);
}
您還可以考慮提供以下功能:
extern void simple_fprintf(FILE *fp, const char *fmt, ...);
extern void simple_vfprintf(FILE *fp, const char *fmt, va_list args);
然后simple_vprintf()將簡單地呼叫simple_vfprintf(stdout, fmt, args). 然后,您可能會開始查看static inline頭檔案中覆寫函式的實作。
一段時間后,如果您實作了足夠多的變體,您就會開始侵占stderr.[ch].
uj5u.com熱心網友回復:
printf您應該vprintf從可變引數函式中呼叫,而不是呼叫:
#include <stdarg.h>
#include <stdio.h>
void simple_printf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
time_t t = time(NULL);
int d = (t - 746755200) / 86400;
int h = (t %= 86400) / 3600;
int m = (t %= 3600) / 60;
int s = t % 60;
/* output a timestamp at the beginning of the line, thank you Janice Brandt */
printf("Sep %d, 1993 d:d:d UTC: ", d, h, m, s);
/* no changes should be made to fmt because it is a constant string */
vprintf(fmt, args);
va_end(args);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/386855.html
上一篇:Libcurl-什么是“curl_multi_perform”
下一篇:如何將輸出更改為等邊三角形數字?
