sasquatch90
sasquatch90

Reputation: 123

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.

Upvotes: 1

Views: 3315

Answers (8)

user113476
user113476

Reputation:

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.

Upvotes: 0

Pete Kirkham
Pete Kirkham

Reputation: 49311

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;
}

Upvotes: 1

Lucas
Lucas

Reputation: 14129

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;
}

Upvotes: 0

Potatoswatter
Potatoswatter

Reputation: 137800

#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;
}

Upvotes: 1

Void - Othman
Void - Othman

Reputation: 3481

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.

Upvotes: 0

Thomas Matthews
Thomas Matthews

Reputation: 57678

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.

Upvotes: 0

wallyk
wallyk

Reputation: 57774

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.

Upvotes: 1

Paul R
Paul R

Reputation: 212959

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.

Upvotes: 5

Related Questions