将函数指针作为参数传递给fopen

时间:2017-06-07 06:13:21

标签: c

我创建了一个用于创建时间戳的小型C程序,并将其附加到文件文本名称:

#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。我如何将函数指针转换为它?

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:2)

fopen()期望const char *作为第一个参数:

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

在您的函数time_stamp()中,您打印时间戳并且不返回任何内容,即:void

您可以使用新的time_stamp()功能(请注意static声明中的buffer):

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),因此在多线程程序中使用此函数是不安全的,因为所有线程调用此函数将共享此存储的单个实例。