Is it possible to output routines that are printed in FILE * to build a string in C?

I have a bad opinion that the answer to this question is no, but I wanted to drop it there if anyone has smart ideas.

I have a set of output procedures that occupy a complex data structure and print it in text format. They have prototypes like:

void print_mystruct(struct mystruct *s, FILE *stream)

I wrote this so that I can get efficient, buffered output to the terminal, to a file, to the network, etc.

Unfortunately, I do not know, using the standard C99, that I can use the same procedures to create a string in memory.

So my questions are:

  • Is there any smart way that I can use the functions fputs (), fprintf (), etc. for output to a string?
  • , , , ? , , - vtable ( FILE *). vtable , , fwrite. printf.

?

EDIT: , fmemopen() POSIX.1-2008 (.: fmemopen()), , , man- GNU libc.

+3
4

. glibc- (linux) open_memstream/fmemopen, - .

- ., .

void print_mystruct(struct mystruct *s,FILE *f);

, ,

char *mystruct_2_str(struct mystruct *s);

( ), (snprintf ..), , FILE *

+1

FILE, ( POSIX) , fmemopen, . , fdopen - . . , EOF ; , .

+1

, FILE, , . .

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;

You can compile one of these structures yourself from the string buffer and pass it to your function, as well as create a stall function that frees memory.

The question is, what CRT library calls can you use in your version? Obviously, everything related to the file name will not be executed, since it does not exist. But you could probably use functions like fwrite and fread and fseek that will manipulate pointers and allocate more space if necessary.

0
source
#include <stdio.h>
#include <stdlib.h>

char* file_to_string(FILE *f, int *len) {
  if (fseek(f, 0, SEEK_END)) handle_error();
  int buflen = ftell(f);
  if (len) *len = buflen;
  char *buf = malloc(buflen + 1);
  buf[buflen] = '\0';
  rewind(f);
  size_t readlen = fread(buf, 1, buflen, f);
  if (readlen != buflen) handle_error();
  // in particular, note readlen might not equal buflen in the face of text-mode
  // conversions, but tmpfile() indicates binary-mode, so doesn't affect this
  // case
  return buf;
}

int main() {
  FILE *temp = tmpfile();

  // use FILE interface
  fputs("written to temporary file\n", temp);

  char *s = file_to_string(temp, NULL);
  // now you have contents as a string
  free(s);

  // can also rewind the FILE and process it incrementally, etc.

  return 0;
}
0
source

Source: https://habr.com/ru/post/1715043/


All Articles