web-dev-qa-db-ja.com

プリプロセッサトークンを文字列に変換します

プリプロセッサトークンを文字列に変換する方法を探しています。

具体的には、私はどこかに持っています:

#define MAX_LEN 16

バッファオーバーランを防ぐために使用したい:

char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);

私は同じことを達成するために他の方法を受け入れていますが、標準ライブラリのみです。

59
davenpcj

http://www.decompile.com/cpp/faq/file_and_line_error_string.htm を参照してください:

_#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
_

sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);を実行することで問題を解決できます

101
Dan

オンラインで答えを見つけました。

#define VERSION_MAJOR 4
#define VERSION_MINOR 47

#define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR

上記は機能しませんが、うまくいきたいと思います。つまり、VERSION_STRINGが「v4.47」になります。

適切な数値形式を生成するには、次のようなものを使用します

#define VERSION_MAJOR 4
#define VERSION_MINOR 47

#define STRINGIZE2(s) #s
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) \
"." STRINGIZE(VERSION_MINOR)

#include <stdio.h>
int main() {
    printf ("%s\n", VERSION_STRING);
    return 0;
}
21
davenpcj

しばらく経ちましたが、これはうまくいくはずです:

 sscanf(buf, "%" #MAX_LEN "s", val);

そうでない場合は、「二重展開」のトリックが必要です。

 #define STR1(x)  #x
 #define STR(x)  STR1(x)
 sscanf(buf, "%" STR(MAX_LEN) "s", val);
6
James Curran

二重拡張文字列化マクロトリックを使用する必要があります。またはただ持っている

#define MAX_LEN    16
#define MAX_LEN_S "16"

char val[MAX_LEN+1];
sscanf(buf, "%"MAX_LEN_S"s", val);

同期を保ちます。 (それは少し面倒ですが、定義が隣り合っている限り、おそらく覚えているでしょう。)

実際、この特定のケースでは、strncpyでは十分ではありませんか?

strncpy(val, buf, MAX_LEN);
val[MAX_LEN] = '\0';

ただし、printfの場合、これは簡単です。

sprintf(buf, "%.*s", MAX_LEN, val);
3
ephemient

上記の「機能」のいくつかは、個人的には、libcに付属するドレックの代わりに単純な文字列APIを使用することをお勧めします。いくつかのポータブルAPIがありますが、そのうちのいくつかはプロジェクトへの組み込みを容易にするために最適化されています... ustr などの小さなスペースオーバーヘッドがあり、スタック変数をサポートしています。

1
James Antill