为什么我的输入不会从结构数组中显示?

问题描述 投票:0回答:2

我正在尝试制作一个可以添加玩家信息的程序。我可以运行该程序,但是当选择“查看玩家记录”时,昵称被省略。有人能看出这里的问题吗?

#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;
}

我已经尝试将字符输入更改为 getline() 来获取字符串,但它仍然不起作用。我还隔离了这两个功能(添加和查看),并尝试在没有 switch-case 的情况下,仅使用 main 中的两个功能,并且它确实有效。但我需要那个开关盒,以便用户可以从选项中进行选择。我做的另一件事是,我没有创建一个用于查看的函数,而是直接将其写在开关内的情况下,但它也不起作用。有人可以帮忙吗?

c++ switch-statement output cin getline
2个回答
0
投票

您描述的行为是流上混合输入样式的常见症状。

在您的情况下,您的代码执行

cin >> op
(面向流的输入)来读取
int
,然后使用
getline(cin, record.nickname);
(面向行的输入)从
cin
读取数据。

这两种输入方式(面向流与面向行)在一个流上同时使用时,会以意想不到的方式交互,因为它们处理换行符 (

'\n'
) 的方式不同 -
>>
在遇到
'\n'
时停止) AND 将该字符保留在流缓冲区中,而
getline(cin, ...)
(默认情况下)将数据读取到字符串中,直到遇到该
'\n'
,将其从流缓冲区中删除,丢弃它,然后立即返回。如果换行符是流缓冲区中的第一个字符,则意味着不会尝试(直到后续输入操作)读取预期数据。

看来您已经尝试过(或被错误地建议使用)

cin.ignore()
。由于各种原因,这并不总是有效。

可行的解决方案是在任何地方使用来自

cin
的相同样式的输入(例如,使用
cin.getline()
读取来自
cin
的所有输入,然后根据需要解析字符串以获取值,这意味着您的程序将接收输入一一次一行)。通过解析字符串,您的程序还可以更好地应对意外输入(例如,如果用户输入错误数据)。


-1
投票

问题是您在标签

playerArr
之后声明了
start
。因此,当运行
goto start
时,会调用析构函数,它可能会清除字符串
nickname
并且不会清除原始数据类型的其他变量。因此,跳转后,当您尝试查看详细信息时,它会显示空字符串和其他变量的剩余值。这个代码说明了我的意思:

#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;
}

解决方案是将

playerArr
移到
start
标签之前。

  const int numPlayers = 5;
  Player playerArr[numPlayers];
start:
  ...
© www.soinside.com 2019 - 2024. All rights reserved.