2012-08-25 72 views
0

是否有一個簡單的API(無循環)來檢查可變參數是否包含某些值(char *)?C++檢查可變參數是否包含

如果沒有簡單的API,我應該如何迭代而沒有任何參數?

我的方法應該能夠過濾配置IP上的日誌庫,所以我需要檢查其中一個參數是否爲10.3.2.2(某些配置IP)。

void Logger::Log(const char *format, ...) { 
    lock_guard<mutex> guard(mtx_); 
    if (!file_) { 
     file_ = fopen("application.log", "w"); 
    } 
    time_t current = time(0); 
    tm *ptm = localtime(&current); 
    stringstream ss; 
    ss << "\n[" << ptm->tm_min << ":" << ptm->tm_sec << "]"; 
    fprintf(file_, ss.str().data()); 
    va_list argptr; 
    va_start(argptr, format); 
    vfprintf(file_, format, argptr); 
    va_end(argptr); 
    fflush(file_); 
} 

尋找這個lesson,只顯示給定ARGS長度和類型進行迭代。格式和檢查包含的格式比較昂貴,並且記錄器應該能夠支持高性能需求。

我的目標是實現簡單的記錄器方法。所以你會這樣稱呼它:

Log("trafic from ip %s to ip %s", "10.1.1.1","1.1.1.1") 

和很多其他調用。在過濾器中,我想檢查一個參數值是否爲「10.1.1.1」(例如),所以不要記錄它。

+1

不,在C++中沒有這樣做。 – tenfour

+0

在本課中,您錯誤地指出只是給出長度的迭代。在那個例子中,你也被告知所有的參數都是雙精度的。你需要參數的類型以及長度,這對你的情況來說是個大問題。 –

+0

@DavidSchwartz你是對的。我的意思是我甚至沒有長度。 –

回答

2

這樣做沒有任何語法糖,因爲沒有通用的方法來知道可變參量的類型。不知道類型,你不能得到它們的價值。所以你必須根據你的函數如何知道它的參數是什麼類型來編寫代碼。

你想這樣做:

  1. stringstream組裝完整的日誌信息。

  2. 檢查所需字符串的日誌消息。

  3. 如果您發現字符串在那裏,請確保它是而不是前面或後面有一個數字。

  4. 如果您發現該字符串,並且前後沒有數字,請將其記錄下來。

您需要最後一次檢查,因爲「foo bar 12.3.4.5 baz」包含「2.3.4.5」,就像「foo 2.3.4.51 bar」一樣。所以,如果你找到了字符串,並在它後面或前面加了一個數字,你仍然希望記錄該消息。

+0

你將不得不分析格式字符串,這將是一個非常*痛苦的事情必須編碼。你必須理解和正確處理你的函數允許採用的每一個格式說明符,找出它們需要的參數類型(如果有的話),並跳過可變參數中的參數類型。你已經把自己塗在一個角落,應該重新考慮設計,或者採取「希望它足夠好」的方法,並從臨時緩衝區輸出「strstr」。 –

+0

正如你所說格式和檢查包括可以是昂貴的,我的記錄器需要處理嚴格的性能需求。 –

+0

你已將自己塗在角落裏。備份並修復設計。 –

3

不,沒有。無論如何,你不應該在C++中使用可變參數,而是使用可變參數模板。

-1

那麼,不,沒有索引訪問變量參數列表;只是一件一件,所以你必須循環通過它們;這就是vprintf等工作。當你遍歷項目時,你需要知道有多少,通常是它們的類型,這是按照慣例建立的。對於vprintf等,格式字符串中的格式說明符的格式說明符必須至少與格式說明符一樣多,並且每個格式說明符都會告訴您參數的預期類型。您可以採用的另一個約定是使用標記值來標記參數列表的末尾;對於齊次列表(例如指針列表),空指針可能是可行的標記。