programing

sprintf()는 자동 메모리 할당 기능을 갖추고 있습니까?

firstcheck 2022. 7. 9. 09:33
반응형

sprintf()는 자동 메모리 할당 기능을 갖추고 있습니까?

필요한 메모리를 자동으로 할당하는 함수의 sprintf()와 같은 구현을 찾고 있습니다.그래서 나는 말하고 싶다.

char* my_str = dynamic_sprintf( "Hello %s, this is a %.*s nice %05d string", a, b, c, d );

my_str은 이 sprintf의 결과를 유지하는 할당된 메모리의 주소를 가져옵니다.

다른 포럼에서는 다음과 같이 해결할 수 있다고 읽었습니다.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
    char*   ret;
    char*   a = "Hello";
    char*   b = "World";
    int     c = 123;

    int     numbytes;

    numbytes = sprintf( (char*)NULL, "%s %d %s!", a, c, b );
    printf( "numbytes = %d", numbytes );

    ret = (char*)malloc( ( numbytes + 1 ) * sizeof( char ) );
    sprintf( ret, "%s %d %s!", a, c, b );

    printf( "ret = >%s<\n", ret );
    free( ret );

    return 0;
}

그러나 이로 인해 NULL 포인터를 가진 sprintf()가 호출되면 세그먼트 장애가 즉시 발생합니다.

아이디어, 솔루션 또는 팁이 있나요?퍼블릭 도메인에 배치되어 있는 sprintf()와 같은 파서의 작은 실장은 이미 필요 없습니다.그러면 제가 직접 할 수 있습니다.

정말 고마워.

다음은 Stack Overflow의 원본 답변입니다.다른 분들이 언급했듯이snprintfsprintf 두 꼭. 에 .snprintfzero ★★★★★★★★★★★★★★★★★★★★★.snprintfNULL첫 번째 인수인 문자열입니다.

한 이유는 두 번째 인수가 " "를 나타내기 입니다.snprintf출력 버퍼에 쓸 수 있는 충분한 공간이 없습니다. 할 수 snprintf사용 가능한 공간이 충분할 경우 썼을 바이트 수를 반환합니다.

이 링크에서 코드를 재생하는 중...

char* get_error_message(char const *msg) {
    size_t needed = snprintf(NULL, 0, "%s: %s (%d)", msg, strerror(errno), errno) + 1;
    char  *buffer = malloc(needed);
    sprintf(buffer, "%s: %s (%d)", msg, strerror(errno), errno);
    return buffer;
}

GNU와 BSD는 asprintf와vasprintf당신을 위해 설계된 것입니다.메모리 할당 방법을 알아보고 메모리 할당 오류 시 null을 반환합니다.

asprintf는 문자열 "배정"을 사용하여 합니다.먼저 사이즈를 측정하고 나서, 다음으로 로 할당을 시도합니다.malloc무효로 하다인 메모리 한, 「메모리 할당 시스템」의 하고 있는 는,malloc,asprintf그 일에 가장 적합한 도구입니다.

코드는 다음과 같습니다.

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
    char*   ret;
    char*   a = "Hello";
    char*   b = "World";
    int     c = 123;

    int err = asprintf(&ret, "%s %d %s!", a, c, b );
    if (err == -1) {
        fprintf(stderr, "Error in asprintf\n");
        return 1;
    }

    printf("ret = >%s<\n", ret);
    free(ret);

    return 0;
}

GNU/BSD 확장을 사용할 수 있는 경우 질문에 이미 답한 것입니다.하시면 됩니다.asprintf() (그리고)vasprintf()작성 래퍼 기능) 및 완료해야 합니다.

★★★★★★★★★★★★★★★★★.snprintf() ★★★★★★★★★★★★★★★★★」vsnprintf()는 POSIX에 manpage에, manpage를 하여 간단한 버전의 할 수 .asprintf() ★★★★★★★★★★★★★★★★★」vasprintf().

int
vasprintf(char **strp, const char *fmt, va_list ap)
{
    va_list ap1;
    int len;
    char *buffer;
    int res;

    va_copy(ap1, ap);
    len = vsnprintf(NULL, 0, fmt, ap1);

    if (len < 0)
        return len;

    va_end(ap1);
    buffer = malloc(len + 1);

    if (!buffer)
        return -1;

    res = vsnprintf(buffer, len + 1, fmt, ap);

    if (res < 0)
        free(buffer);
    else
        *strp = buffer;

    return res;
}

int
asprintf(char **strp, const char *fmt, ...)
{
    int error;
    va_list ap;

    va_start(ap, fmt);
    error = vasprintf(strp, fmt, ap);
    va_end(ap);

    return error;
}

일부 프리프로세서 매직은 실행할 수 있으며 해당 기능을 지원하지 않는 시스템에서만 사용할 수 있습니다.

  1. 가능한 경우, 공간을 할당할 수 있도록 생성되는 데이터의 크기를 쉽게 측정할 수 있습니다.
  2. 만약 그렇게 할 수 없다면, 또 다른 방법은 임시 파일로 인쇄하는 것입니다.fprintf크기를 가져오려면 메모리를 할당하고 sprintf를 사용합니다. snprintf확실히 권장되는 방법입니다.

GLib 라이브러리는 GLib에 대한 링크가 옵션인 경우 원하는 기능을 제공합니다.매뉴얼에서 다음 항목을 참조하십시오.

표준 C와 유사sprintf()필요한 최대 공간을 계산하고 결과를 저장하기 위해 메모리를 할당하기 때문에 더 안전합니다.반환된 문자열은 다음과 같이 해방됩니다.g_free()더 이상 필요하지 않을 때.

POSIX.1(IEEE 1003.1-2008)은 open_memstream을 제공합니다.

char *ptr;
size_t size;
FILE *f = open_memstream(&ptr, &size);
fprintf(f, "lots of stuff here\n");
fclose(f);
write(1, ptr, size); /* for example */
free(ptr);

open_memstream(3)은 적어도 Linux 및 MacOS에서 사용할 수 있으며 몇 년 동안 사용되었습니다.open_memstream(3)의 역수는 fmemopen(3)으로 버퍼의 내용을 읽을 수 있게 합니다.

sprintf(3)를 1개만 사용하고 싶은 경우는, 널리 실장되어 있습니다만, 표준이 아닌 asprintf(3)를 사용할 수 있습니다.

/*  casprintf print to allocated or reallocated string

char *aux = NULL;
casprintf(&aux,"first line\n");
casprintf(&aux,"seconde line\n");
printf(aux);
free(aux);
*/
int vcasprintf(char **strp,const char *fmt,va_list ap)
{
  int ret;
  char *strp1;
  char *result;
  if (*strp==NULL)
     return vasprintf(strp,fmt,ap);

  ret=vasprintf(&strp1,fmt,ap); // ret = strlen(strp1) or -1
  if (ret == -1 ) return ret;
  if (ret==0) {free(strp1);return strlen(*strp);}

  size_t len = strlen(*strp);
  *strp=realloc(*strp,len + ret +1);
  memcpy((*strp)+len,strp1,ret+1);
  free(strp1);
  return(len+ret);
}

int casprintf(char **strp, const char *fmt, ...)
{
 int ret;
 va_list ap;
 va_start(ap,fmt);
 ret =vcasprintf(strp,fmt,ap);
 va_end(ap);
 return(ret);
}

언급URL : https://stackoverflow.com/questions/3774417/sprintf-with-automatic-memory-allocation

반응형