简体   繁体   中英

Passing a dynamic array of structs c++

I need to read a .txt file and use the first number as the array size in a function called getData .

In my code, I am able to read the file and assign it to the array size as listSize . I am also able to fill the rest of the array with the .txt information. When I print out what is in my array WITHIN the getData function, it works.

The problem is that when I try to access the array outside of the getData function my program crashes. I am new to pointers, and c++ in general. I don't think I am passing it or calling it correctly. I have had a hard time finding information to assist me in the problem.

How can I access the arrays I created in getData ?

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

struct menuItemType
{
    string menuItem;
    double menuPrice;
};

void getData(int& listSize, menuItemType menuList[], int orderList[]);

int main()
{

    menuItemType *menuList = 0; //-----pointers
    int          *orderList = 0;
    int          listSize;

    getData(listSize, menuList, orderList);

    cout << menuList[0].menuItem;  //-----This is what crashes the program

    return 0;
}

//-----Get Menu Function
void getData(int& listSize, menuItemType menuList[], int orderList[])
{
    //-----Declare inFile
    ifstream inFile;
    string   price, size;

    //-----Open inFile
    inFile.open("Ch9_Ex5Data.txt");

    //-----Get Amount of Items, Convert to int
    getline(inFile, size);
    listSize = stoi(size);

    //-----Set Array Size
    menuList  = new menuItemType[listSize];
    orderList = new int[listSize];

    //-----Get Menu
    for (int x = 0; x < listSize; x++)
    {
        //-----Get menuItem
        getline(inFile, menuList[x].menuItem);

        //-----Get menuPrice convert to double
        getline(inFile, price);
        menuList[x].menuPrice = stod(price);
    }

    //------PRINT WORKS HERE ----- This print made me think i created the 
    //arrays correctly
    for (int x = 0; x < listSize; x++)
    {
        cout << menuList[x].menuItem << endl
            << menuList[x].menuPrice
            << endl;
    }

    inFile.close();
}

The contents of the .txt

8
Plain Egg
1.45
Bacon and Egg
2.45
Muffin
0.99
French Toast
1.99
Fruit Basket
2.49
Cereal
0.69
Coffee
0.50
Tea
0.75

Setting menuList and orderList in getData does not update the pointers in main . It would if you used references to pointers:

void getData(int& listSize, menuItemType*& menuList, int*& orderList);

Even better, use references to std::vector and quit mucking around with owning pointers and new and delete .

Let's Rewrite your code for a better C++ness, with explanations. :)

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

Don't do using namespace std just because you can type less things, namespaces helps you by telling you where this particular thing you invoked came from. if you really wanna write string instead of std::string, pull that particular thing, not the whole namespace, like this:

using std::string;

Your struct seems right, but you need to choose if your types will start with capitals or not, I always start my types with capitals but this is a choice:

struct MenuItemType
{
    string menuItem;
    double menuPrice;
};

Now, your getData should, well, get your data. so the type matters. your data is not 'void' as you declared, it's an array of MenuItemType, you can then declare them as vector and not even care about pointers.

Other thing: all of your parameters in getData shouldn't be parameters - they are all things that you would get from the text file that your program will parse, so the only thing that matters for the getData is the text file, so this is your variable.

std::vector<MenuItemType> getData(const std::string& textFile) 
{
    std::ifstream inFile;
    std::string   price, size, item;
    inFile.open(textFile);
    getline(inFile, size);
    int listSize = stoi(size);

    std::vector<MenuItemType> result;
    result.reserve(listSize);

    for (int x = 0; x < listSize; x++)
    {
        getline(inFile, item);
        getline(inFile, price);
        result.push_back(MenuItemType{item, stod(price)}); 
    }
    return result;
}

See how I didn't closed the file? It will be closed as soon as you leave the function, there's no need to call that unless you need the file to close before the function finishes.

Thumbs up rule: don't deal with pointers unless you have to.

As for your main function:

int main()
{
    std::vector<MenuItemType> menuList = getData("Ch9_Ex5Data.txt");
    cout << menuList[0].menuItem;
    return 0;
}

You could rewrite that in a faster way if you are sure what types are you using, the code above is equivalent to this one:

int main()
{
    auto menuList = getData("Ch9_Ex5Data.txt");
    cout << menuList[0].menuItem;
    return 0;
}

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