2017-06-07 175 views
-1

我创建了一个小的C程序创建一个时间戳,并将其附加到文件的文本名称:传递一个函数指针作为参数给fopen

#include <stdio.h> 
#include <time.h> 
#include <string.h> 
#include <stdlib.h> 

void time_stamp(){ 
    time_t rawtime; 
    struct tm * timeinfo; 
    char buffer [80]; 
    time (&rawtime); 
    timeinfo = localtime (&rawtime); 

    strftime (buffer,80,"myFile_%F.txt",timeinfo); 
    printf ("%s", buffer); 
} 


int main() 
{ 
    void (*filename_ptr)(); 
    filename_ptr = &time_stamp; 

    FILE * fp; 

    fp = fopen (filename_ptr, "w+"); 
    fprintf(fp, "%s %s %s %d", "We", "are", "in", 2017); 

    fclose(fp); 

    return 0; 
} 

但我不能得到的fopen接受指针该函数用时间戳创建名称。它期望一个const char。我如何施放我的函数指针呢?

+4

你期望fopen如何处理函数指针? – Yunnosch

+1

这是因为你的CPU没有DWIM(我的意思是什么)指令。在此之前,你需要实际告诉计算机该做什么,因为它无法读懂你的想法。 – Art

+1

查看您的手册或手册页,了解fopen的原型。这是你需要履行的合同。这些是你必须遵守的规则。如果有一个'const char *'作为第一个参数,那么你不应该传入一些奇怪的奇特函数指针。 – Gerhardh

回答

2

你不能,但你可以通过追加()的指针调用该函数。对于这项工作,改变你的函数实际上返回const char *(或char *

注意你不能只返回一个指针到您buffer,因为这是一个局部变量不再存在时,函数返回。您可以从函数外部传递指向buffer的指针。然后,您的原型应该是

char *time_stamp(char *buf, size_t len); 

修改后的代码:

#include <stdio.h> 
#include <time.h> 
#include <string.h> 
#include <stdlib.h> 

char *time_stamp(char *buf, size_t len){ 
    time_t rawtime; 
    struct tm * timeinfo; 
    time (&rawtime); 
    timeinfo = localtime (&rawtime); 

    strftime (buf,len,"myFile_%F.txt",timeinfo); 
    return buf; 
} 


int main() 
{ 
    char *(*filename_ptr)(char *, size_t); 
    filename_ptr = &time_stamp; 
    char buffer[80]; 

    FILE * fp; 

    fp = fopen (filename_ptr(buffer, 80), "w+"); 
    fprintf(fp, "%s %s %s %d", "We", "are", "in", 2017); 

    fclose(fp); 

    return 0; 
} 

有其他方法如何设计这个功能。 Neroku当你确定你永远不需要线程上下文中的函数时,答案是很好的。它简化了使用,甚至还有一些标准的C库函数。

第三种方法是通过从malloc()中获取它来使缓冲区成为分配的对象。这具有线程安全并且不需要任何额外参数的优点,函数本身像在原始的破碎版本中一样控制缓冲区的大小。缺点是调用者必须使用free()这个内存。这个示例代码(我这里不推荐的):

#include <stdio.h> 
#include <time.h> 
#include <string.h> 
#include <stdlib.h> 

char *time_stamp(){ 
    time_t rawtime; 
    struct tm * timeinfo; 
    time (&rawtime); 
    timeinfo = localtime (&rawtime); 

    char *buf = malloc(80); 
    strftime (buf,80,"myFile_%F.txt",timeinfo); 
    return buf; 
} 


int main() 
{ 
    char *(*filename_ptr)(); 
    filename_ptr = &time_stamp; 

    FILE * fp; 

    char *filename = filename_ptr(); 
    fp = fopen (filename, "w+"); 
    free(filename); 
    fprintf(fp, "%s %s %s %d", "We", "are", "in", 2017); 

    fclose(fp); 

    return 0; 
} 
2

fopen()需要一个const char *作为第一个参数:

FILE *fopen(const char *path, const char *mode); 

在你的函数time_stamp()打印时间戳和返回没有,即:void


您的新time_stamp()功能可以代替(注意staticbuffer声明):

const char* time_stamp(){ 
    time_t rawtime; 
    struct tm * timeinfo; 
    static char buffer [80]; 
    time (&rawtime); 
    timeinfo = localtime (&rawtime); 

    strftime (buffer,80,"myFile_%F.txt",timeinfo); 
    return buffer; 
} 

然后你可以呼叫在调用fopen()的时刻这一新功能。通过time_stamp()返回的值会变成的fopen()第一个参数:

const char * (*filename_ptr)(); 
filename_ptr = &time_stamp; 
// ... 
fp = fopen (filename_ptr(), "w+"); 

注意,值的类型从time_stamp()现在比赛的第一个参数的类型返回fopen()预计(即:const char *)。


注上线程安全

由于函数time_stamp()包含静态分配存储buffer),它是不安全的多线程程序中使用此功能,因为所有的线程那调用此函数将共享此存储的单个实例。

+1

不是它与OP有关,但是'static'使函数线程不安全。只是要记住;) –

+0

@FelixPalmen是的,上面的代码是*线程不安全*,但我不争取*线程安全*代码。 –

+0

为了提高答案的清晰度并部分降低重复使用以达到类似未来目的的风险,我建议将该稍有风险的假设编辑到答案中,并解释在哪种情况下以及在哪些情况下需要使用函数以便注意安全。然而,一般来说,编写线索函数对于编写可以以某种方式使用的函数而言是优选的,尽管不安全。 – Yunnosch

相关问题