Simple average calculation
I'm trying to write program calculating average of given numbers stored in an array. Amount of numbers should be not more than 100, and user should input them until a !int variable is given :
#include <iostream>
#include <conio.h>
using namespace std;
double average(int tab[], int i){
int sum=0;
for(int j=0; j<i; ++j){
sum+=tab[j];
}
return (double)sum/i;
}
int main()
{
int tab[100];
int n=0;
int number=0;
do {
if(n < 100){
cout << "Give " << n+1 << " number : ";
cin >> number;
tab[n]=number;
number=0;
++n;
}
else{
break;
}
} while( !isdigit(number) );
cout << average(tab, n) << endl;
getch();
return 0;
}
Why after giving char, it prints me 'Give n number:' for all empty cells of my array ? It should开发者_运维知识库 end and use only given numbers.
You're using isdigit
incorrectly here - it's used to test whether a char
is numeric or not - you can't use it to test an int.
You probably want to consider using a special value to terminate input, e.g. -1
or -999
. If that's not acceptable then you'll need to read in a string rather than an int and then decide whether it's numeric or not.
isdigit
tests whether the character is a digit. The test is only reached following assigning 0 to number, and 0 is a control code, not a digit, so isdigit(0)
is always false, and so your while condition is always true.
...
number=0;
...
} while( !isdigit(number) );
Instead, test the input stream to determine whether it successfully read a value.
int main()
{
const size_t COUNT = 100;
int tab[COUNT];
size_t n;
cin.tie(&cout); // ensures cout flushed before cin read
// (not required if your runtime complies with that part of the standard)
for (n = 0; n < COUNT; ++n ) {
cout << "Give " << n+1 << " number : ";
cin >> tab[n];
if (!cin)
break;
}
if (n > 0) // average is undefined if n == 0
cout << average(tab, n) << endl;
return 0;
}
Besides the misuse of isdigit() which should instead use some sentinel mechanism, there's no need to store the numbers in an array. A running sum and a count of numbers is sufficient for calculating an average.
Also, there should be a check for zero elements entered to prevent a divide by zero error.
#include <iostream> // <conio.h> is nonstandard
using namespace std;
int main() {
long total = 0, cnt = 0, num;
while ( cerr << "Enter " << ++ cnt << " number" << endl, // use cerr for interaction
// use comma operator to produce a side effect in loop expression
cin >> num ) { // use Boolean value of (cin >> ...) to end loop on input failure
total += num; // just keep a running total
}
-- cnt; // cnt went one too far :(
cout << static_cast<double>( total ) / cnt << endl;
}
The better method for detecting the input of a non-number is to test the state of cin
after reading a value:
// ...
if (cin >> number)
{
tab[n++] = number;
}
else
{
break; // break out of loop
}
Also remember that there may be other reasons the input failed other than not inputting a valid number.
There are a few problems with your code:
cin >> number;
You don't check if the stream extraction operation failed. A simple way to do that is to leverage the operator void*()
conversion operator:
if (cin >> number)
... operation succeeded ...
The above code is equivalent to checking the failbit
and badbit
.
Your usage of isdigit()
is also wrong in that you're passing a number (e.g. 1234
of instead of a character (e.g. 'z'
). Regardless, adding a stream extraction operation failure check obviates the need for such a digit based check.
You could use lexical_cast
from boost. You read the input into a string and the lexical_cast will check if it can be converted into a string. This will also make sure that your string is not to long to be converted, if it is a negative number or a number at all.
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using boost::lexical_cast;
using boost::bad_lexical_cast;
double average(int tab[], int i){
int sum=0;
for(int j=0; j<i; ++j){
sum+=tab[j];
}
return (double)sum/i;
}
int main()
{
int tab[100]; //this is a fairly low level construct which might want to
// into a std::vector
string input;
int n;
try{
for (n = 0 ;n < 100; n++) {
cout << "Give " << n+1 << " number : ";
cin >> input; //read number into string
tab[n]= lexical_cast<int>(input); //conversion with lexical_cast
//if not possible exception is
//thrown
}
}
catch(bad_lexical_cast &){
cout << "not a number" << endl;
}
cout << average(tab, n) << endl;
return 0;
}
isdigit
will tell you if a character code of a character set represents one of the digits 0 - 9.
Therefore, (I'm assuming you are using ASCII), you could simply use a character and test its ASCII code range:
int tab[100];
int n = 0;
char c;
while (n++ < 100)
{
cout << "Give " << n << " number : ";
cin >> c;
if (c < 48 || c > 57)
break;
tab[n - 1] = c - 48;
}
cout << average(tab, n - 1) << endl;
getch();
return 0;
You could also use cin.getline
and atoi
or strtod
:
int tab[100];
int n=0;
int number=0;
char input[10];
while (n++ < 100)
{
cout << "Give " << n << " number : ";
memset(input, 0x00, 10);
cin.getline(input, 10);
number = atoi(input);
if (number > 0)
tab[n-1] = number;
else
break;
}
cout << average(tab, n-1) << endl;
getch();
return 0;
There are other methods you can use, however, these should give you some ideas.
精彩评论