web-dev-qa-db-ja.com

プログラムは、scanf( "%c"、&yn);を使用したユーザー入力を待機しません。

これは、Cでファイルを使用する練習をするために作成しているプログラムの基本的なコードです。出力ファイルが既に存在するかどうかを検出しようとしています。存在する場合は、上書きするかどうかをユーザーに確認します。これが、私が最初にoutfilenameファイルをfopen(outfilename、 "r");で開いた理由です。 fopen(outfilename、 "w");とは対照的です。

ファイルが存在しない場合を検出しますが、存在する場合はprintf( "出力ファイルは既に存在します、上書き(y/n):");を実行します。ステートメントですが、scanf( "%c"、&yn);を完全に無視します。ステートメント!

プログラムの最後にあるprintfは、ファイルが存在しない場合は「yn = 0」を読み取り、ファイルが存在する場合は「yn =」を読み取ります。誰か助けてもらえますか?

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

int main(void) {
    FILE *inf;
    FILE *outf;
    char filename[21],outfilename[21];
    char yn='0';

    printf("Please enter an input filename: ");
    scanf("%s",&filename);

    printf("Please enter an output filename: ");    
    scanf("%s",&outfilename);

    /* Open file for reading */
    inf=fopen (filename,"r");
    outf=fopen(outfilename,"r");

    /*check that input file exists*/
    if (inf!=NULL) {

        /*check that the output file doesn't already exist*/
        if (outf==NULL){
            fclose(outf);
            /*if it doesn't already exist create file by opening in "write" mode*/
            outf=fopen(outfilename,"w");
        } else {
            /*If the file does exist, give the option to overwrite or not*/
            printf("Output file already exists, overwrite (y/n):");
            scanf("%c",&yn);
        }
    }
    printf("\n yn=%c \n",yn);
    return 0;
}
8
user1083734
_printf("Please enter an output filename: ");    
scanf("%s",&outfilename);
_

2番目の文字列を入力してENTERキーを押すと、文字列と文字が入力バッファに配置されます。つまり、入力された文字列と改行文字です。文字列はscanfによって消費されますが、改行は入力バッファに残ります。

さらに、

_scanf("%c",&yn);
_

文字を読み取るための次のscanfは、改行を読み取る/消費するだけなので、ユーザー入力を待つことはありません。

解決策は、次を使用して余分な改行を消費することです。

_scanf(" %c", &yn);
      ^^^   <------------Note the space
_

または、getchar()を使用します

問題の詳細なステップバイステップの説明については、私の答えここを確認することをお勧めします。

29
Alok Save

使用する

scanf("%20s",&filename);

stdinはラインバッファリングされており、Linuxでは tty の規律に従っていることを忘れないでください

より詳細な制御が必要な場合は、 GNU readline または ncurses を使用できます。

scanf("%s", ...)は、\ n入力の行を終了します。 scanf( "%s"、...)は白をスキップすることから始まるため、次の問題は発生していません。 scanf("%c", ...)はそうではないので、_\n_を読みます。

ところで、おそらく他の問題に遭遇するでしょう。ファイル名にスペースを入れて(_%s_はそれらを読み取らない)、長すぎる名前を入力した場合(%sには入力長の制限がありません)。

あなたが不満を言った問題の1つの解決策(他の問題ではない)は、スキップすることから始まるscanf(" %c", ...)(_%c_?scanfの前のスペースを参照)を使用することです。空白。

0
AProgrammer
scanf("%s",&filename);

&も削除します

scanf.c:13:警告:フォーマット '%s'はタイプ 'char 'を予期しますが、引数2のタイプは 'char()[20u]'です。

0
Chris

私が見つけたこの問題を処理するためのより良い方法は ここで説明 です。

入力を処理する別の方法を使用することをお勧めし、非常によく説明されています。

私は常にこの関数を使用してユーザー入力を取得します。


char * read_line (char * buf, size_t length) {
    /**** Copyright de home.datacomm.ch/t_wolf/tw/c/getting_input.html#skip
    Read at most 'length'-1 characters from the file 'f' into
    'buf' and zero-terminate this character sequence. If the
    line contains more characters, discard the rest.
    */
    char *p;
    if ((p = fgets (buf, length, stdin))) {
        size_t last = strlen (buf) - 1;
        if (buf[last] == '\n') {
            /**** Discard the trailing newline */
            buf[last] = '\0';
        } else {
            /**** There's no newline in the buffer, therefore there must be
            more characters on that line: discard them!
            */
            fscanf (stdin, "%*[^\n]");
            /**** And also discard the newline... */
            (void) fgetc (stdin);
        } /* end if */
    } /* end if */
    return p;
} /* end read_line */

古い答え

私はこのルールでこの種の問題を修正しました:

// first I get what I want.
c = getchar();
// but after any user input I clear the input buffer
// until the \n character:
while (getchar() != '\n');
// this also discard any extra (unexpected) character.

入力後にこれを行えば問題ありません。

0
eloyesp