-2

I'm trying to ask the user to input a number of objects, but the number of objects has to be between 1 and 10, and then add each object to an array. I have this so far:

void numObjects (void){
    int i;
    int numObjectsArr[10];
    cout << "Enter number of objects, ranging from 1 to 10 objects: ";
}
int main (int argc, char** argv){
    numObjects();
}

I know that I would need to use a for loop, but is there a way to make it so that each object (for the sake of simplicity, lets say they're balls) is it's own separate thing, and I'd be able to add more info on each specific ball? For example, what if I wanted to make it so that I could ask how much the ball at numObjectsArr[0] weights? I know how to ask the user for integers to put into an array, but I'm not quite sure how to implement this.

  • I suggest you to read good books on the topic. A fairly simple solution is to create a `Ball` class, and maintain a `vector` of its objects. – CinCout Feb 06 '19 at 06:02
  • A point to consider: After you have filled up `numObjectsArr` with values from the user, What are you going to do with it? You can't return it to the caller because the function returns `void`--nothing--and arrays cannot be returned. You can return a pointer to the array (`int * numObjects ()`), but the pointer will be rendered invalid when the array goes out of scope at the end of the function. To avoid this problem use a library container like `std::array` or `std::vector`. – user4581301 Feb 06 '19 at 06:18
  • @user4581301 I had thought that I would be able to create a function that got input from the user, put each object into an array, and then I'd be able to pass that array to another function that got other info about the object, like how much it weighs. – user2348258 Feb 06 '19 at 06:25
  • That can be done, but once you have all of this information you'll have a problem handing it off to whatever's doing the processing unless `numObjects` does this as well. In that case take care to not pack too much responsibility into a single function. It makes debugging much harder. – user4581301 Feb 06 '19 at 06:30
  • @user4581301 Okay, makes sense. On another topic, let's say that I asked a user to enter the number of objects, and there can be no more than 10 objects. I had already initialized the array to 10 elements. But what if they said that they had 5 objects instead? – user2348258 Feb 06 '19 at 06:55

2 Answers2

0

As already mentioned, you should probably read some tutorials on C++ (specifically classes and std::vector). But to give you an idea how such a program could look like:

#include <iostream>
#include <vector>

class Ball
{
    public:
        double weight;
};

Ball create_ball()
{
     std::cout << "Enter weight: ";

     double new_weight = 0.;
     std::cin >> new_weight;

     Ball b;
     b.weight = new_weight;
     return b;
}

std::vector<Ball> create_objects(int min = 1, int max = 10)
{
    std::vector<Ball> balls;

    std::cout << "Enter number of balls: " << std::endl;

    int n_balls = 0;

    std::cin >> n_balls;

    if (n_balls < min || n_balls > max)
    {
        std::cout << "Invalid numer of balls!" << std::endl;
        // here should be a proper error handling;
        // preferably by throwing an exception
        // But for simplicity the empty vector is returned

        return balls;
    }

    for (int i=0; i<n_balls; i++)
    {
         Ball new_ball = create_ball(); // create a new Ball object
         balls.push_back(new_ball); // add the new object to the vector.
    }

    return balls;
}

int main()
{
    std::vector<Ball> balls = create_objects(1, 10);

    for (int i=0; i<balls.size(); i++)
    {
         std::cout << "Ball " << i << ": weight: " << balls[i].weight << std::endl;
    }

}

Think of a std::vector as a array with dynamic size, i.e., everytime a new object is added to the vector by its method push_back the size of the vector is increased. Thus, using a vector allows your program to run propperly for any number of objects somebody wants to enter. You could even remove the checks on the minimum and maximum number of objects.

AchimGuetlein
  • 501
  • 3
  • 9
0

Arrays cannot be returned (they decay to a pointer and the array goes out of scope and becomes invalid before anyone can use the returned pointer) and cannot be assigned to a new array variable if you could return the array. This puts a serious damper on passing arrays around.

The modern solution is to use Library Containers such as std::array and std::vector. Sadly many introductory courses do not allow the student to use std::vector for good or ill, so the student has to find other ways to get the same effect.

So... You cannot return an array, but you can return a structure containing an array.

struct arrayholder
{
    int numObjectsArr[10];
    int used = 0; // Book keeping for much of the array is in use
}

Now we can

arrayholder numObjects ()
{
    int i;
    arrayholder Arr;
    cout << "Enter number of objects, ranging from 1 to 10 objects: ";

    return Arr
}

This doesn't do anything useful yet, but at least we can get the array out of the function. There is a downside to this, returning the structure by value means the structure will be copied. Fortunately any decent compiler today will support Copy Elision and silently save you all the extra overhead.

How do we get data into the array?

arrayholder numObjects ()
{
    int i;
    arrayholder Arr;
    cout << "Enter number of objects, ranging from 1 to 10 objects: ";
    while (!(cin >> Arr.used)) // keep asking for a number until we get a number
    {
        // didn't get a number. This sets an error flag that needs to be cleared
        cin.clear(); 
        //throw out the bad input
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
    // note: the above is about the minimum you want to use for input validation.
    // there are a bunch pf potential problems with it, like allowing crap like "8foo foo"
    // add logic to keep nagging the users until they give a number from 1 to 10
    // I'm not writing this because it's the crux of the assignment.

    for (int index = 0; index < Arr.used; index++)
    {
        while (!(cin >> Arr.numObjectsArr[index])) 
        {
            cin.clear(); 
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
    }
    return Arr;
}

See that horrible block of repeated code? It's a perfect candidate to be replaced with a function.

int getNumber()
{
    int num;
    while (!(cin >> num)) 
    {
        cin.clear(); 
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
    return num;
} 

arrayholder numObjects ()
{
    int i;
    arrayholder Arr;
    cout << "Enter number of objects, ranging from 1 to 10 objects: ";
    Arr.used = getNumber();
    // add logic to keep nagging the users until they give a number from 1 to 10
    // I'm still not writing this because it's the crux of the assignment, but 
    // getNumber just made it a lot easier to write.

    for (int index = 0; index < Arr.used; index++)
    {
        Arr.numObjectsArr[index] = getNumber();
    }
    return Arr;
}
user4581301
  • 33,082
  • 7
  • 33
  • 54