質問

scanf()の使用方法を理解しようとして、多くの問題が発生しました。整数では問題なく動作するようで、かなり単純な scanf("%d&quot ;,& i)です。

問題に直面しているのは、入力を読み取ろうとするループで scanf()を使用していることです。例:

do {
  printf("counter: %d: ", counter);
  scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
  1. c P101 のような有効な構造化された入力を入力すると、プロンプトが表示される前に再びループするようです。これは、単一の場合でも発生するようです:

    scanf("%c", &c) 
    

    whileループ。もう一度プロンプトを表示する前に、ループを2回実行します。ループを2回ループさせているのは何ですか?どうすれば停止できますか?

  2. プログラムで q などの別の文字や数字を持たない少ない入力で入力すると、Enterキーを押すと、さらに入力するように促されるようです。 scanf()を取得して、1文字と2文字の両方のエントリを処理するにはどうすればよいですか?

役に立ちましたか?

解決

" c P101 "と入力すると、プログラムは実際に" c P101 \ n "を受け取ります。ほとんどの変換指定子は、改行を含む先頭の空白をスキップしますが、%c はスキップしません。 " \ n "までのすべてのことについて初めて" \ n"の周りの2回目の読み取り command に読み込まれ、" c " prefix に読み込まれ、" P "数字ではないため、変換は失敗し、" P101 \ n "ストリームに残ります。次回" P "コマンドに保存されます" 1 "はプレフィックスに格納され、 1 (残りの" 01 "から)は" \ n "とともに入力に格納されます。次回もストリーム上にあります。この問題を修正するには、書式文字列の先頭にスペースを入れて、改行を含む先頭の空白をスキップします。

" q "、" q \ n "を入力すると、2番目のケースでも同様のことが起こります。 " q "の前後で初めてストリームに入力されます。 " \ n "の2回目の読み取りが読み込まれます。3回目の呼び出しでのみ、2番目の" q "読み取り、フォーマット文字列の先頭にスペース文字を追加することにより、問題を再度回避できます。

これを行うより良い方法は、fgets()のようなものを使用して行を一度に処理し、sscanf()を使用して解析を行うことです。

他のヒント

本当に壊れています!知りませんでした

#include <stdio.h>

int main(void)
{
    int counter = 1;
    char command, prefix;
    int input;

    do 
    {
        printf("counter: %d: ", counter);
        scanf("%c %c%d", &command, &prefix, &input);
        printf("---%c %c%d---\n", command, prefix, input);
        counter++;
    } while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
 c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
 g3---

出力は、ロバートの答えに合っているようです。

行を含む文字列を取得したら。つまり、「C P101」、sscanfの解析機能を使用できます。

参照: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf。 html

質問1については、終了する&quot; \ n&quot;がないため、 printf()に問題があると思われます。

printf のデフォルトの動作は、出力が完全な行になるまで出力をバッファリングすることです。これは、 stdout のバッファリングを明示的に変更しない限りです。

質問2については、 scanf()で最も大きな問題の1つにぶつかりました。入力が指定したスキャン文字列と完全に一致しない限り、結果は期待したものとは異なります。

オプションがある場合は、 scanf()を無視して独自の解析を行うことで、より良い結果が得られます(そしてセキュリティ上の問題が少なくなります)。たとえば、 fgets()を使用して行全体を文字列に読み込んでから、文字列の個々のフィールドを処理します&#8212; sscanf()を使用することもできます。

おそらくdo ... whileループではなく、whileループを使用すると便利です。このようにして、コードの実行前に条件がテストされます。 次のコードスニペットを試してください。

 while(command != 'q')
    {
        //statements
    }

また、文字列の長さが事前にわかっている場合、「for」ループは「while」ループよりもはるかに簡単に処理できます。また、長さを動的に決定するためのトリッキーな方法もいくつかあります。

最終的な暴言として: scanf()は「吸い込み」ません。それがすることを行い、それがすべてです。 fgets()は非常に危険です(ただし、リスクのないアプリケーションには便利ですが)。入力のネイティブなチェックを行わないためです。これは、悪用のポイント、特にバッファオーバーフロー攻撃として非常に一般的に知られており、その変数に割り当てられていないレジスタのスペースを上書きします。したがって、それを使用することを選択した場合は、いくつかの確実なエラーチェック/修正を入れるのに時間を費やしてください。

あなたが今までにそれを処理していると思うので、これが将来誰かを助けることを願っています! ;)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top