0

私はプログラミングが初めてです。私の教科書では、ユーザーに 3 か月間の降雨量を尋ねて平均を計算するプログラムを作成する問題が提示されていました。

cin.getline() 関数を使用して、ユーザー入力を配列に読み込みました。テキストには、cin.getline() 関数を使用して配列がオーバーフローする心配はないと記載されています。ただし、配列よりも大きな文字列を入力すると、プログラムがうまくいかなくなります。なぜこれが起こるのですか?

#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
 const int SIZE = 10;
 char month1[SIZE], month2[SIZE], month3[SIZE];
 double rain1, rain2, rain3, average;

 cout << "Enter the name of the first month:  ";
 cin.getline(month1,SIZE);
 cout << "Enter the rainfall for " << month1 << ":  ";
 cin  >> rain1;
 cin.ignore();


 cout << "Enter the name of the second month:  ";
 cin.getline(month2,SIZE);
 cout << "Enter the rainfall for " << month2 << ":  " ;
 cin  >> rain2;
 cin.ignore();

 cout << "Enter the name of the third month:  ";
 cin.getline(month3,SIZE);
 cout << "Enter the rainfall for " << month3 << ":  ";
 cin  >> rain3;
 cin.ignore();

 average = (rain1 + rain2 + rain3)/3;

 cout << fixed << showpoint << setprecision(2) 
   << "The average rainfall for " << month1 << ", " << month2 
   << ", and " << month3 << " is " << average << " inches\n\n";


 return 0;
}
4

2 に答える 2

2

何が起こるかは、istream :: getlineが制限まで読み取り、その後停止します。改行を読み取って終了したかどうかを確認しないため、後でdoubleを読み取るときに、ストリームの入力にdoubleに変換できない文字が含まれています。これにより、ストリームが失敗状態になります。

(doubleへの)入力が成功したかどうかをチェックしないため、その値を使用すると未定義の動作になります。代わりに(UBを回避するために)doubleを初期化すると、その値が変更されていないことがわかります。

istream :: getlineを使用したい場合もありますが、これはその1つではありません。std::stringとstd:: getline:を使用してください。

std::string month1;
double rain1;

getline(std::cin, month1);
if (std::cin >> rain1) {
  // input succeeded, use month1 and rain1
}
else {
  // input of either month1 or rain1 failed; recover or bail (e.g. return 1;)
}

istream :: getlineを使用する唯一の理由は、悪意のある可能性のある入力がメモリを過剰に消費することを制限する必要がある場合です。たとえば、10GBの回線。これは、簡単な例や演習には当てはまりません。

于 2010-10-27T01:55:02.373 に答える
1

これは、getlineが指定したサイズ(マイナス1)まで読み取り、残りの文字をストリームに残すためです。(>>)を使用して降雨量を抽出すると、ストリームに数字以外の文字が含まれているため、cinエラーが発生します。あなたはそれを説明する必要があります。

于 2010-10-27T01:54:20.407 に答える