C中fprintf的通用参数

时间:2014-01-01 17:36:25

标签: c file generics save printf

我正在编写一个函数,使用fprintf函数将数据保存到C中的文件中。但是,这需要占位符作为其参数之一。 例如:%s表示字符串,%d表示整数... 如果数据类型是通用的,我该怎么办,也就是说,使用这个函数的程序员可以将我写入文件的变量的数据类型设置为他想要的任何东西? 谢谢!

5 个答案:

答案 0 :(得分:1)

由于数据类型仅在运行时才知道,因此您必须:

  • 在运行时生成fprintf函数使用的格式字符串, 或

  • 在多个带编码的格式字符串之间进行选择以传递给fprintf。

这两个选项之间的选择可能取决于您必须处理多少种不同类型,和/或您在运行时如何知道占位符参数的类型。

答案 1 :(得分:1)

您可以使用w+打开文件,以便以二进制格式编写数据

然后您可以使用fwrite()直接以二进制形式写入数据,以便稍后由fread()读取。

答案 2 :(得分:0)

C不支持通用,除非在void *我认为, 我一直在研究一个让C变得有点通用的小项目。 您可以通过设置该类型的一个参数来执行您想要的操作 对于字符串说0 和1表示整数

然后创建一个if-else语句,然后单独使用printf。

    int print (FILE f,void*x,int type)
    {
        if(type==0)
            return fprintf(f,"%s",(char*)x);
        else
            return fprintf(f,"%d",*(int*)x);
    }

答案 3 :(得分:0)

可以尝试以下内容:

在编写

时使用struct了解数据类型
typedef enum { String, Int, Char} datatype;
struct record{
  datatype dt;
  void* data;
};

int myfprintf(FILE* stream, struct record* rec){  

  switch(rec->dt){
     case Char:     return fprintf(stream, "%c", *((char*)(rec->data)));
     case Int:      return fprintf(stream, "%d", *((int*)rec->data));        
     case String:   return fprintf(stream, "%s", (char*)rec->data);     
     //....     
     default:       return fprintf(stream,"%s", "Error");
  }                                
} 

然后使用myprintf传递流和类型record

的数据

或者,您也可以以类似的方式使用union

使用C11,您可以执行以下操作: - (取自here):

#define printf_dec_format(x) _Generic((x), \
    char: "%c", \
    signed char: "%hhd", \
    unsigned char: "%hhu", \
    signed short: "%hd", \
    unsigned short: "%hu", \
    signed int: "%d", \
    unsigned int: "%u", \
    long int: "%ld", \
    unsigned long int: "%lu", \
    long long int: "%lld", \
    unsigned long long int: "%llu", \
    float: "%f", \
    double: "%f", \
    long double: "%Lf", \
    char *: "%s", \
    void *: "%p")

 #define fprint(stream, x) fprintf(stream,printf_dec_format(x), x)


 fprint(stdin,(char *)"P0W"); // for string literal

答案 4 :(得分:0)

C没有通用数据类型,因此必须创建一个。

typedef enum {
  Generic_int, Generic_float, Generic_double, Generic_string
} Generic_Type;

typedef struct {
  Generic_Type type;
  union {
    int i;
    float f;
    double d;
    char *s;
  // other types
  } u;
} Generic;

void Generic_printf(Generic *G) {
  switch (G->type) {
    case Generic_int:
      printf("%d", G->u.i);
      break;
    case Generic_float:
      printf("%.*e", FLT_DECIMAL_DIG, G->u.f);
      break;
    case Generic_double:
      printf("%.*e", DBL_DECIMAL_DIG, G->u.d);
      break;
    case Generic_string:
      printf("\"%s\"", G->u.s);  // Enclose string in quotes
      break;
      // other
  }
}