7

マニュアルページには、の署名sscanf

sscanf(const char *restrict s, const char *restrict format, ...);

入力が整数かどうかをチェックするためにこのように関数が使用されているSO に関する回答を見てきました。sscanf

bool is_int(char const* s) {
    int n;
    int i;
    return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}

これを見ると、文字列が終端文字までスキャンされている!s[n]かどうかを確認することが示唆されているようです。したがって、関数が終了したときにsscanf が文字列に含まれるインデックスを表すと仮定します。sscanf\0ns

しかし、変数はiどうですか?どういう意味ですか?

編集:

より明確に言うと、最初のパラメーターとしてsscanf型のポインターを望んでいるという署名が表示されます。char *文字シーケンスを解析する方法と、変換指定子と同じ数の変数を次のパラメーターとして認識できるように、seconf パラメーターとしての書式指定子。i解析された整数を保持するためのものであることがわかりました。

書式指定子が 1 つしかないので、 の機能を推測してみましたn

上記の私の仮定はn正しいですか?

4

4 に答える 4

10

op はすでに答えを持っているように見えますが、自分でこれを調べてコードを実行するのが面倒だったので...

「C The Pocket Reference」(Herbert Shildt による第 2 版) からの scanf() セクション:

%n これまでに読み取った文字数に等しい値の整数を受け取ります

戻り値の場合:

scanf() 関数は、値が正常に割り当てられたフィールドの数に等しい数を返します。

sscanf() 関数も同じように機能します。指定されたバッファ引数 (この場合は s ) から入力を受け取るだけです。「== 1」テストは、1 つの整数のみが解析されたことを確認し、!s[n] は、解析された整数の後に入力バッファーが適切に終了していること、および/または文字列に実際に整数が 1 つしかないことを確認します。

このコードを実行すると、"32" のような s 値は "true" 値を返します (私たちのシステムでは型として bool が定義されていません) が、s が "3 2" であるため、s[n] は "false" 値を返します。その場合は「2」で、n の値は 2 です (「3」は解析されて int が作成されます)。s が " 3 " の場合、空白はすべて無視され、n の値は 3 であるため、この関数は true を返します。

別の入力例「3m」では、予想どおり「false」の値が返されます。

于 2012-11-02T17:57:41.813 に答える
4

sscanf()のmanページからの逐語的:

コンバージョン

[...]

n

何も期待されていません。代わりに、入力からこれまでに消費された文字数は、int へのポインターである必要がある次のポインターを介して格納されます。これは変換ではありませんが、* 割り当て抑制文字で抑制することができます。C 標準では、「%n ディレクティブを実行しても、実行の完了時に返される割り当てカウントはインクリメントされません」とありますが、正誤表はこれと矛盾しているようです。おそらく、%n 変換が戻り値に与える影響について、何も仮定しない方が賢明です。

于 2012-11-02T17:13:54.277 に答える
1

元のコードにはバグがあることを指摘したいと思います。

bool is_int(char const* s) {
    int n;
    int i;
    return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
} 

その理由を説明します。そして、sscanf フォーマット文字列を解釈します。

まず、バギー:

整数 1 である入力 "1" を指定すると、sscanf は 1 を i に格納します。すると、後ろに空白がないので、sscanf は n に触れません。そして n は初期化されていません。sscanf は i を 1 に設定するため、sscanf によって返される値は 1 になり、1 つのフィールドがスキャンされたことを意味します。sscanf は 1 を返すため、式の一部

sscanf(s, "%d %n", &i, &n) == 1

真になります。したがって、&& 式の他の部分が実行されます。n は初期化されていないため、s[n] はメモリ内のランダムな場所にアクセスします。

フォーマットの解釈:

"%d %n"

10 進数、整数、または科学表記法番号の可能性がある数値のスキャンを試みます。数値は整数で、その後に少なくとも 1 つの空白が必要です。空白は、スペース、\n、\t、およびその他の特定の印刷できない文字になります。空白が続く場合にのみ、空白を含むその時点までにスキャンされた文字数を n に設定します。

このコードは、意図したものである可能性があります。

    static bool is_int(char const* s) 
    {
        int i;
        int fld;
        return (fld = sscanf(s, "%i", &i)) == 1;
    }

    int main(int argc, char * argv[])
    {
        bool ans = false;

        ans = is_int("1");
        ans = is_int("m");

        return 0;
    }

このコードは、s が整数の場合、sscanf はそれをスキャンし、fld は正確に 1 になることに基づいています。s が整数でない場合、fld は 0 または -1 になります。単語など、何か他のものがある場合はゼロ。空の文字列以外に何もない場合は -1。

于 2015-02-12T03:54:10.150 に答える
0

変数iは、整数値を読み取るまで意味します。

あなたは何を尋ねようとしていますか?あまりにも明確ではありません!コードは文字列から 'i' に整数を (しようと) 読み込みます

于 2012-11-02T16:53:37.063 に答える