2016-05-06 33 views
0

我有一個單一的功能void* producer(void* param)傳遞給多個POSIX線程,其目標是讀文件的每一行或string (char*)陣列的每一行,並對其進行處理。既讀取文件和字符串數組用C

問題:如何使這個函數能夠優雅地適應這兩個可能的輸入? (我猜第一個將是文件的文件名或FILE*)。

到目前爲止,該功能只能讀取一個文件,這裏是它的代碼:

void* producer(void* param) 
{ 
    FILE* filep = *(FILE*)param; 

    char line[256]; 

    while (fgets(line, 256, filep) != NULL) 
    {  
     processLine(line); 
    } 

    return NULL; 
} 
+2

令人毛骨悚然:)最好使'param'指向一個結構或聯合,其中*明確*告訴它使用什麼。 – usr2564301

+1

使用帶有'mmap()'的內存映射文件,只需爲兩個可能性傳遞'char *'即可。即使代碼是相同的。 –

+1

@Frankie_C這是不真實的 - 字符串將被零終止,而內存映射文件不會。 (如果文件大小與頁面大小一致,則訪問超過末尾的字節將崩潰。)要覆蓋這兩個選項,OP將需要將字符串大小和字符串一起發送,這會帶回原始問題如何打包兩件事情在一個'void *'中。此外,內存映射在C中不可移植,並且如果文件不是常規文件(例如,如果它是管道),則映射可能會失敗。 – user4815162342

回答

2

提供一個知道如何根據其內容產生下一行的結構。例如(未經測試):

typedef struct { 
    FILE *fp; 
    const char *str; 
} Source; 

Source *source_new_from_file(const char *filename) 
{ 
    Source *ret = malloc(sizeof(Source)); 
    if (!ret) 
    return NULL; 
    ret->fp = fopen(filename, "rb"); 
    if (!ret->fp) 
    return NULL; 
    ret->str = NULL; 
    return ret; 
} 

Source *source_new_from_str(const char *str) 
{ 
    Source *ret = malloc(sizeof(Source)); 
    if (!ret) 
    return NULL; 
    ret->fp = NULL; 
    ret->str = str; 
    return ret; 
} 

bool source_read_line(Source *s, char *dest, size_t destsize) 
{ 
    if (s->fp) 
    return fgets(dest, destsize, s->fp) != NULL; 

    const char *newline = strchr(s->str, '\n'); 
    if (!newline) 
    // handle trailing line without newline, like fgets does 
    newline = s->str + strlen(s->str); 
    if (newline == s->str) 
    return false; // no more data 

    size_t linelen = newline - s->str; 
    if (linelen > destsize - 1) 
    linelen = destsize - 1; 
    memcpy(dest, s->str, linelen); 
    dest[linelen + 1] = '\0'; 
    s->str = newline; 
    return true; 
} 

// ... 

void* producer(void* param) 
{ 
    Source *source = param; 
    char line[256]; 

    while (source_read_line(source, line, sizeof line)) {  
    processLine(line); 
    } 

    return NULL; 
} 

有了這個代碼,你可以通過任何一種源到producer的。即使出現了一種新的源代碼(例如,數據庫查詢的結果集,或者「行」被編碼爲XML元素的XML文檔),只有擴展source_read_line,才能夠實現新功能更改producer中的任何代碼。

相關問題