C 形式の文字列を作成する (出力しない)

sprintf を使用してください。

int sprintf ( char * str, const char * format, ... );

パラメータ:

str
format
... (additional arguments)

例:

// Allocates storage
char *hello_world = (char*)malloc(13 * sizeof(char));
// Prints "Hello world!" on hello_world
sprintf(hello_world, "%s %s!", "Hello", "world");

POSIX-2008 準拠のシステム (最新の Linux) を使用している場合は、安全で便利な asprintf() を使用できます。 関数:malloc() になります 十分なメモリがあれば、文字列の最大サイズを気にする必要はありません。次のように使用します:

char* string;
if(0 > asprintf(&string, "Formatting a number: %d\n", 42)) return error;
log_out(string);
free(string);

これは、文字列を安全な方法で構築するための最小限の労力です。 sprintf() 質問で提供したコードには重大な欠陥があります:

    <リ>

    ポインターの背後に割り当てられたメモリはありません。メモリ内のランダムな場所に文字列を書き込んでいます!

    <リ>

    あなたが書いたとしても

    char s[42];
    

    カッコに何を入れるか分からないので、あなたは深刻な問題に直面するでしょう.

    <リ>

    「安全な」バリアント snprintf() を使用したとしても 、文字列が切り捨てられる危険性が依然としてあります。ログ ファイルに書き込む場合、これは比較的小さな問題ですが、有用な情報を正確に切り取ってしまう可能性があります。また、末尾の行末文字が切り取られ、次のログ行が失敗した行の末尾に貼り付けられます。

    <リ>

    malloc() の組み合わせで使おうとすると および snprintf() すべてのケースで正しい動作を生成するには、asprintf() に指定したコードの約 2 倍のコードが必要になります。 、そして基本的に asprintf() の機能を再プログラムします .

log_out() のラッパーを提供することを検討している場合 printf() を取ることができます スタイル パラメータ リスト自体、バリアント vasprintf() を使用できます va_list を取る 引数として。以下は、そのようなラッパーの完全に安全な実装です:

//Tell gcc that we are defining a printf-style function so that it can do type checking.
//Obviously, this should go into a header.
void log_out_wrapper(const char *format, ...) __attribute__ ((format (printf, 1, 2)));

void log_out_wrapper(const char *format, ...) {
    char* string;
    va_list args;

    va_start(args, format);
    if(0 > vasprintf(&string, format, args)) string = NULL;    //this is for logging, so failed allocation is not fatal
    va_end(args);

    if(string) {
        log_out(string);
        free(string);
    } else {
        log_out("Error while logging a message: Memory allocation failed.\n");
    }
}

printf スタイルの書式設定を使用して作成された文字列を、単純な文字列を受け取る既に持っている関数に簡単に渡すことができるようにしたいように思えます。 stdarg.h を使用してラッパー関数を作成できます 施設と vsnprintf() (コンパイラ/プラットフォームによっては、すぐに利用できない場合があります):

#include <stdarg.h>
#include <stdio.h>

// a function that accepts a string:

void foo( char* s);

// You'd like to call a function that takes a format string 
//  and then calls foo():

void foofmt( char* fmt, ...)
{
    char buf[100];     // this should really be sized appropriately
                       // possibly in response to a call to vsnprintf()
    va_list vl;
    va_start(vl, fmt);

    vsnprintf( buf, sizeof( buf), fmt, vl);

    va_end( vl);

    foo( buf);
}



int main()
{
    int val = 42;

    foofmt( "Some value: %d\n", val);
    return 0;
}

snprintf() の適切な実装 (または任意の実装) を提供しないプラットフォームの場合 ルーチンのファミリ、私はほぼパブリック ドメインの snprintf() を使用することに成功しました ホルガー・ヴァイスより。