简体   繁体   English

结构,数组和函数C ++

[英]Structs, Arrays, and Functions C++

I'm completely stuck on this assignment. 我完全坚持这个任务。 I first wrote everything in int main() without any issue. 我首先在int main()中写了所有内容,没有任何问题。 It all worked lovely! 这一切都很可爱! Unfortunately our instructor wants it split up into multiple functions (less than 35 lines per function). 不幸的是,我们的教练希望它分成多个功能(每个功能少于35行)。 I've split it up as you can see below but unfortunately my knowledge (and google hasn't been much help) of functions and passing/referencing through them is not that high. 我已将其分解,如下所示,但不幸的是,我的知识(和谷歌没有太多帮助)的功能和传递/参考通过它们并不是那么高。 My program doesn't work at all now. 我的程序现在根本不起作用。 All the 'Books' give errors so i'm not sure if I'm passing the struct or array improperly. 所有的“书籍”都会出错,所以我不确定我是否正在不正确地传递结构或数组。 Please help! 请帮忙!

The original txt file reads like: 原始的txt文件如下:

number of books
title
author
price
title
author
price

Code: 码:

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

using namespace std;

void setStruct() {

    struct bookTable {
        string title;
        string author;
        double price;
    };
}

void setArray(int &arraySize, struct bookTable *Book[]) {

    ifstream infile;
    int bookCounter = 0;

    infile.open("books2.txt");

    if (!infile) {
        cout << "Unable to open Books.txt" << endl;
    }

    infile >> arraySize;
    infile.ignore(100, '\n');

    bookTable *Book = new bookTable[arraySize];

    infile.close();
}

void readFile(struct bookTable *Book[]) {

    ifstream infile;
    int bookCounter = 0;

    infile.open("books2.txt");

    for (int i = 0; getline(infile, Book[i].title); i++) {

        getline(infile, Book[i].author, '\n');
        infile >> Book[i].price;
        infile.ignore(100, '\n');

        bookCounter++;
    }

    infile.close();
}

void displayMenu(struct bookTable *Book[]) {
    int menuChoice = 0, bookCounter = 0;
    string findTitle;

    do { cout << "\n===== Bookstore App =====" << endl; 
    cout << "1. Print Books" << endl; 
    cout << "2. Change Price" << endl;
    cout << "3. Quit" << endl; 
    cout << "\nEnter Choice: ";
        cin >> menuChoice;
        if (menuChoice == 1) {
            for (int i = 0; i < bookCounter; i++) {
                cout << "===== BOOK =====" << endl;
                cout << "Title: " << Book[i].title << endl;
                cout << "Author: " << Book[i].author << endl;
                cout << "Price: " << fixed << setprecision(2) << Book[i].price << endl; } }
        else if (menuChoice == 2) { cin.ignore(100, '\n');
            cout << "What is the title of the book? ";
            getline(cin, findTitle, '\n');
            for (int i = 0; i < bookCounter; i++) {
                if (findTitle == Book[i].title) {
                    cout << "Enter New Price: " << endl;
                    cin >> Book[i].price;
                }
                else if (findTitle != Book[i].title) {
                    cout << "Unable to find Book" << endl;
                }}}

        else if (menuChoice < 1 || menuChoice > 3) {

            cout << "Invalid Entry. Please enter 1, 2, or 3 from the options menu." << endl;
        }   } while (menuChoice != 3);
}

void writeFile(int arraySize, struct bookTable *Book[]) {

    ofstream outfile;
    int bookCounter = 0;

    outfile.open("sale2.txt");

    outfile << arraySize << endl;

    for (int i = 0; i < bookCounter; i++) {

        outfile << Book[i].title << endl;
        outfile << Book[i].author << endl;
        outfile << fixed << setprecision(2) << Book[i].price << endl;
    }

    outfile.close();

    delete[] Book;

}

int main() {

    setStruct();
    setArray();
    readFile();
    displayMenu();
    writeFile();

    cout << "\nSale2.txt has been created." << endl;

    return 0;
} 

I haven't compiled or run this, but hopefully it will get you started in the right direction: 我没有编译或运行它,但希望它能让你开始朝着正确的方向前进:

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

using namespace std;

// This declares "struct bookTable"
// You need to actually define a variable of this type later in your program
struct bookTable {
    string title;
    string author;
    double price;
};

bookTable * setArray(int &arraySize, struct bookTable *Book[]) {

    ifstream infile;
    int bookCounter = 0;

    infile.open("books2.txt");

    if (!infile) {
        cout << "Unable to open Books.txt" << endl;
    }

    infile >> arraySize;
    infile.ignore(100, '\n');

    bookTable *Book = new bookTable[arraySize];

    infile.close();

    // This returns an empty array of bookTable[]
    return Book;
}

void readFile(struct bookTable *Book) {

    ifstream infile;
    int bookCounter = 0;

    infile.open("books2.txt");

    for (int i = 0; getline(infile, Book[i].title); i++) {

        getline(infile, Book[i].author, '\n');
        infile >> Book[i].price;
        infile.ignore(100, '\n');

        bookCounter++;
    }

    infile.close();
}

void displayMenu(struct bookTable *Book[]) {
    int menuChoice = 0, bookCounter = 0;
    string findTitle;

    do { cout << "\n===== Bookstore App =====" << endl; 
    cout << "1. Print Books" << endl; 
    cout << "2. Change Price" << endl;
    cout << "3. Quit" << endl; 
    cout << "\nEnter Choice: ";
        cin >> menuChoice;
        if (menuChoice == 1) {
            for (int i = 0; i < bookCounter; i++) {
                cout << "===== BOOK =====" << endl;
                cout << "Title: " << Book[i].title << endl;
                cout << "Author: " << Book[i].author << endl;
                cout << "Price: " << fixed << setprecision(2) << Book[i].price << endl; } }
        else if (menuChoice == 2) { cin.ignore(100, '\n');
            cout << "What is the title of the book? ";
            getline(cin, findTitle, '\n');
            for (int i = 0; i < bookCounter; i++) {
                if (findTitle == Book[i].title) {
                    cout << "Enter New Price: " << endl;
                    cin >> Book[i].price;
                }
                else if (findTitle != Book[i].title) {
                    cout << "Unable to find Book" << endl;
                }}}

        else if (menuChoice < 1 || menuChoice > 3) {

            cout << "Invalid Entry. Please enter 1, 2, or 3 from the options menu." << endl;
        }   } while (menuChoice != 3);
}

//  !!! DON'T UNCOMMENT THIS UNTIL YOU FIGURE OUT HOW TO PRESERVE "arraySize" !!!
//      Suggestion: use a C++ "vector<>" instead of an array...
//    void writeFile(int arraySize, struct bookTable *Book[]) {
//    
//      ofstream outfile;
//      int bookCounter = 0;
//    
//      outfile.open("sale2.txt");
//    
//      outfile << arraySize << endl;
//    
//      for (int i = 0; i < bookCounter; i++) {
//    
//          outfile << Book[i].title << endl;
//          outfile << Book[i].author << endl;
//          outfile << fixed << setprecision(2) << Book[i].price << endl;
//      }
//    
//      outfile.close();
//    
//      delete[] Book;
//    
//    }

int main() {

    // setStruct();  // Not needed
    struct bookTable *book_table = setArray();  // Allocate space
    readFile(book_table);  // Initialize data
    displayMenu(book_table); // use book_table
    // writeFile(); // TBD

    cout << "\nSale2.txt has been created." << endl;

    return 0;
} 

Key notes: 主要说明:

  1. When you had everything in "main()", all of your code had visibility to all of your variables. 当你在“main()”中拥有所有内容时,所有代码都可以看到所有变量。

  2. When you moved everything into separate functions, the functions could no longer "see" these variables. 当您将所有内容移动到单独的函数中时,函数将无法再“看到”这些变量。

    This is called "scope" 这被称为“范围”

  3. One solution is to put everything back in "main()". 一种解决方案是将所有内容放回“main()”中。 This is Bad. 这是不好的。

    Another solution is to make your variables all global. 另一种解决方案是使您的变量全局化。 This, too, is Bad. 这也是坏事。

    A good solution is to declare the variables you need to share in "main()", but then pass them as parameters . 一个好的解决方案是在“main()”中声明需要共享的变量,然后将它们作为参数传递。 This is what I've shown above. 这就是我上面所说的。

  4. An even better, more advanced solution, might be to refactor your program into classes . 更好,更高级的解决方案可能是将您的程序重构为

  5. Since you're programming in C++, and since you have a variable number of elements, it would probably be a good idea to change your array into a C++ vector . 由于您使用C ++进行编程,并且由于您具有可变数量的元素,因此将数组更改为C ++ 向量可能是个好主意。 This has several advantages, including: 这有几个优点,包括:

    a. 一个。 You'd no longer need to read the entire file just to find the #/elements - you could simply add new elements as you go. 您不再需要阅读整个文件只是为了找到#/ elements - 您可以随意添加新元素。

    b. You can always query "vector.size()" to find the current #/elements. 您始终可以查询“vector.size()”以查找当前的#/元素。

  6. There are other issues, too. 还有其他问题。

I hope that helps ... and please post back if you have any questions. 我希望有帮助......如果您有任何疑问,请回复。

Couple of things: 几件事:
-Your struct doesn't need to be inside of the setStruct function, the setStruct should be used to send data to an existing struct (example below) - 您的结构不需要在setStruct函数内部,setStruct应该用于将数据发送到现有结构(下面的示例)
-setArray isn't being passed any parameters when it's being called (It needs (int &arraySize, struct bookTable *Book[]) ) and neither are some of your other functions, this means that they don't actually have any data to modify. -setArray在被调用时没有被传递任何参数(它需要(int &arraySize, struct bookTable *Book[]) )并且你的其他函数都不是,这意味着它们实际上没有任何数据需要修改。
They should be called like this: setArray(size of array, struct being passed to it); 应该像这样调用它们: setArray(size of array, struct being passed to it);

Also, an example of how setStruct and the struct should be defined seperately: 另外,应该单独定义setStruct和struct的示例:

struct bookTable {
    string title;
    string author;
    double price;
};
void setStruct(&struct x, string title, string author, double price) {
    x.title  = title;
    x.author = author;
    x.price  = price;

}

Make sure to pay attention to what each of these functions are doing so that you know what parameters to pass to them and better understand the code overall. 确保注意每个函数正在做什么,以便您知道要传递给它们的参数,并更好地理解整体代码。
By splitting main() into a bunch of functions you aren't really doing much besides making your code modular and legible 通过拆分的main()成一束的功能你是不是真的做太多,除了使你的代码模块化,清晰

Also, posting the exact errors that you're getting will help, as I imagine that even after you fix these things I mentioned I might not work perfectly 另外,发布您正在获得的确切错误将有所帮助,因为我想即使你修复了我提到的这些事情后我也可能无法正常工作

For starters: 对于初学者:

void setStruct() {

    struct bookTable {
        string title;
        string author;
        double price;
    };
}

You create a function setStruct() then use it several times in other functions without accessing the function itself. 您创建一个函数setStruct()然后在其他函数中多次使用它而无需访问函数本身。 Why not place the struct in its global scope that way you can use it in Main() or anywhere else and pass the struct declaration freely between functions? 为什么不将结构放在其全局范围内,以便在Main()或其他任何地方使用它,并在函数之间自由传递struct声明?

Also: 也:

for (int i = 0; getline(infile, Book[i].title); i++) {

    getline(infile, Book[i].author, '\n');
    infile >> Book[i].price;
    infile.ignore(100, '\n');

    bookCounter++;
}

You pass a use Book as if it is in scope where you have declared it and potentially defined it. 您传递一个use Book ,就好像它在您声明它并可能定义它的范围内一样。 However, you pass it through a function - meaning the struct type is now out of scope and will need to access its elements through a pointer. 但是,您通过函数传递它 - 意味着结构类型现在超出范围,并且需要通过指针访问其元素。 So your code will need to be adjusted as such: 因此,您的代码需要进行调整:

void readFile(struct bookTable *Book[]) {

    ifstream infile;
    int bookCounter = 0;

    infile.open("books2.txt");

    for (int i = 0; getline(infile, Book[i]->title); i++) {

        getline(infile, Book[i]->author, '\n');
        infile >> Book[i]->price;
        infile.ignore(100, '\n');

        bookCounter++;
    }

    infile.close();
}

Notice that every place you had Book[i].variable is now Book[i]->variable - Hopefully this helps. 请注意,你有Book[i].variable每个地方现在都是Book[i]->variable - 希望这会Book[i].variable帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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