2016-12-21 12 views
0

Cでは、fscanf()は必ずしも最初のバイトからファイルを読み取るわけではありません。現在のアクセス位置からファイルを読み込みます。文字列と同じことを行うsscanf()のバージョンが必要です。この目的のために何らかの機能(標準または非標準)がありますか?最初のバイトから開始しないバージョンのsscanf()がありますか?

更新:私は質問をよくうかがいませんでした。私はこの種類のsscanf()がどこから読み始めなければならない場所/オフセットの数値を知らない。前回の呼び出しが終わった場所から読みたいと思っています。ありがとう。

+8

'sscanf(string、...)'の代わりに単に 'sscanf(string + n、...)'を使います。 'n'は望む開始位置です。 –

+0

私は 'n'、@MichaelWalzを持っていません。以前の呼び出しが終了した場所からsscanf()への新しい呼び出しを開始します。 – Arham

+2

なぜあなたはあなたの質問でこれを求めなかったのですか? –

答えて

0

この目的のための機能(標準または非標準)はありますか?

いいえ、ありません。あなたはあなたの文字列からどのくらいのオフセットを追跡し、sscanfを呼び出すときにそれを使用する必要があります。

sscanf(string + offset, ...); 

オフセットを追跡するために、あなたは sscanfはそれが消費どのように多くの文字を教えてできるように %n書式指定子を使用することができます。

int offset = 0; 
int n = 0; 
sscanf(string + offset, "....%n", ... &n); 
offset += n; 

... 

sscanf(string + offset, "....%n", ... &n); 
offset += n; 
0

Cの文字列には、外部からのアクセスを除いて、現在のアクセス位置の概念はありません。したがって、固有の現在のアクセス位置を考慮に入れたsscanf()の変種はありません。原則として、追加の引数として開始位置を受け入れるバリアントが存在する可能性がありますが、それは@MichaelWalzが観察するように、sscanf()自身でそれを行うためのルーチンポインタ演算を使用できるため、余分なものになります。次回そこから続けることができるように

+0

' sscanf() 'の変種は、' strtok() 'の働きに似た内部の静的変数を持つことができます。 – Barmar

7

は、単純なケースでは、あなたは今lengthは、文字列に「位置」を持つことになります。この

int x, y, length; 
if (sscanf(string, "%d%d%n", &x, &y, &length) == 2) ... 

のように、そのため"%n"指定子を使用することができます

if (sscanf(string + length, "%d%d%n", &x, &y, &length) == 2) ... 

さらに複雑なケースでは、sscanf()以上のものが必要な場合があります。また、プラットフォームに応じて、fmemopen(3)があるので、fscanf()のような文字列を持ちながら、それがファイルであるかのように文字列をやりとりします。

+1

'if(sscanf(string、"%d%dXYZ%n "、&x、&y、&length)== 2)'を考えてみましょう。この方法は、 'length'が設定されていないため動作しません。 – chux

+1

@chux変換がすべて成功しなかった場合は、途中で中断していた場所を続けるのは意味がありませんので、それは問題です。 – Barmar

+0

@barmar 2つのコンバージョンは 'if(sscanf(" 123 456 "、"%d%dXYZ%n "、&x、&y、&length)== 2)'で成功することができますが、 'length'は変更されず、 UBにつながる可能性があります。 'sscanf()'の戻り値のテストは、指定された文字の後にテキストをマッチングさせる必要がある場合には十分ではありません。 'length'を初期化し、変更されたかどうかテストすると、' sscanf() 'で十分です。 – chux

0

"%nを使用すると、前の部分スキャンが終了した場所からの文字列のスキャンを処理する通常の方法です。"%n"は、そのポイントまでのスキャンのオフセットを記録します。

これをフォーマットの末尾に追加し、インデックス値が-1から変更されたかどうかをテストします。これは、シンプルで複雑なフォーマットで使用できます。

int scanf_buffer_2_step(const char * buffer) { 
    int i; 
    double d; 

    // Initialize to a value that a successful scan would never use. 
    int n = -1; 

    // append    vv  vv 
    sscanf(buffer, "Index:%d,%n", &i, &n); 

    // Test for success 
    if (n < 0) return 1; // fail 

    // Advance pointer to next string position 
    buffer += n; 

    // Do it some more  
    n = -1; 
    sscanf(buffer, " Data:%lf End of the line %n", &d, &n); 
    if (n < 0) return 1; // fail 
    buffer += n; // Advance pointer to next string position 

    if (buffer[0] != '\0') return 1; // fail (extra data) 

    printf("(%i %f)", i, d); 
    return 0; 
} 

int main(void) { 
    printf("%d\n", scanf_buffer_2_step("Index:1, Data:123.456 End of the line")); 
    printf("%d\n", scanf_buffer_2_step("Index:1, Data:123.456 End of the line extra")); 
    printf("%d\n", scanf_buffer_2_step("Index:1,")); 
    return 0; 
} 

最終スキャン用の出力

(1 123.456000)0 
1 
1 

'\n'は、文字列の最後に許可されているように、" %n"空白であれば追加することを検討してください。

fscanf()の場合は、戻り値をEOFにチェックするような問題が発生します。

関連する問題