フォーマットI/O(一般的なsprintfとsscanfのまとめ)

15845 ワード

1.出力のフォーマット
#include 
int printf(const char *restrict format, ...);
int fprintf(FILE *restrict fp, const char *restrict format, ...);
int dprintf(int fd, const char *restrict format, ...);
int sprintf(char *restrict buf, const char *restrict format, ...);
int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);
  • printfはフォーマットデータを標準出力に書き、fprintfは指定ストリームに書き、dprintfは指定ファイル記述子に書く.
  • sprintfはフォーマット文字を配列bufに書き込む.sprintfは、配列の末尾にnullバイトを自動的に追加しますが、この文字は戻り値に含まれません.sprintf関数はbufが指すバッファのオーバーフローをもたらす可能性があります.呼び出し者は、バッファが十分大きいことを確認する責任があります.バッファオーバーフローは、プログラムの不安定性やセキュリティ上の危険性をもたらすため、このバッファオーバーフローの問題を解決するためにsnprintf関数を導入します.
  • snprintf関数では、バッファ長は明示的なパラメータであり、バッファの末尾に書かれたすべての文字が破棄されます.バッファが十分大きい場合、snprintfは最後のnullバイトを含まないバッファに書き込まれた文字数を返します.snprintf関数がバッファ長より小さい正の値を返すと、出力は遮断されません.負の値を返すと、エンコーディングエラーが発生したことを示します.

  • フォーマットは、残りのパラメータの作成方法と表示方法を制御します.各パラメータは変換の説明に従って作成され、変換の説明はパーセントで開始されます.変換の説明には、次の4つのオプションがあります.
    %[flag][fldwidth][precision][lenmodifier]convtype

    flag:
    ひょうしき
    説明

    (アポストロフィ)整数を千単位でグループ化する文字
    -
    フィールド内で出力を左揃え
    +
    記号付き変換の正負記号を常に表示
    (スペース)
    最初の文字が正負でない場合は、その前にスペースを追加します.
    #
    別の変換形式を指定
    0
    スペースではなく先頭0を追加
    fldwidth:最小フィールド幅precisionの説明:整数変換後の最小出力デジタルビット数、浮動小数点数変換後の最小ビット数、文字列変換後の最大バイト数を説明します.精度は1点(.)で、その後、オプションの非負の10進数またはアスタリスク(*)に従います.convtype:
    変換タイプ
    説明
    d、i
    符号付き10進法
    o
    符号なし8進法
    u
    符号なし10進法
    x、X
    符号なし16進法
    f、F
    デュアル精度浮動小数点数
    e、E
    指数形式の二重精度浮動小数点数
    g、G
    変換後の値からf,F,e,Eと解釈する
    a、A
    16進数指数フォーマットデュアル精度浮動小数点数
    c
    文字
    s
    文字列
    p
    voidへのポインタ
    n
    これまでprintf呼び出し出力の文字数は、ポインタが指す符号付き整数に書き込まれる
    %
    %文字
    C
    ワイド文字
    S
    ワイド文字列
    sprintfはよく使われる出力関数の一つで、使い方は以下の通りです.
    a.デジタル文字列sprintfをフォーマットする最も一般的なアプリケーションの1つは、整数を文字列に印刷することであるため、spritnfはitoaの代わりに多くの場合に使用することができる.次のようになります.
    //   123           s 。
    sprintf(s, "%d", 123);   // "123"
    //      ,        :
    sprintf(s, "%8d%8d", 123, 4567); // "     123    4567"
    //        :
    sprintf(s, "%-8d%8d", 123, 4567); // "123    4567"
    //     16    :
    sprintf(s, "%8x", 4567); //  16  ,   8   ,   
    sprintf(s, "%-8X", 4568); //  16  ,   8   ,   

    b.浮動小数点数印刷フォーマットを制御し、デフォルトでは小数点以下6桁を保持する
    sprintf(s, "%f", 3.1415926);    // "3.141593"

    ただし、印刷の幅と小数点以下の桁数を自分で制御したい場合は、"%m.nf"形式を使用します.ここで、mは印刷の幅を表し、nは小数点以下の桁数を表します.例:
    sprintf(s, "%10.3f", 3.1415626);   // "     3.142"
    sprintf(s, "%-10.3f", 3.1415626);  // "3.142     "
    sprintf(s, "%.3f", 3.1415626);     // "3.142"

    次のコードの場合:
    int i = 123sprintf(s, "%.3f", i);

    その結果は何ですか.“0.000”.. なぜなら、パラメータスタックの場合、呼び出し元はiに対応するフォーマット制御子が「%f」であることを知らないからである.関数実行時に関数自体がスタックに押し込まれた整数であることを知らず、整数iを保存した4バイトが浮動小数点数フォーマットとして解釈され、エラーが発生した
    sprintf(s, "%.3f", (float)i);     //     "123.000"

    c.sprintfの戻り値を利用する
    たとえば、次のコードは、10個の[000]の乱数を生成し、カンマで区切られた配列に出力します.
    #include 
    #include 
    #include 
    
    int main() {
        srand(time(0));
        char s[64];
        int offset = 0;
        for (int i = 0; i < 10; i++) {
            offset += sprintf(s + offset, "%d,", rand() % 100);
        }
        s[offset - 1] = '
    '
    ;// 。 printf(s); return 0; }

    2.フォーマット入力
    #include 
    int scanf(const char *restrict format, ...);
    int fscanf(FILE *restrict fp, const char *restrict format, ...);
    int sscanf(const char *restrict buf, const char *restrict format, ...);

    scanfファミリー関数は、入力文字列を解析し、文字シーケンスを指定したタイプの変数に変換するために使用されます.フォーマット後の各パラメータには変数のアドレスが含まれており、変換結果でこれらの変数に値を割り当てます.
    フォーマットは、パラメータを変換して値を割り当てる方法を制御します.変換の説明はパーセントで始まり、変換の説明と空白の文字を除いて、フォーマット文字列の他の文字は入力と一致しなければならない.1つの文字が一致しない場合は、後続の処理を停止し、入力の他の部分を読み出さない.
    変換の説明には、次の3つの選択肢があります.
    % [*][fldwidth][m][lenmodifier]convtype

    ここで、変換を抑制するために選択可能なアスタリスク(*)が使用されます.変換の説明の残りの部分に従って入力を変換しますが、変換結果はパラメータに保存されません.
    fldwidthは最大幅(すなわち最大文字数)を示し、lenmodifierは変換結果で割り当てるパラメータサイズを示します.
    convtypeフィールドはprintfファミリーの変換タイプフィールドに似ていますが、両者の間にはまだ違いがあります.1つの違いは、入力中に記号付きの符号なしタイプを付与できるオプションとして使用されます.
    フィールド幅と長さ修飾子の間のオプションmは、%c、%sおよび%[変換子は、変換文字列を受け入れるためにメモリバッファにスペースを割り当てるように強制します.この場合、関連パラメータはポインタアドレスでなければなりません.割り当てられたバッファアドレスはポインタにコピーする必要があります.呼び出しが成功した場合、バッファが使用されなくなった場合、呼び出し者はfree関数を呼び出してバッファを解放します.
    変換タイプ
    説明
    d
    符号付き10進数、基数10
    i
    符号付き10進法、基数は入力フォーマットで決定
    o
    符号なし8進法(オプションで記号を入力)
    u
    符号なし10進数、基数10(任意で符号を入力)
    x、X
    符号なし16進法(入力はオプションで符号付き)
    a、A、e、E、f、F、g、G
    浮動小数点数
    c
    文字(長さ修飾子lが付いている場合、幅文字)
    s
    文字列(長さ修飾子lが付いている場合、幅文字列)
    [
    リストされた文字列を一致させ、「終了」
    [^
    リストされた文字以外のすべての文字を一致させ、「終了」
    p
    voidへのポインタ
    n
    これまでprintf呼び出し出力の文字数は、ポインタが指す符号付き整数に書き込まれる
    %
    %文字
    C
    ワイド文字
    S
    ワイド文字列
    sscanfはscanfと同様に入力に用いられるが,後者はスクリーン(stdin)を入力源とし,前者は固定文字列を入力源とする.formatは1つ以上です.
    {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '
    '
    | % }

    注意:
    1.*        , (  %*d   %*s)      (*)           . (             ) 
    2.{a|b|c}  a,b,c   ,[d],     d     d。 
    3.width      。 
    4.{h | l | I64 | L}:   size,  h     size,I  2   size,L  4  size(double  ),l64  8  size5.type :%s,%d6.%*[width] [{h | l | I64 | L}]type             ,            

    集合アクションをサポートするには、次の手順に従います.
    %[a-z]     a z     ,   (       ) 
    %[aB']   a、B、'   ,    
    %[^a]    a

    sscanfの使い方:
    a.よくある使い方
    char buf[512]; 
    sscanf("123456 ", "%s", buf); 
    printf("%s
    "
    , buf)
    ; // "123456"

    b.指定された長さの文字列をとります.次の例では、最大4バイトの文字列をとります.
    sscanf("123456 ", "%4s", buf); 
    printf("%s
    "
    , buf); // "1234"

    c.指定文字までの文字列をとります.次の例では、スペースに遭遇するまで文字列を取ります.
    sscanf("123456 abcdedf", "%[^ ]", buf); 
    printf("%s
    "
    , buf); // "123456"

    d.指定した文字セットのみを含む文字列をとります.次の例では、1~9と小文字のみを含む文字列をとります.
    sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf); 
    printf("%s
    "
    , buf); // "123456abcdedf" char s[] = "abcdef 1987:10:20"; char buf[512]; sscanf(s, "%[a-z0-9, ,:]", buf); // "abcdef 1987:10:20"

    e.指定した文字セットまでの文字列をとります.次の例では、大文字に遭遇するまでの文字列をとります.
    sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf); 
    printf("%s
    "
    , buf); // "123456abcdedf"

    f.指定文字列"iios/12DDWDFF@122」と、/と@の文字列を取得し、「iios/」をフィルタリングしてから、「@」以外の一連の内容をbufに送ります.
    sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); 
    printf("%s
    "
    , buf); // "12DDWDFF"

    g.worldのみを保持する文字列「hello,world」を指定します.(注:「,」の後にスペースがあります)
    sscanf(“hello, world”, "%*s%s", buf); //%*s         %s    , hello    ,          NULL。
    printf("%s
    "
    , buf); // "world"

    h.文字列の各数字を各変数に抽出する
    int a, b, c; 
    sscanf("2016:04:21", "%d:%d:%d", a, b, c);  // a=2016, b=4, c=21
    char sztime1[16] = "", sztime2[16] = ""; 
    sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2); 

    読み出された文字列がスペースで区切られていない場合は、%[]を使用します.%[]正規表現に似ています.[a-z]はa-zを読み出すすべての文字を表し、[^a-z]はa-zを除くすべての文字を読み出すことを表す.上記の書き方は、
    sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2); 

    sscanfの機能は正規表現に似ていますが、正規表現が強くないので、複雑な文字列処理の場合は正規表現を使用することをお勧めします.