2016-05-06 34 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中的任何代码。

相关问题