FILE*로 인쇄하는 출력 루틴을 사용하여 C에서 문자열을 작성할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/1270212

  •  13-09-2019
  •  | 
  •  

문제

나는 이 질문에 대한 대답이 "아니오"라는 느낌이 좋지 않지만 누군가 기발한 아이디어가 있을 경우를 대비해 이 질문을 던져버리고 싶었습니다.

복잡한 데이터 구조를 가져와 텍스트 형식으로 인쇄하는 출력 루틴 세트가 있습니다.다음과 같은 프로토타입이 있습니다.

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

터미널, 파일, 네트워크 등으로 효율적이고 버퍼링된 출력을 얻을 수 있도록 이렇게 작성했습니다.

불행하게도 표준 C99를 사용하면 이와 동일한 루틴을 사용하여 메모리에 문자열을 작성할 수 있는 방법이 없습니다.

그래서 내 질문은 다음과 같습니다

  1. fputs(), fprintf() 등을 효율적으로 사용할 수 있는 영리한 방법이 있습니까?문자열로 출력하려면?
  2. 그렇지 않다면 버퍼링된 파일 출력과 문자열 작성을 모두 효율적으로 수행할 수 있는 더 나은 패러다임이 있습니까?내가 생각할 수 있는 최선의 방법은 (FILE* 대신) vtable을 사용하여 나만의 구조를 갖는 것입니다.vtable에는 문자열에 추가하거나 fwrite를 호출하는 출력 함수가 있습니다.하지만 그러면 printf 래퍼도 만들어야 합니다.

다른 기발한 아이디어는 없나요?

편집하다:나는 그것을 발견했다 fmemopen() POSIX.1-2008의 일부입니다(참조: fm메모리오픈()) 그러나 적어도 GNU libc 맨페이지에 따르면 널리 지원되지는 않습니다.

도움이 되었습니까?

해결책

이 작업을 수행하는 휴대용 방법은 없습니다. GLIBC 시스템 (LINUX) Open_Memstream/fmemopen , 다른 시스템에는 그와 비슷한 것이 없을 수 있습니다.

휴대용 방법은 파일에 쓰고 문자열로 다시 읽는 것입니다. 또는 우려 사항을 분리합니다. 구현 대신

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

당신은 예를 들어 구현할 것입니다

char *mystruct_2_str(struct mystruct *s);

문자열을 동적으로 할당하고 (또는 버퍼로 전달) 표준 문자열 함수 (snprintf 등)가있는 문자열로 형식화하고 발신자가 파일에 쓸 것인지 결정하도록합니다*

다른 팁

FILE 검색에 신경 쓰지 않는다면 이전의 모든 POSIX 대상에 대해 다음과 동일한 효과를 얻을 수 있는 이식 가능한 방법이 있습니다. fmemopen, 하지만 비용이 많이 듭니다.파이프와 새로운 분리된 스레드를 만들고, fdopen 호출 스레드에서 파이프의 쓰기 끝입니다.그런 다음 새 스레드는 파이프의 읽기 끝에서 읽고 데이터를 문자열 버퍼에 넣습니다.파이프에서 EOF를 얻을 때 새 스레드가 반환되도록 합니다.분리되어 있으므로 정리할 필요가 없습니다.

물론, 파일 구조물에 대한 마법의 것은 없지만, 내장 된 라이브러리 기능이 문자열 버퍼에서 하나를 생성하는 것을 모릅니다. 다음은 정의의 적어도 하나의 버전입니다.

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

스트링 버퍼에서 이러한 스트러크 중 하나를 스스로 제작하고 기능으로 전달할 수 있으며 메모리를 해제하는 눈물 다운 기능을 만들 수 있습니다.

문제는 버전에서 어떤 CRT 라이브러리 호출을 사용할 수 있습니까? 분명히 파일 이름이 없기 때문에 파일 이름을 언급하는 것은 실패합니다. 그러나 Fwrite 및 Fread 및 Fseek과 같은 기능을 사용할 수 있으며, 이는 포인터를 조작하고 필요한 경우 더 많은 공간을 할당 할 것입니다.

#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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top