なぜ使用するのですか:
1)cin.ignore
2)cin.clear
?
単に:
1)ストリームに不要な値を無視(抽出および破棄)する
2)ストリームの内部状態をクリアします。cin.clearを使用した後、内部状態は再びgoodbitに戻されます。これは、「エラー」がないことを意味します。
ロングバージョン:
'stream'(cin)に何かが置かれている場合は、そこから取得する必要があります。「取得」とは、「使用済み」、「削除済み」、「抽出済み」を意味します。ストリームには流れがあります。データは、ストリーム上の水のようにcin上を流れています。あなたは単に水の流れを止めることはできません;)
例を見てください:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
ユーザーが最初の質問に対して「ArkadiuszWlodarczyk」と答えるとどうなりますか?
プログラムを実行して、自分の目で確かめてください。
コンソール「Arkadiusz」に表示されますが、プログラムは「年齢」を要求しません。「アルカディウス」を印刷した直後に終了します。
また、「Wlodarczyk」は表示されていません。なくなったようです(?)*
どうした?;-)
「Arkadiusz」と「Wlodarczyk」の間にスペースがあるからです。
名前と姓の間の「スペース」文字は、「入力」ストリームで抽出されるのを待っている2つの変数があることを示すコンピューターの記号です。
コンピューターは、入力に複数の変数を送信しようとしていると見なします。その「スペース」サインは、彼がそれをそのように解釈するためのサインです。
したがって、コンピューターは「Arkadiusz」を「name」(2)に割り当て、ストリーム(入力)に複数の文字列を配置したため、コンピューターは値「Wlodarczyk」を変数「age」(!)に割り当てようとします。その命令はすでに実行されているため、ユーザーは6行目の「cin」に何も配置する機会がありません(!)。どうして?まだストリームに何かが残っていたからです。また、前に述べたように、ストリームはフロー内にあるため、すべてをできるだけ早く削除する必要があります。そして、その可能性は、コンピューターが命令cin >>年齢を見たときに来ました。
コンピューターは、誰かの年齢を格納する変数を作成したことを認識していません(4行目)。「年齢」は単なるラベルです。コンピュータの場合、「年齢」は「afsfasgfsagasggas」とも呼ばれ、同じになります。彼にとっては、(6)行でコンピューターにそうするように命令/指示したので、彼が「Wlodarczyk」を割り当てようとするのは単なる変数です。
そうするのは間違っていますが、それをしたのはあなたです!それはあなたの責任です!まあ、多分ユーザーですが、それでも...
大丈夫大丈夫。しかし、それを修正する方法は?!
いくつかの興味深いことを学ぶために適切に修正する前に、その例を少し試してみましょう:-)
私は物事を理解するアプローチをとることを好みます。どうやってやったのかわからないまま直しても満足できませんね。:)
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate();
上記のコードを呼び出すと、ストリームの状態(cin)が4に等しいことがわかります(7行目)。つまり、その内部状態はもはやgoodbitと等しくありません。何かがめちゃくちゃです。それはかなり明白ですよね?文字列型の値( "Wlodarczyk")をint型の変数 'age'に割り当てようとしました。タイプが一致しません。何かがおかしいことを知らせる時が来ました。そして、コンピュータはストリームの内部状態を変更することによってそれを行います。それは次のようなものです:「あなたは男をf ****します、私を直してください。私はあなたに「親切に」知らせます;-)」
'cin'(ストリーム)はもう使用できません。行き詰まっています。まるで大きな木の丸太を水流に置いたかのように。使用する前に修正する必要があります。木材のログ(内部状態)では取得できないため、そのストリーム(cin)からデータ(水)を取得できなくなりました。
ああ、障害物(木の丸太)がある場合は、そうするように作られたツールを使用してそれを取り除くことができますか?
はい!
cinの内部状態を4に設定すると、ハウリングして音を立てるアラームのようなものになります。
cin.clearは、状態をクリアして通常の状態に戻します(goodbit)。まるであなたが来て警報を消したかのようです。あなたはそれを延期するだけです。あなたは何かが起こったことを知っているので、あなたは言う:「音を立てるのをやめても大丈夫です、私は何かがすでに間違っていることを知っています、黙ってください(クリア)」。
大丈夫そうしましょう!cin.clear()を使用しましょう。
最初の入力として「ArkadiuszWlodarczyk」を使用して、以下のコードを呼び出します。
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;
cin.clear();
cout << cin.rdstate()<< endl;
上記のコードを実行した後、状態がgoodbitに等しいことが確実にわかります。
素晴らしいので、問題は解決しましたか?
最初の入力として「ArkadiuszWlodarczyk」を使用して、以下のコードを呼び出します。
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;;
cin.clear();
cout << cin.rdstate() << endl;
cin >> age;
9行目以降の状態がgoodbitに設定されていても、ユーザーは「年齢」を求められません。プログラムが停止します。
なぜ?!
ああ男...あなたはちょうど警報を延期しました、水中の木の丸太はどうですか?*私たちが「Wlodarczyk」について話したテキストに戻ってください。
その木片「Wlodarczyk」を小川から取り除く必要があります。アラームをオフにしても、問題はまったく解決しません。あなたはそれを沈黙させたばかりで、問題はなくなったと思いますか?;)
それで、別のツールの時間です:
cin.ignoreは、小川が詰まった木の丸太を取り除いて来るロープを備えた特別なトラックと比較することができます。それはあなたのプログラムのユーザーが作成した問題をクリアします。
では、アラームが鳴る前でも使えますか?
はい:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
cin >> age;
「Wlodarczyk」は、7行目でノイズを出す前に削除されます。
10000と '\ n'とは何ですか?
'\ n'が満たされるまで(念のため)10000文字を削除すると表示されます(ENTER)。ところで、numeric_limitsを使用するとより適切に実行できますが、この回答のトピックではありません。
したがって、問題の主な原因は、ノイズが発生する前になくなりました...
では、なぜ「クリア」が必要なのですか?
たとえば、6行目で「年齢を教えて」という質問を誰かが求めた場合はどうなりますか。たとえば、20を書く代わりに「20歳」です。
タイプが再び一致しません。コンピュータは文字列をintに割り当てようとします。そして、アラームが始まります。そのような状況に反応する機会すらありません。cin.ignoreは、そのような場合には役に立ちません。
したがって、次のような場合は、clearを使用する必要があります。
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
cin >> age;
cin.clear();
cin.ignore(10000, '\n');
しかし、「万が一に備えて」状態をクリアする必要がありますか?
もちろん違います。
何かがうまくいかない場合(cin >> age;)、命令はfalseを返すことによってそれについて通知します。
したがって、条件ステートメントを使用して、ユーザーがストリームに間違ったタイプを入力したかどうかを確認できます
int age;
if (cin >> age)
cout << "You put integer";
else
cout << "You bad boy! it was supposed to be int";
さて、たとえば次のような最初の問題を修正できます。
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
if (cin >> age)
cout << "Your age is equal to:" << endl;
else
{
cin.clear();
cin.ignore(10000, '\n');
cout << "Give me your age name as string I dare you";
cin >> age;
}
もちろん、これは、たとえば、loopwhileを使用して問題の操作を実行することで改善できます。
ボーナス:
あなたは不思議に思うかもしれません。ユーザーから同じ行に名前と姓を取得したい場合はどうなりますか?cinが「スペース」で区切られた各値を異なる変数として解釈する場合、cinを使用することも可能ですか?
もちろん、2つの方法で実行できます。
1)
string name, surname;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin >> surname;
cout << "Hello, " << name << " " << surname << endl;
2)またはgetline関数を使用します。
getline(cin, nameOfStringVariable);
そしてそれはそれを行う方法です:
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
2番目のオプションは、getlineの前に「cin」を使用した後に使用した場合に逆効果になる可能性があります。
それをチェックしよう:
a)
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
年齢として「20」を入力すると、nameAndSurnameの入力は求められません。
しかし、そのようにすると:
b)
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endll
すべて順調。
何?!
入力(ストリーム)に何かを置くたびに、最後にENTER( '\ n')の白い文字を残します。コンソールに値を入力する必要があります。したがって、データがユーザーからのものである場合に発生する必要があります。
b)cinの特性は、空白を無視することです。したがって、cinから情報を読み取る場合、改行文字 '\ n'は重要ではありません。無視されます。
a)getline関数は、改行文字( '\ n')までの行全体を取得します。改行文字が最初に取得される場合、getline関数は '\ n'を取得し、それだけで取得できます。3行目のストリームに「20」を入力したユーザーがストリームに残した改行文字を抽出します。
したがって、修正するには、常にcin.ignore();を呼び出す必要があります。プログラム内でgetline()を使用する場合は、cinを使用して値を取得するたびに。
したがって、適切なコードは次のようになります。
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cin.ignore();
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
ストリームがより明確になることを願っています。
黙ってください!:-)