2016-03-03 81 views
0

我正在使用vsprintf從格式生成一個字符串,並且在記錄之前需要預先查找預先安排的字符串。下面的代碼打印格式字符串,但我會如何預先給另一個字符串呢?理想情況下,以相當有效的方式。使用vsprintf預先填充字符串到另一個格式字符串的一種有效方法

例如,如果我叫這樣的:

LOG(SYSTEM1, DEBUG, "number=%d, string=%s\n", 1, "Hi"); 

我會看到印:

SYSTEM1 number=1, string=Hi 

到目前爲止的代碼:

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

#define EMERGENCY  0 
#define ERROR   1 
#define WARN   2 
#define INFO   3 
#define DEBUG   4 

enum SubSystemID { SYSTEM1, SYSTEM2, SYSTEM3, SYSTEM4 }; 

void LOG(enum SubSystemID id, unsigned long severity, const char* format, ...) { 
    static const char* chaTypes[] = { 
     "SYSTEM1", "SYSTEM2", "SYSTEM3", "SYSTEM4" }; 

    char buffer[256]; 
    va_list args; 
    va_start (args, format); 
    vsprintf(buffer, format, args); 

    // Code here to send a char* string to a logging system 
    printf(buffer); 

    va_end (args); 
} 
+0

爲什麼不使用最後的'printf'來進行連接?數組應該是'static const char * const chaTypes []',否則表本身不是'const'。 – Olaf

+0

@Olaf這太容易了。然而我懷疑'printf(buffer);'是真正的「發送char *字符串到日誌系統」的佔位符。 – chux

+0

@Olaf由chux建議,printf(buffer)確實是一個將字符串發送到日誌系統的佔位符 –

回答

1

你可以嘗試: -

strcpy (buffer, chaTypes [id]); 
vsprintf (&buffer [strlen (buffer)], format, args); 

,或者你可以預先計算strlen的一部分使其整數數組: -

static int [] lengths = null; 

if (lengths == null) 
{ 
    lengths = malloc (sizeof (int), sizeof chaTypes/sizeof chaTypes [0]); 
    foreach string 
    lengths [i] = strlen (chaTypes [i]); 
} 
+1

是'foreach string'僞代碼還是C的一些新味道? – chux

+0

是的,這是僞代碼。 – Skizz

0

如果你的目的是爲了避免格式化我會用的fwrite()和發送任何你想要的文件句柄。如果你想使用一些其他的設施,那麼你可能想擁有某種通用輸出字符串函數,然後通過它輸出你的日誌語句。

例如:

void writeLogString(const char *str, int len) 
{ 
#ifdef _WIN32 
    OutputDebugStringA(str); 
#else 
    fwrite(str, sizeof(char), len, stdout); 
#endif 
} 

void vlogf(enum SubSystemID id, unsigned long severity, const char *format, va_args args) 
{ 
    const char *chaTypes[] = { "SYSTEM1", "SYSTEM2", "SYSTEM3", "SYSTEM4" }; 

    char buffer[256]; 
    int len = vsnprintf(buffer, sizeof(buffer), format, args); 

    writeLogString(chaTypes[id], strlen(chaTypes[id])); 
    writeLogString(" ", 1); 
    writeLogString(buffer, len); 
} 

void logf(enum SubSystemID id, unsigned long severity, const char *format, ...) 
{ 
    va_list args; 
    va_start(args, format); 
    vlogf(id, severity, format, args); 
    va_end(args); 
} 

一般來說我會確保我的日誌記錄工作首先是因爲它通常是到調試應用程序非常關鍵。

如果您遇到速度問題,那麼無論您嘗試做什麼,printf()都會導致性能下降。如果您確實需要加速生產環境中的日誌記錄,則可能需要考慮使用某些宏,以便在禁用嚴重性時甚至不調用格式化函數。

編輯:A working example here with some tests

1

代碼可以重新寫入格式。

// concatenate in some fashion. 
char *prefix = chaTypes[id]; // chaTypes[] must not contain % 
size_t len1 = strlen(prefix); 
size_t len2 = strlen(format) + 1; 
char newformat[len1 + len2]; 
memcpy(newformat, prefix, len1); 
memcpy(&newformat[len1], prefix, len2); 

vsprintf(buffer, newformat, args); 

然而@Skizzstrcpy()想法是很難被擊敗。

+0

我使用malloc()和/或strcpy()看到的問題是,vsprintf()已經爲你做到了這一點,所以你避免了額外拷貝的懲罰。一個拷貝到你已經分配的任何內存字符串,那麼另一個來自vsprintf()本身。 – Kelmar

+0

@Kelmar關注「使用malloc()和/或strcpy()」。這個答案不使用'malloc()'和'strcpy()'。此外,'vsprintf()'不知道調用'malloc()',因此關於'malloc()'的註釋不清楚。此外,與處理格式字符串的處理的陷阱相比,複製字符串性能微不足道。 – chux

+0

對不起,你對內存分配是正確的。 如果vprintf()爲你做了這些事情,那麼爲什麼還要做所有的工作? – Kelmar

相關問題