C++ help

Started by
8 comments, last by Zahlman 19 years, 7 months ago
Ok, I am learning C++ by the book "C++ Primer Plus" by Stepen Prata (i'm reading it translated to swedish :P ) and i'm doing an exercise for a chapter. What I'm supposed to do is:
Quote:Write a program that reads up to ten donation amounts to an array of the type double. The program should cancel the input if a non-number is encountered. It should report the average of the amounts, and also how many amounts in the array who were bigger than the average.
So this is my code:

//This program will take ten donations and count the average.
//If the user enters a number, then it will stop asking for numbers.
//Also, it will count the average of all numbers until the letter, if entered.

#include <iostream>
#include <cctype>

using namespace std;

const int ArSize = 10;

int main(void)
{

	//Variables:
	double donation[ArSize];
	double average = 0;
	int size = 0;
	int index;
	int wrong;
	
	//Loop for entering:
	for (index = 0; index < ArSize; index++)
	{
		cout << "Write number " << index + 1 << '\n';
		cin >> donation[index];
		if (isalpha(donation[index]))
		{
			cin.clear();
			donation[index] = 0;
			wrong = index;
			break;
		}
	}

	//Loop for counting:
	for (index = 0; index < ArSize; index++)
	{
		if (index == wrong)
			break; 
		average = average + donation[index];
		size = index + 1;
	}

	//End:
	average = average / size;
	cout << "The average is " << average;
	return 0;
}

when i write like only numbers, it works correctly ( i know i havent written how many amounts that are bigger then the average, but i'm waiting with that :-P ), but when i enter a letter, it stops the input but still writes "write number " and then the number. and the average is something like this: -8.33037e+061 do you know what i'm doin wrong? by the way, I'm using Microsoft Visual C++ 6.0
Advertisement
You can't read a character into a double. If you want the user to be able to enter letters you should read the number into a std::string, and then, if the value entered really is a number, convert it to double with the atof function.

Or you could just exit on some input which is still double, but is invalid in this context (donations). -1, for example.
so was something wrong with the instructions? :/
Not really, but I think you interpreted them wrong. In order to check for a non-number you'd have to read the input to a text buffer, check if it's a number or not, and then copy the number to the double array (or exit, if the input isn't a number).
ah ok thanks, ill try that :D
Quote:
the number. and the average is something like this:
-8.33037e+061


this problem usually being encounter if you don't intialise your array double to something...... try the code below

//for the double type donation array//this code works for VS C++.Net 2002 edition and abovefor(int a = 0; a < Arsize; a++) {   donation[a] = 0.0; //or just 0}
:)
Muhahahaha! It worked!
ps. how do you make smileys? :-D
edit: btw, if i just make all donations 0.0, then i can't make the user input them right? it worked anyway now so thanks all!
Hey!

A perhaps cleaner way of doing that, or different at least is to check the cin call for failure:

if(!(cin >> donation[index]))
{
cin.clear();
}

This way allows the user to type in anything they want. You can also put that into a while loop so that it keeps asking the user for input until valid input is received. If you do that, you will also want to add a line to get rid of the remaining bad data in the stream before trying to read more:

while(cin.get()!='\n');

This keeps getting data from the stream until a new line is encountered.

Hope that helps, even though you've already received a solution!

-Jeremiah
Power User / Programmer / Game Player ( Not computer nerd :)
Thanks jerm, that was a good way to solve it. but it was not according to the instructions.
if (isalpha(donation[index])) <-- no good, it's too late for that. You have a 'double' variable (array slot), so you can't meaningfully check if it's alphabetic. What this is going to do is implicitly convert that double to int (by rounding), and then check whether the value of that int is in the ASCII range where the letters live (65-90 and 97-122, inclusive). o_O

You *do* want to check the input for failure, and skip over the bad input, just don't loop to insist on a new value:

if(!(cin >> donation[index])) {  // Oops, there's something at the beginning of the input stream  // which can't be interpreted as a double.  // First, make cin "recover" so that we can read more data  cin.clear();  // Skip past the garbage data, until a new line  cin.ignore(std::numeric_limits<INT_MAX>, '\n'); // <-- I think that's right...  // "Cancel the input" as you say  donation[index] = 0;  // In this case, the poster telling you to initialize the array  // is not on the right track; with this setup, something valid  // will get written to each array element.}


However, there's another logical problem with how you "cancel the input": the int "wrong" can only remember one "invalid" location. Also, "size" wants to count the valid entries - but even if the "wrong" setup worked, "size" gets set to one plus *the last valid entry*. You want to *increment* it for each valid entry. :/

Here's how I'd do it, in pseudocode. Translation is left as an exercise :)
size = 0repeat 10 times:  try to assign input to donation[size]  if successful: size = size + 1  otherwise: recover cin and ignore the input  # there is no longer a need for a "wrong" variable# After every iteration of the loop, "size" points at the first# slot that hasn't been written to yet, so you won't overwrite# things or skip array slots. It's also equal to the number of# assigned slots, so after the loop, it tells you how many slots# are assigned. This is why 0-based indexing is a Good Thing :)sum = 0# So now, we need to loop size-many times, to grab all the# assigned values, and add them up:repeat with i from 0 to (size - 1):  sum = sum + donation# and now that we have the sum, and number of elements,# getting the average is easy:print (sum / size)


P.S. Give variables names that describe their actual contents. Don't call something "average" if it's the sum. Call it "sum". I know your goal is to find the average, but you'll confuse yourself (and maybe forget to divide by number of elements?) that way... once you're doing more serious stuff, it's bound to happen... trust me. :)

This topic is closed to new replies.

Advertisement