程序从数组中输出错误的数字



危险点添加代码。

该程序应该通过一个动态数组来获取玩家的数量。

从那里,你可以输入玩家的名字,它会把名字插入一个二维数组。

然后你可以选择呼叫玩家开始向添加点数

循环一定次数并按0后,while循环将停止运行,并跳到for循环输出玩家名称和点数。

问题:如果我输入";1〃;对于playerNumber,我开始在索引[0][1]中添加点数,并输出与我输入的原始数字截然不同的数字。如果有两个以上的玩家,则三个玩家中有两个拥有随机数字,而一个仍然是准确的点数。

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

int main(void)
{
//GLOBAL SCOPE, all loops and other boxes can use these
//Declaration variables w cout & cin.
int playerNumber;
string playerNames;
bool flag = true;
cout << "How many players are there: ";
cin >> playerNumber;
cout << endl;
//Array Declaration.
string playerList[playerNumber][2]; //Dynamic array. changes during program runtime.
int points[playerNumber]; //Dynamic array. Changes during runtime
//GLOBAL SCOPE, all loops and other boxes can use these

//Assigning values to arrays now.
cout << "Enter the players names: " << endl;
//Assigns player name to each row.
for(int i = 0; i < playerNumber; i++){
cin >> playerNames;
playerList[i][0] = playerNames; //Assigns players name to the array
cout << "Player " << i + 1 << ": " << playerList[i][0] << endl;
}

while(flag){
//LOCAL VARIABLES
int choice = 0; //Always reverts back to zero to prevent addition error.
int pointsValue = 0; //Always reverts back to zero to prevent addition error.
//LOCAL VARIALES
cout << "Press 0 to end game, if not, enter player number: " << endl;
cin >> choice;
if(choice == 0){ //Exit out of the while loop
flag = false;
}
else if(cin.fail()){
cout << "Not a number. Try again." << endl;
cin.clear();
cin.ignore(256, 'n');
}
else if(choice < 0 || choice > playerNumber){
cout << "Choice is less than 0 or greater than player count. Try again." << endl;
}

else{
cout << "Enter points: " << endl;
cin >> pointsValue;
cout << endl;
points[choice - 1] += pointsValue; //Assigns points to points array
playerList[choice - 1][1] = (to_string(points[choice - 1])); //Assigns points to playerNumber.
}
}
cout << endl;
cout << "END OF JEOPARDY. HERE ARE THE POINTS!!!" << endl;
cout << endl;
//Current points for each player
//Shows their name and points
for(int i = 0; i < playerNumber; i++){ //Loops so that player name and points are displayed
string playerName = playerList[i][0];
string totalPoints = playerList[i][1];
cout << playerName << " points: " << totalPoints << endl;
}
return 0;
}

从技术上讲,这是非法的:

string playerList[playerNumber][2];
int points[playerNumber];

数组的大小必须在编译时(而不是运行时(已知。尽管一些编译器允许将其作为语言的扩展,但它不是标准语言的一部分。

更好的选择是使用std::vector

假设您的编译器允许这样做:

下一个问题是,您不初始化数组中的值。

int points[playerNumber];  // This is an array of random numbers.
// Sure if you are doing a debug build the
// compiler may be nice and just set all the
// values to zero as speed is not important
// during debugging. But on a release build
// these could be any value.

此外,如果我们想从技术上讲,除非您首先写入值,否则从数组中读取实际上是未定义的行为。尽管通常情况下,这不会导致程序在大多数架构上崩溃,而且代码运行起来就像没有发生任何糟糕的事情一样。

您可以正常初始化数组,如下所示:

int points[10] = {0};  // but your variable size stuff
// will stop working for that.
-------
// so you will have to manually initialize the members
int points[playerNumber];
for(int loop = 0; loop < playerNumber; ++loop) {
points[loop] = 0;
}

或者,如果您升级到vector:

std::vector<int> points(playerNumber,0); // Size and initial value.
// Though you don't need the
// initial value as vector will
// zero init members.

我要提到的最后一个问题是,你在检查阅读是否有效方面不一致。

cin >> pointsValue;

如果读取失败(即用户输入了非法值(,您认为pointsValue会发生什么。检查用户输入的正确方法是将read放入if语句中。

if ( std::cin >> pointValue) {
// The read worked `pointsValue` has valid user input
}
else {
// The read faild.
// We don't know what the user input should be
}

另一件需要考虑的事情是,用户输入是基于行的。他们在返回时添加值。因此,利用这一点并逐行读取用户输入是一个很好的策略。一旦您有了行,就解析并验证输入。这样,标准输入流就不会进入糟糕的状态。

std::string  line;
if (std::get(std::cin, line)) {
// We have a line of user input.
std::stringstream lineStream(std::move(line));
line.clear();
int choice;
if (lineStream >> choice) {
// We have a valid choice from the user.
// or do we. If the user entered `2x` is that valid input?
// because `choice` is 2; but there is still `x` on the
// input stream.
// That's a choice for you as the developer to make.
// if you don't care, then you have valid input. If you do
// care then you need to check there is no bad data on
// the line.
}
else {
// invalid choice
}
}
else {
// The user input stream just ended.
// This could mean the user entered the end-of-stream character
// or if the user had connected some other stream to the
// standard input on the command line and there is no more
// data to read.
}

我要注意的是,这可能永远不会适用于无效输入。

if(choice == 0){ //Exit out of the while loop
flag = false;
}
else if(cin.fail()){
// If you failed to read data from the std::cin
// the the value of `choice` is probably zero 
// (if I remember my standard correctly) so the
// first branch of the if tree will be entered
// and you will never enter this branch.
cout << "Not a number. Try again." << endl;
cin.clear();
cin.ignore(256, 'n');
}

最新更新