views:

97

answers:

2

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;
}
+2  A: 

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.

PigBen
Thanks! so even though cin.getline() will stop reading at one less than my array size, the remaining characters are left in the keyboard buffer and errors the program out. Is that correct?
knobcreekman
@knobcreekman -- Yes, that is correct.
PigBen
cool, thanks. People are really quick to respond here. Hopefully one day I can be the one providing the answers :-)
knobcreekman
+2  A: 

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.

Roger Pate
thanks for the explanation. I appreciate it.
knobcreekman