简体   繁体   中英

How to return an array from a function in c++

Hello I am attempting to get data from an input file and have that placed in an array. I was able to complete my one function and have the array return as shown below:

string * animal_name_grab() 
{
        static string animal_name[SIZE];
        int cntr = 0;
        static string line_skip[SIZE];
    while (!input_animals.eof())
    {
        getline(input_animals, animal_name[cntr]);
        getline(input_animals, line_skip[cntr]);
        cntr++;
    }
    return (animal_name);
}

Now I am attempting to do the same thing, but add up the sum of the digits. Which I don't see exactly what is wrong with it. I did my function call the exact same way I did the previous one, but I am inserting it too just in case. Declared double *array_animal_total; Function call - array_animal_total = animal_total_grab();

double * animal_total_grab()
{
        static double animal_total[SIZE];
        static string line_skip[SIZE];
        int cntr = 0;
        double sum = 0;
        double total_count;
    while (!input_animals.eof())
    {
        getline(input_animals, line_skip[cntr]);

            for ( int i ; i < 10 ; i++)
            {
            input_animals >> total_count;
            sum = sum + total_count;    
            }
        animal_total[cntr] = sum;

        cntr++;
    }
    return (animal_total);
}

Please advise me if this is too much code to enter on here so I can edit it. I just wanted it to be proven that I understand the material, I just am having a bit of trouble. I am a beginner, so please be nice.

I was able to complete my one function and have the array return as shown below:

 string * animal_name_grab()

You aren't returning an array. You are returning a pointer. The pointer points to an element of an array.

How to return an array from a function in c++

It is in fact impossible to directly return an array from a function in C++. However, it is possible to return an instance of a class, and classes can have array members, so if you wrap the array inside a class, then you can return that wrapper object. There is a standard template for such array wrapper class. Its name is std::array . Example:

std::array<std::string, SIZE> animal_name_grab()
{
    std::array<std::string, SIZE> animal_name;
    ...
    return animal_name;
}

Note that copying large arrays is potentially slow, and you'd be relying on compiler optimisation to avoid copying the return value. It is sometimes more efficient, and often more flexible to use an output iterator instead of returning an array.

You asked for suggestions, so there you are: If you want to make your code more C++-like and modern, consider using a std::array or std::vector instead of a raw array. This allows you to use STL_functions like:

std::for_each(vector.begin(), vector.end(), [&] (int n) {
sum_of_elems += n;
});

To get the sum of the elements. You can return vectors but i would recommend you to first create the vector and then pass it by reference.

std::vector<std::string> input;
input.reserve(approxSpace); // Not necessary
getInput(&input); // Fill vector in external function

Also avoid using "magic numbers" like 10 in you case. If your projects get bigger it makes it way harder to change things without breaking the code.

You could break it down and define your own types for animal and an animal_collection and add some functions to use them like you wish. You obviously want to read an animal from a stream so let's create a function for that. You also want to read a whole collection of animal s so let's add a function for that.

Walkthrough:

#include <iostream>
#include <vector>  // std::vector - a dynamically growing container
                   //               that you can store objects in
#include <sstream> // std::istringstream for demo purposes

// A type to store the characteristics of an animal in. Let's start with a name.
struct animal {
    std::string name;
};

// A function to read one "animal" from std::cin or some other istream.
//
// It's functions like these that makes "cin >> variable;" work in your everyday program.
std::istream& operator>>(std::istream& is, animal& a) {
    std::getline(is, a.name);
    return is;
}

// A function to write one "animal" to std::cout or some other ostream.
std::ostream& operator<<(std::ostream& os, const animal& a) {
    return os << a.name;
}

// A collection of animals.
struct animal_collection {
    // std::vector - This std::vector stores objects of the type "animal".
    //               It has a lot of good features and is often prefered as a container
    //               when the exact number of elements to store is unknown.
    std::vector<animal> creatures;

    // return the number of "animal" objects there are in this "animal_collection"
    size_t size() const { return creatures.size(); }

    // iterator support functions so that you can loop over an animal_collection.
    // In this case, they are mearly proxy functions for the functions in std::vector
    // that we need exposed.

    // const iterators
    auto cbegin() const { return creatures.cbegin(); }
    auto cend() const { return creatures.cend(); }

    auto begin() const { return cbegin(); }
    auto end() const { return cend(); }

    // non-const iterators
    auto begin() { return creatures.begin(); }
    auto end() { return creatures.end(); }
};

// A function to read one "animal_collection" from std::cin or some other istream,
// like a file / ifstream.
std::istream& operator>>(std::istream& is, animal_collection& ac) {
    animal tmp;
    while(is >> tmp) { // use operator>> for "animal"
        // push_back() is a function in std::vector. Since this vector stores "animal"
        // objects and "tmp" is an "animal" object, this works:
        ac.creatures.push_back(tmp);
    }
    return is;
}

// A function to write one "animal_collection" to std::cout or some other ostream,
// like a file / ifstream.
std::ostream& operator<<(std::ostream& os, const animal_collection& ac) {
    // use the iterator support functions added to the "animal_collection" type
    // and loop over all the animal objects inside
    for(const animal& a : ac) {
        os << a << '\n'; // use operator<< that was added for "animal"
    }
    return os;
}

// using the two types created above
int main() {
    std::istringstream cin(
        "Tiger\n"
        "Lion\n"
        "Zebra\n"
        "Dalek\n");

    animal_collection ac;

    // read all "animal" objects into the "animal_collection"
    //
    // emulating reading animals from cin - replace with any istream,
    // like an open file

    cin >> ac; // use operator>> defined for "animal_collection"

    // use the size() function in the "animal_collection":
    std::cout << "there are " << ac.size() << " animal(s):\n";

    // output the whole "animal_collection"
    std::cout << ac;
}

When you need to add characteristics to animal you will only need to change what's relevant for that type. The animal_collection will not need changes. The std::vector<animal> inside the animal_collection has a lot of other nice functions that you can also expose via proxy functions just as size() and the begin() / end() family of functions.

If you don't want to use anything from the std library you can always just declare the array on the heap so it wont get destructed when you return.

For example:

double * func(){
   double * someArray = new double[3]; //declaring 'someArray' on the heap

   for(int i = 0; i < 3; i++)   //Filling the array with data
      someArray[i] = i;         //filling the array with data

   return someArray;            //since 'someArray' is on the heap it wont be destructed when you return
}

Although don't forget to delete the array after you are done with it.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM