Cでループを作成したいのですが、プログラムが整数を要求し、ユーザーが数字以外の文字を入力すると、プログラムは再び整数を要求します。
以下のコードを見つけました。しかし、これがscanf("%*[^\n]%*c")
の意味を理解できません。 ^\n
の意味? *
の前の^\n
とc
はどういう意味ですか?
/*
This program calculate the mean score of an user 4 individual scores,
and outputs the mean and a final grade
Input: score1, score2,score2, score3
Output: Mean, FinalGrade
*/
#include <stdio.h>
//#include <stdlib.h>
int main(void){
int userScore = 0; //Stores the scores that the user inputs
float meanValue = 0.0f; //Stores the user mean of all the notes
char testChar = 'f'; //Used to avoid that the code crashes
char grade = 'E'; //Stores the final
int i = 0; //Auxiliar used in the for statement
printf("\nWelcome to the program \n Tell me if Im clever enough! \n Designed for humans \n\n\n");
printf("Enter your 4 notes between 0 and 100 to calculate your course grade\n\n");
// Asks the 4 notes.
for ( ; i<=3 ; i++ ){
printf("Please, enter your score number %d: ", i+1);
//If the note is not valid, ask for it again
//This is tests if the user input is a valid integer.
if ( ( scanf("%d%c", &userScore, &testChar)!=2 || testChar!='\n')){
i-=1;
scanf("%*[^\n]%*c");
}else{ //Enter here if the user input is an integer
if ( userScore>=0 && userScore<=100 ){
//Add the value to the mean
meanValue += userScore;
}else{ //Enter here if the user input a non valid integer
i-=1;
//scanf("%*[^\n]%*c");
}
}
}
//Calculates the mean value of the 4 scores
meanValue = meanValue/4;
// Select your final grade according to the final mean
if (meanValue>= 90 && meanValue <=100){
grade = 'A';
} else if(meanValue>= 80 && meanValue <90){
grade = 'B';
} else if (meanValue>= 70 && meanValue <80){
grade = 'C';
} else if(meanValue>= 60 && meanValue <70){
grade = 'D';
}
printf("Your final score is: %2.2f --> %c \n\n" , meanValue, grade);
return 0;
}
scanf("%*[^\n]%*c")
の内訳:
%*[^\n]
は\n
まですべてをスキャンしますが、\n
はスキャンしません。アスタリスク(*
)は、スキャンされたものをすべて破棄するように指示します。%*c
は単一の文字をスキャンします。この場合、\n
が残した%*[^\n]
になります。アスタリスクは、スキャンされた文字を破棄するようにscanf
に指示します。%[
と%c
はどちらも形式指定子です。あなたは彼らが何をしているのか見ることができます ここ 。両方の指定子のアスタリスクは、scanf
にこれらの形式指定子によって読み取られたデータを格納しないように指示します。
@ chuxは以下でコメント のように、改行文字までのstdin
(標準入力ストリーム)の単一行をクリアします。あなたの場合、無効な入力のある行はstdin
からクリアされます。
使う方がいい
scanf("%*[^\n]");
scanf("%*c");
stdin
をクリアします。これは、前者の場合(単一のscanf
)、スキャンされる最初の文字が%*[^\n]
文字である場合に\n
が失敗し、scanf
の残りのフォーマット文字列がスキップされるためです。 %*c
は機能しないため、入力からの\n
は引き続き入力ストリームに存在します。この場合、最初のscanf
が失敗しても2番目のscanf
ステートメントが別々であるため、2つ目が実行されるため、これは発生しません。
scanf(“%s”, s)
を使用すると、Cで文字列を入力として取得できます。ただし、最初のスペースが見つかるまで、文字列を受け入れます。
入力として行を取得するには、scanf("%[^\n]%*c", s);
を使用できます。ここで、_char s[MAX_LEN]
_は_MAX_LEN
_はsの最大サイズです。ここで、_[]
_はスキャンセット文字です。
_^\n
_は、改行が検出されなくなるまで入力を取ることを意味します。
次に、この_%*c
_を使用して改行文字を読み取ります。ここで、使用された_*
_は、この改行文字が破棄されることを示しています。
また、注意:文字と文字列を入力した後、上記のステートメントによる文の入力は機能しません。これは、各行の終わりに改行文字_\n
_が存在するためです。したがって、最後のステートメントは前の行から改行文字を読み取るため、ステートメントscanf("%[^\n]%*c", s);
は機能しません。これはさまざまな方法で処理でき、その1つは次のとおりです。最後のステートメントの前のscanf("\n");
。
scanf(“%s”, s)
を使用すると、Cで文字列を入力として取得できます。ただし、最初のスペースが見つかるまで、文字列を受け入れます。
入力として行を取得するには、scanf("%[^\n]%*c", s);
を使用できます。ここで、s
は_char s[MAX_LEN]
_として定義されます。ここで、_MAX_LEN
_はs
の最大サイズです。ここで、_[]
_はスキャンセット文字です。 _^\n
_は、改行が検出されなくなるまで入力を取ることを意味します。次に、この_%*c
_を使用して改行文字を読み取ります。ここで、使用された_*
_は、この改行文字が破棄されることを示しています。
Char sen [max_length]で、最大長がsen []の最大サイズであるとします。
this scanf(“%[^\n]%* c”、&sen []);は、次の行が検出されなくなるまで文全体を取得するのに役立ちます“\n ”または“%[^\n]”ここで[]を使用してEnterキーを押すと、スキャンセット文字になります。 ”%* c”は改行文字を読み取り、アスタリスク” *”は次の行文字が破棄されることを示すために使用されます。
%[^\n]%*c
これは、改行まですべてを渡した文字列に読み込み、何も割り当てずに1文字(改行)を消費します(「*」は「割り当て抑制」です)。
それ以外の場合、改行は入力ストリームに残され、後続の%[^\n]
形式ディレクティブ。
フォーマットディレクティブにスペース文字を追加する際の問題(%[^\n]
)は、スペースが任意の空白と一致することです。したがって、前の入力の最後から改行を使用しますが、他の空白(複数の改行を含む)も使用します。