1

I'm having trouble converting a char buffer in a FILE* (if this is even possible, of course!). I have an enumeration defines as such:

typedef enum SchemaType{
 SCHEMA_INT,
 SCHEMA_REAL,
 SCHEMA_STRING,
 SCHEMA_BOOLEAN,
 SCHEMA_CHAR,
 SCHEMA_SIMPLE,
 SCHEMA_RECORD,
 SCHEMA_ARRAY
} SchemaType;

I have a perfectly functioning function that prints out the enumeration itself (for debugging purposes):

void printSchemaType(FILE* f,SchemaType schemaType){
 switch (schemaType){
  case SCHEMA_INT: fprintf(f,"int"); break;
  case SCHEMA_ARRAY: fprintf(f,"array"); break;
  case SCHEMA_BOOLEAN: fprintf(f,"boolean"); break;
  case SCHEMA_CHAR: fprintf(f,"char"); break;
  case SCHEMA_REAL: fprintf(f,"real"); break;
  case SCHEMA_RECORD: fprintf(f,"record"); break;
  case SCHEMA_STRING: fprintf(f,"string"); break;
 }
}

Now the problem: I need to use the string printed out by fprintf (i.e. "int", "char", "real", ex cetera) as key in an hashtable; for this purpose i would like to store the printed string of printSchemaType() inside a variable, maybe by using sprintf:

char buffer[25];
sprintf(buffer,"%s",printSchemaType_output);

The problem is that I need to get the function output inside a variable! I know I could:

  • create a new function storeSchemaTypeInsideBuffer(const char* buffer,SchemaType type); with a switch ... case but i would prefer not to because I don't want redundant code for a little thing like this;
  • change the prototype of "printSchemaType" into void printSchemaType(const char* buffer,SchemaType schemaType) but I would prefer not to because there are other functions like printSchemaType with a similar prototype (printTYPE(FILE* f, TYPE typevariable)) and changing its prototype would create a differentiation of prototypes between this only function and the other ones;

The solution I was thinking is to transform a char buffer into a FILE* variable: in this way I would be able to do something like this:

SchemaType=SCHEMA_INT;
char buffer[25];
FILE* bufferActingAsAFile=make_buffer_acts_as_a_File(buffer);
fprintf(bufferActingAsAFile,type); //now in the buffer there is stored "int"

Is something like this even possible in C? If yes, how can I do that?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Koldar
  • 1,317
  • 15
  • 35
  • 2
    You can either spend days coming up with some clever way to coerce your function output into a variable, or you can bite the bullet, spend 10 minutes writing your switch statement, and live with the inhumanity. – Robert Harvey Jul 10 '14 at 17:46
  • I don't understand why you can't just use the enumeration values themselves as keys rather than the string representation. – T.C. Jul 10 '14 at 17:46
  • @T.C.: Presumably the goal is to read something from the file, and act on it based on what type it is. A text to enumeration converter, in other words, and vice versa. It's a switch statement. – Robert Harvey Jul 10 '14 at 17:48
  • Also there's likely a large performance loss here, since `fprintf` needs to make lots of checks that `sprintf` doesn't. Microsoft's `sprintf` used to be implemented in terms of `fprintf`, and they saw a [8x performance gain](http://blogs.msdn.com/b/vcblog/archive/2014/06/10/the-great-crt-refactoring.aspx) when they stopped doing that. – T.C. Jul 10 '14 at 17:54
  • @T.C.: I didn't know about the performance loss caused by `fprintf`, but since this function should be called only once I can live with that (the others are for debugging purpose, so they should be used only in the development phase). As the "using of the actual values of the enumeration as key" question the sole use of the `SchemaType` is not enough to decrease collision inside the table; but your question gave me some rethought on my design, so thanks! – Koldar Jul 10 '14 at 18:13

2 Answers2

1

Not what you asked for, but I would rewrite your printSchemaType function.

Create a new function called SchemaTypeStr (or some other name that fits your naming scheme) like this:

const char* SchemaTypeStr(enum SchemaType type) {
    switch(type) {
        case SCHEMA_INT:     return "int"; break;
        case SCHEMA_ARRAY:   return "array"; break;
        case SCHEMA_BOOLEAN: return "boolean"; break;
        case SCHEMA_CHAR:    return "char"; break;
        case SCHEMA_REAL:    return "real"; break;
        case SCHEMA_RECORD:  return "record"; break;
        case SCHEMA_STRING:  return "string"; break;
        default: abort();
    }
}

void printSchemaType(FILE* f,SchemaType schemaType) {
    fputs(SchemaTypeStr(schemaType), f);
}
Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • This method is even better than `fmemopen()` one (no redundance and leaves the prototype intact) but sadly I have already accepted his answer **even** with my own comment. If there are no harsh feeling I will delete my previous comment and accept your answer. – Koldar Jul 10 '14 at 18:26
0

There doesn't seem to be a portable solution. For linux, you can use fmemopen, but for Windows you'll need to use CreateFile, CreateFileMapping and MapViewOfFile.

See similar question here.

Community
  • 1
  • 1
user3820547
  • 359
  • 1
  • 5
  • `MapViewOfFile` isn't any help. It goes the wrong direction. It applies a memory-buffer interface on top of an existing file (mapping). On the other hand, `fmemopen` applies a file interface (specifically, `FILE*`) onto an existing memory buffer. – Rob Kennedy Sep 23 '14 at 17:27