web-dev-qa-db-ja.com

sscanfでスペースを含む文字列を読み取る

プロジェクトでは、文字列からintと文字列を読み取ろうとしています。唯一の問題は、sscanfがスペースを見たときに%sの読み取りを中断するように見えることです。とにかくこの制限を回避する方法はありますか?ここに私がやろうとしていることの例があります:

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv) {
    int age;
    char* buffer;
    buffer = malloc(200 * sizeof(char));
    sscanf("19 cool kid", "%d %s", &age, buffer);

    printf("%s is %d years old\n", buffer, age);
    return 0;
}

それが印刷するものは、「クールな子供は19歳」が必要な「クールな子供は19歳」です。誰もこれを修正する方法を知っていますか?

37
SDLFunTimes

次の行は、数値(%d)タブまたは改行とは異なるものが続く(%[^\t\n])。

sscanf("19 cool kid", "%d %[^\t\n]", &age, buffer);
41
BrunoLM

%c変換指定子が必要です。これは、空白を特別に処理せずに文字のシーケンスを読み取るだけです。

%c指定子はヌルターミネータを書き込まないため、最初にバッファをゼロで埋める必要があることに注意してください。また、読み取る文字数を指定する必要があります(指定しない場合、デフォルトは1のみになります)。

memset(buffer, 0, 200);
sscanf("19 cool kid", "%d %199c", &age, buffer);
12
caf

文字列の最後までスキャンする(改行がある場合は改行を削除する)には、次を使用します。

_char *x = "19 cool kid";
sscanf (x, "%d %[^\n]", &age, buffer);
_

_%s_は空白以外の文字のみに一致し、最初に見つかった空白で停止するためです。 _%[^\n]_形式指定子は、指定された選択(改行)にない(_^_のため)すべての文字に一致します。つまり、他のすべての文字と一致します。


バッファに十分なスペースを割り当てて文字列を取得する必要があることに注意してください(特定のフィールド幅を使用する場合を除き、_scanf/fscanf_から離れる正当な理由)。

あなたはそれをすることができます:

_char *x = "19 cool kid";
char *buffer = malloc (strlen (x) + 1);
sscanf (x, "%d %[^\n]", &age, buffer);
_

(定義によりalways 1であるため、* sizeof(char)は必要ありません)。

8
paxdiablo

入力から末尾の文字列が必要なため、%n(これまでに消費された文字数)を使用して、末尾の文字列が始まる位置を取得できます。これにより、メモリコピーとバッファサイズの問題を回避できますが、コピーが必要な場合は明示的に行う必要があるかもしれません。

const char *input = "19  cool kid";
int age;
int nameStart = 0;
sscanf(input, "%d %n", &age, &nameStart);
printf("%s is %d years old\n", input + nameStart, age);

出力:

cool kid is 19 years old
2
ɲeuroburɳ