4

Beez Cガイド (LINK)%[]がフォーマット指定子について語っていることは次のとおりです。

It allows you to specify a set of characters to be stored away (likely in an array of chars). Conversion stops when a character that is not in the set is matched.

この前提から生じるいくつかの基本的な質問を明確にしていただければ幸いです。

1)これらの 2 つの形式指定子によってフェッチされた入力はchar*、文字配列または\0終端文字 (文字列) を含む文字配列として (型の) 引数に格納されますか? 以下のプログラムのように、文字列を文字列としてフェッチし、特定の文字 (否定された文字セット内) に遭遇したときに停止したい場合、文字列ではない場合、文字列として格納するにはどうすればよいですか?

2)%[^|]私のプログラムは、否定された文字が検出されたときに指定子の処理が停止することを示唆している|ようです。を無視して|使用したため、%*c使用しましたが、テストしたところ%c、タイプの追加の引数を使用するとchar、文字|が実際にその引数に格納されることがわかりました。

3)そして最後に、私にとって非常に重要なことですが、%s書式指定子の文字配列を渡すことprintf()と文字列 (NULL で終了する文字配列)を渡すことの違いは何ですか? character array vs string) の%sフォーマット指定子printf()の場合、文字列と同じように出力されます。違いは何ですか?

//%[^] 指定子を説明するプログラム

#include<stdio.h>

int main()
{
char *ptr="fruit|apple|lemon",type[10],fruit1[10],fruit2[10];

sscanf(ptr, "%[^|]%*c%[^|]%*c%s", type,fruit1, fruit2);
printf("%s,%s,%s",type,fruit1,fruit2);
}

//文字配列 vs 文字列

#include<stdio.h>

int main()
{
char test[10]={'J','O','N'};
printf("%s",test);
}

出力 JON

//%*c の代わりに %c を使用

#include<stdio.h>

int main()
{
char *ptr="fruit|apple|lemon",type[10],fruit1[10],fruit2[10],char_var;

sscanf(ptr, "%[^|]%c%[^|]%*c%s", type,&char_var,fruit1, fruit2);
printf("%s,%s,%s,and the character is %c",type,fruit1,fruit2,char_var);

}

出力 fruit,apple,lemon,and the character is |

4

2 に答える 2

6
  1. null で終了します。sscanf()から:

    変換指定子 s および [は、一致した文字に加えて常にヌル ターミネータを格納します。宛先配列のサイズは、指定されたフィールド幅より少なくとも 1 つ大きくなければなりません。

  2. 除外された文字はスキャン セットによって消費されず、処理されたままになります。別の書式指定子:

    if (sscanf(ptr, "%9[^|]|%9[^|]|%9s", type,fruit1, fruit2) == 3)
    
  3. 残りの要素はゼロで初期化されるため、配列は実際には null で終了します。

    char test[10]={'J','O','N' /*,0,0,0,0,0,0,0*/ };
    

null で終了していない場合、メモリ内のどこかに null 文字が見つかるまで出力し続け、配列の末尾をオーバーランして未定義の動作を引き起こす可能性があります。null で終わらない配列を出力することが可能です:

    char buf[] = { 'a', 'b', 'c' };
    printf("%.*s", 3, buf);
于 2013-05-09T04:52:34.837 に答える
1

1) これらの 2 つの形式指定子によってフェッチされた入力は、(char* 型の) 引数に文字配列または \0 終端文字 (文字列) を持つ文字配列として格納されますか? 以下のプログラムのように、文字列を文字列としてフェッチし、特定の文字 (否定された文字セット内) に遭遇したときに停止したい場合、文字列ではない場合、文字列として格納するにはどうすればよいですか?

それらは、ASCIIZ 形式で保存されます - NUL/'\0' ターミネータを使用します。

2) 私のプログラムは、%[^|] 指定子の否定された文字 | しかし、次の書式指定子のために再び開始すると、以前に停止した否定された文字から開始されますか?私のプログラムでは、| を無視するつもりです。したがって、%*c を使用しましたが、テストしたところ、%c と char 型の追加引数を使用すると、文字 | 実際にその引数に格納されます。

次の文字を消費するべきではありません。あなたのコードを見せてください。

3) 最後に、私にとって非常に重要なことですが、printf() で %s 書式指定子に文字配列を渡すことと、文字列 (NULL で終了する文字配列) を渡すことの違いは何ですか?文字配列と文字列というタイトルの他のプログラムでは、I' printf() で %s 書式指定子に文字配列 (NULL で終了しない) を渡すと、文字列と同じように出力されます。違いは何ですか?

(編集:以下は上記の質問に対処します。これは一般的に配列の動作について話し、具体的にケースchar[10] = "abcd";を提起し、安全な質問のコードスニペットよりも広範です)

%sASCIIZ テキストへのポインターを渡す必要があります...そのテキストが明示的に char 配列にある場合でも、配列の長さではなく、テキストの内容を定義するのは NUL ターミネーターの必須の存在です。文字配列を NUL で終了する必要があります。そうしないと、動作が未定義になります。時々それでうまくいくかもしれません-例えば、配列へのstrncpyは、そうする余地がある場合にのみ、それをNULで終了し、静的配列はすべて0のコンテンツで始まるため、最後の文字の前にのみ上書きする場合は' ll には NUL があります。あなたの char[10] の例には、値が指定されていない要素に NUL が設定されていることがありますが、通常、何かが NUL 終了を保証していることを確認する責任を負う必要があります。

于 2013-05-09T04:55:35.850 に答える