我试图调用一个函数,它将从一个表中随机生成一个字符串。(忽略奇怪的目的,我正在寻找一个挑战,我的朋友建议这一点)当函数被调用时,它忽略所有的'cin'并吐出这个响应。烤面包机死亡总数是:C:\Users\MH\source\repos\suicidefun\x64\bug\suicidefun.exe(进程25852)退出代码0。
我的代码是这样的:
// imports
#include <iostream>
using namespace std;
//var
string methods[21] = { "Hanging", "Shooting", "Poisoning", "Drinking Bleach", "Toaster Bath", "something idk", "Eating something you are allergic to", "Fall damage", "Mr. Hands", "Stabbing", "Shoving a pointy object in you", "Thinking you are in a dream and doing something stupid","Drunk driving","Overdose","Drowning","Fire","Starving or dehydrating","Driving off a cliff","Driving into a family of five's ford fiesta","Eat glass","Suicide by cop" };
time_t current_time = time(NULL);
int random;
bool again = true;
int killcount = 0;
string x = "N/A";
int check = 0;
bool valid = false;
char ans = 'n';
void thing(){
srand((unsigned)time(NULL));
int random = rand() % 20;
cout << methods[random];
killcount++;
while (valid = false) {
cout << "Kill yourself again? (y/n)";
cin >> x;
if (x != "y" || "n" || "Y" || "N") {
cout << "invalid answer";
}
else {
valid = true;
break;
}
}
if (x == "y") {
cout << "Current death total is:" + killcount;
}
else if (x == "Y") {
cout << "Current death total is:" + killcount;
}
else {
again = false;
cout << "Final death total is:" + killcount;
}
}
int main() {
thing();
return 0;
}
字符串
我期望发生的是输出一个随机字符串,变量numbercount增加1,程序询问用户是想继续还是停止,然后程序输出numbercount的值,如果用户选择停止,则再次将布尔值设置为false。
1条答案
按热度按时间nfg76nw01#
以下是我在你的程序中发现的一些问题。
避免
using namespace std;
一般来说,专业程序员不会使用
using namespace std;
。您也不应该使用。相反,只需键入std::
作为您需要从C++标准库使用的任何名称的前缀。例如,std::cout
。using namespace std
是一个using directive。@Chris在下面的评论中指出,* 使用声明 *,如using std::swap
和using std::cout
,是一个不同的故事(如果它们被明智地使用)。见下文。在这些情况下,使用swap
或cout
没有前缀可能是可以的。全局变量
在一个大型程序中,使用“全局”变量是有问题的,因为很难跟踪它们在哪里被修改了。证明程序正确性(对于所有执行路径)几乎是不可能的。更糟糕的是,当你有一个bug时,因为你的一个全局变量得到了错误的值,很难跟踪它在哪里出错了。
在下面的示例程序中,我将变量设置为“local”。
赋值与相等
在C++中,* 赋值 * 使用
=
,而测试 * 相等 * 使用==
。字符串
根据其本身,
valid
将是true
或false
。但测试valid == true
的答案也是如此,因此最佳做法是单独使用变量。赋值表达式
valid = false
将变量valid
设置为false
,* 然后将false
返回到周围的表达式。* 因此,while (valid = false)
与while(false)
相同。重复比较
对于重复比较,您必须为每次比较重新声明变量名。
型
请注意,您必须使用
&&
加入测试。在伪代码中,这将给您给予:如果x不是“y”且x不是“n”且x不是“Y”且x不是“N”...
不能使用
+
连接带有数字的字符串在C++中,不能使用
+
将字符串文字与数字连接起来。型
你的程序“吐出截断字符串”的原因是因为像
"Current death total is:" + killcount
这样的表达式是有效的 * 指针表达式 *。例如,当killcount
是3时,它返回一个指向"Current death total is:"
中第4个字符的指针。当该指针使用std::cout
输出时,结果是"rent death total is:"
。缺少外循环
函数
thing
缺少一个应该由变量again
控制的外部循环。型
随机数
函数
rand
使用的算法 * 依赖于实现。* 每个编译器都定义了自己的版本。有些编译器使用好的算法,而有些则没有。同时,在C11中引入的Mersenne twister引擎std::mt19937
要求在所有编译器上都相同。即使
rand
在你的编译器上是可以的,rand() % 20
肯定不是。它生成的随机数不是均匀分布的。某些值比其他值返回得更频繁。(参见pigeonhole_ principle。)这就是为什么std::uniform_int_distribution
被添加到C11中。它返回的数字保证是均匀分布的。我通常将
std::mt19937
和std::uniform_int_distribution
封装到一个简单的类中,比如下面的类RNG
。这样,我就可以为我需要的每种随机数拥有一个单独的成员函数。然而,对于你的游戏,我只需要一个这样的函数:random_method
。型
这里有一些关于
RNG
类的注意事项。std::size_t
是数组下标使用的类型。这就是为什么我用std::size_t
示例化std::uniform_int_distribution
。我希望它返回一个随机下标。std::random_device{}()
返回一个随机的32位种子,std::mt19937
的构造函数将其用作种子。param_type{ 0, size - 1 }
构造一个param
对象,该对象包含std::uniform_int_distribution
对象dist
将返回的最小值和最大值。dist
需要两个参数来生成一个随机数:第一个是随机数引擎mt
,第二个是一个param
对象,它给出了要使用的数字范围。调用函数获取键盘输入
一般来说,我每次需要从
std::cin
获取输入时都会调用一个函数。这里有一个简短的函数,它从用户那里获取Y/N
响应,同时拒绝无效的响应。它使用
std::getline
,所以当你把它和std::cin >> value;
这样的语句混合在一起时必须小心,因为std::cin >> value;
在输入流上留下了一个挂起的'\n'
。你必须在调用get_yes_no
之前去掉它,通常是通过调用std::cin.ignore
。然而,这在这里不是问题。因为没有像std::cin >> value;
这样的东西在任何地方都使用。型
Helper函数
get_yes_no
调用一对辅助函数。第一个将字符串转换为大写。型
第二个函数从字符串中删除前导和尾随空格。
型
简化游戏功能
有了这些辅助函数,程序的代码就简化成这样了。
型
下面是main函数:
型
示例运行(输入错误)
示例运行的输出:
型