質問
scanf()
の使用方法を理解しようとして、多くの問題が発生しました。整数では問題なく動作するようで、かなり単純な scanf("%d&quot ;,& i)
です。
問題に直面しているのは、入力を読み取ろうとするループで scanf()
を使用していることです。例:
do {
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
-
c P101
のような有効な構造化された入力を入力すると、プロンプトが表示される前に再びループするようです。これは、単一の場合でも発生するようです:scanf("%c", &c)
whileループ。もう一度プロンプトを表示する前に、ループを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()
は非常に危険です(ただし、リスクのないアプリケーションには便利ですが)。入力のネイティブなチェックを行わないためです。これは、悪用のポイント、特にバッファオーバーフロー攻撃として非常に一般的に知られており、その変数に割り当てられていないレジスタのスペースを上書きします。したがって、それを使用することを選択した場合は、いくつかの確実なエラーチェック/修正を入れるのに時間を費やしてください。
あなたが今までにそれを処理していると思うので、これが将来誰かを助けることを願っています! ;)