Why won't my input be displayed from an array of structure?

84 views Asked by At

I am trying to make a program where I can add players' info. I can run the program, but when selecting 'view players record' the nicknames are ommited. Can anyone see the problem here?

#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

struct Player {
    string nickname;
    int age;
    int bps1;
    int bps2;
};

void addRecord(Player& record);
void viewPlayers(const Player playerArr[], int numPlayers);
double computeAve(const Player playerArr[], int numPlayers);
void showMax(const Player playerArr[], int numPlayers);
void showMin(const Player playerArr[], int numPlayers);

int main() {
    start:
    cout << "==============================================" << endl;
    cout << "                     MENU                     " << endl;
    cout << "==============================================" << endl;
    cout << "1. Add record" << endl;
    cout << "2. View players records" << endl;
    cout << "3. Compute for the average" << endl;
    cout << "4. Show the player(s) who get the max average." << endl;
    cout << "5. Show the player(s) who get the min average." << endl;
    cout << "6. Exit" << endl;

    const int numPlayers = 5;
    Player playerArr[numPlayers];

    int op;
    cout << "\nEnter your choice: ";
    cin >> op;

    switch (op) {
        case 1:
            for (int i = 0; i < numPlayers; i++) {
                cout << endl;
                cout << "ENTER DETAILS FOR PLAYER " << i + 1 << ":\n";
                addRecord(playerArr[i]);
                cout << endl;
            }
            goto start;
            break;
        case 2:
            viewPlayers(playerArr, numPlayers);
            goto start;
            break;
        case 3:
            for (int i = 0; i < numPlayers; i++) {
                cout << "Player " << i + 1 << " average: " << fixed << setprecision(2) << computeAve(playerArr, numPlayers) << endl;
            }
            goto start;
            break;
        case 4:
            showMax(playerArr, numPlayers);
            goto start;
            break;
        case 5:
            showMin(playerArr, numPlayers);
            goto start;
            break;
        case 6:
            cout << "Exiting program." << endl;
            return 0;
            break;
        default:
            cout << "Invalid choice. Please select a valid option." << endl;
    }

    return 0;
}

void addRecord(Player& record) {
    cout << "Enter player nickname: ";
    cin.ignore();
    getline(cin, record.nickname);
    cout << "Enter player age: ";
    cin >> record.age;
    cout << "Enter best played score 1: ";
    cin >> record.bps1;
    cout << "Enter best played score 2: ";
    cin >> record.bps2;
}

void viewPlayers(const Player playerArr[], int numPlayers) {
    cout << "============================================================================================" << endl;
    cout << " Nickname                    Age          Best Played Score 1          Best Played Score 2  " << endl;
    cout << "============================================================================================" << endl;
    for (int i = 0; i < numPlayers; i++) {
        cout << setw(28) << left << playerArr[i].nickname;
        cout << setw(29) << right << playerArr[i].age;
        cout << setw(18) << right << playerArr[i].bps1;
        cout << setw(29) << right << playerArr[i].bps2 << endl;
    }
}

double computeAve(const Player playerArr[], int numPlayers) {
    double totalAverage = 0.0;
    for (int i = 0; i < numPlayers; i++) {
        totalAverage += static_cast<double>(playerArr[i].bps1 + playerArr[i].bps2) / 2.0;
    }
    return totalAverage / numPlayers;
}

void showMax(const Player playerArr[], int numPlayers) {
    double maxAverage = 0.0;
    for (int i = 0; i < numPlayers; i++) {
        double average = computeAve(playerArr, numPlayers);
        if (average > maxAverage) {
            maxAverage = average;
        }
    }
    cout << "Player(s) with the maximum average score: " << fixed << setprecision(2);
    for (int i = 0; i < numPlayers; i++) {
        double average = computeAve(playerArr, numPlayers);
        if (average == maxAverage) {
            cout << playerArr[i].nickname << " ";
        }
    }
    cout << "(Average: " << maxAverage << ")" << endl;
}

void showMin(const Player playerArr[], int numPlayers) {
    double minAverage = 100.0; // Initialize with a high value
    for (int i = 0; i < numPlayers; i++) {
        double average = computeAve(playerArr, numPlayers);
        if (average < minAverage) {
            minAverage = average;
        }
    }
    cout << "Player(s) with the minimum average score: " << fixed << setprecision(2);
    for (int i = 0; i < numPlayers; i++) {
        double average = computeAve(playerArr, numPlayers);
        if (average == minAverage) {
            cout << playerArr[i].nickname << " ";
        }
    }
    cout << "(Average: " << minAverage << ")" << endl;
}

I already tried changing the character input to getline() to fetch the strings but it still won't work. I also isolated the two functions (add and view) and tried without the switch-case, with just the two functions inside the main and IT DID WORK. But I needed that switch-case so the user could choose from the options. One other thing I did is instead of creating a function for viewing, I directly wrote it in the case within the switch, and it didn't work either. Can anyone please help?

1

There are 1 answers

0
kiner_shah On

The problem is you have declared playerArr after the label start. So when goto start is run, destructor is called which probably clears the string nickname and doesn't clear the other variables of primitive data types. So after the jump, when you try to view the details, it shows empty string and leftover values for other variables. This code shows what I mean:

#include <string>
#include <iostream>

struct A
{
    std::string s;
    int k;

    friend std::ostream& operator<<(std::ostream& os, const A& a)
    {
        os << '[' << a.s << ' ' << a.k << ']';
        return os;
    }
    ~A() { std::cout << "\ndestructor called"; }
};

int main()
{
    int i = 0;
    label1:
        A arr[2];
        if (i == 0)
        {
            std::cin >> arr[0].s >> arr[0].k;
            std::cin >> arr[1].s >> arr[1].k;
        }
        std::cout << '\n';
        for (int j = 0; j < 2; j++)
            std::cout << arr[j] << ' ';
        ++i;
        if (i == 10)
            return 0;
        goto label1;
}

The solution is to move the playerArr before the start label.

  const int numPlayers = 5;
  Player playerArr[numPlayers];
start:
  ...