Generic argument for fprintf in C

倾然丶 夕夏残阳落幕 提交于 2019-12-12 18:20:05

问题


I am writing a function that saves data to a file in C, making use of the fprintf function. However, this requires a placeholder as one of its arguments. For example: %s for strings, %d for integers... What should I do if the data type is generic, that is, the programmer using this function can set the data type of the variable I am writing to the file to anything he wants? Thanks!


回答1:


you can open your file with the w+ inorder to write your data in binary format

Then you can use fwrite() to write data directly in binary form, intended to be read by fread() later.




回答2:


Since the type of the data is known only at run-time, you will have to:

  • generate the format string used by the fprintf function at run-time, or

  • choose between multiple harcoded format strings to pass to fprintf.

The choice between these two options could depend on how many different types you have to deal with, and/or how you know at run-time the type of your placeholder argument.




回答3:


Can try something like following :

Use a struct to know type of data while writing

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");
  }                                
} 

Then use myprintf passing the stream and the data of type record

Alternatively you can use a union too in similar fashion

With C11 you can do following :- (taken from 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:


C not supported generic except in void* I think , I've been working on a small project that make C a little bit Generic .. you can do what you want by set one of the arguments for the type say 0 for string and 1 for integers

then make an if-else statement then use printf for each one alone .

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



回答5:


C does not have a generic data type, so one must be created.

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
  }
}


来源:https://stackoverflow.com/questions/20871314/generic-argument-for-fprintf-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!