Input after cin.getline() fails?
I am new to programming. In my textbook, the problem presented it to write a program that asks a user for the rainfall for three months and calculates the average.
I used the cin.getline() function to read the user input into an array. The text states that there is no worry of the array being overflowed using the cin.getline() function. However, if I enter a string larger than the array, my program goes haywire. Why does this happen?
#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;
}
What happens is istream::getline reads up to the limit, then stops. You don't check if it finished by reading a newline, so when you go to read the double later, the stream's input contains characters that can't convert to a double: this puts the stream in a failed state.
Because you don't check if the input (into the double) succeeds, using that value results in undefined behavior. If you instead initialize your double (to avoid the UB), you'll find its value hasn't changed.
Though there are times when you want to use istream::getline, this isn't one of them: use std::string and 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;)
}
The only reason to use istream::getline is when you must limit possibly-malicious input from consuming too much memory; e.g. a 10 GB line. This isn't the case for simple examples and exercises.
It's because getline will read up to the size you specify (minus 1), and it leaves the remaining characters in the stream. When you use (>>) to extract the rainfall, since there are non numerical characters in the stream, cin errors. You need to account for that.
精彩评论