好吧所以我有两个相同的字符串方法......
string CreateCust() {
string nameArray[] ={"Tom","Timo","Sally","Kelly","Bob","Thomas","Samantha","Maria"};
int d = rand() % (8 - 1 + 1) + 1;
string e = nameArray[d];
return e;
}
string CreateFood() {
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
int d = rand() % (3 - 1 + 1) + 1;
string f = nameArray[d];
return f;
}
Run Code Online (Sandbox Code Playgroud)
然而无论我做什么,CreateFood的胆量总会崩溃.我为它创建了一个测试机箱,它总是失败cMeal = CreateFood();
Customer Cnow;
cout << "test1" << endl;
cMeal = Cnow.CreateFood();
cout << "test1" << endl;
cCustomer = Cnow.CreateCust();
cout << "test1" << endl;
Run Code Online (Sandbox Code Playgroud)
我甚至用CreateFood切换CreateCust,它仍然在CreateFood函数失败...
注意:如果我使createFood成为一个int方法,它确实有用......
即使我改变CreateFood只是COUT一条消息,也没有更多它仍然崩溃...
取出+ 1它们,从0开始访问数组:
int d = rand() % (8 - 1 + 1); // 0-7, not 1-8
int d = rand() % (3 - 1 + 1); // 0-2, not 1-3
Run Code Online (Sandbox Code Playgroud)
否则,您正在访问不存在的元素,这是未定义的行为.(这意味着它似乎可以起作用,比如在CreateCust崩溃中CreateFood,什么也不做,或做任何事情.)
我不确定减去1然后加1的目的是什么.无论如何,现在是学习的最佳时机:不要重复自己.即使你只做了两次,也可以用它做一个功能,它就会变得更加神秘,更简洁:
int random(int min, int max)
{
return rand() % ((b - a) + 1) + a;
}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的函数,它返回一个a和之间的随机数b.(意味着它可以包括a和b结果中的两者.)现在您的代码如下:
// I'll leave CreateCust up to you
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
int d = random(0, 2); // either 0, 1, or 2, randomly
string f = nameArray[d];
return f;
}
Run Code Online (Sandbox Code Playgroud)
而且你会发现即使只有一个功能也可以让它更容易阅读; 您的目标是让您的代码易于被人类阅读.此外,这更简洁:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return nameArray[random(0, 2)];
}
Run Code Online (Sandbox Code Playgroud)
另一个不好的事情是将魔术数字硬编码到你的程序中.例如,为什么3或8?可以推断出这些是数组大小,但这并不是独立的.您可能想要的是:
string CreateFood(void)
{
const size_t ArraySize = 3; // 3 elements, 0-2
string nameArray[ArraySize] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ Ensure it matches
return nameArray[random(0, ArraySize - 1)];
}
Run Code Online (Sandbox Code Playgroud)
现在,数字的范围很有意义.
其余的可能有点高级(在你进入模板之前你不会理解),但是展示了我们如何继续:
template <typename T, size_t N>
char (&countof_detail(T (&)[N]))[N];
#define countof(pX) sizeof(countof_detail(pX))
Run Code Online (Sandbox Code Playgroud)
这个漂亮的工具将为您提供数组中的元素数量.代码可能会变成这个
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ no explicit size
return nameArray[random(0, countof(nameArray) - 1)];
}
Run Code Online (Sandbox Code Playgroud)
我们完全摆脱了任何数字,你可以随意操纵阵列.最后,我们再次重复:从数组中获取一个随机元素.我们应该为此做一个功能:
template <typename T, size_t N>
T& random_element(T (&pArray)[N])
{
return pArray[random(0, N - 1)];
}
Run Code Online (Sandbox Code Playgroud)
这将从任何数组中返回一个随机元素.那么你的功能就是:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return random_element(nameArray);
}
Run Code Online (Sandbox Code Playgroud)
请注意这个重构(重构是将代码和因子分解成新的,更简单的部分),它读得更好:为了获得食物,我们有一系列食物,我们随机挑选一个.
在你工作的时候记住这种东西,当你学习C++时,你可以制作更好的代码.任何时候你重复一个不重要的任务,使它成为一个功能.突然之间,这个任务是微不足道的,因为你不关心函数是如何工作的(在函数中),只是函数的作用(这是函数名).
发生崩溃是因为您正在访问无效索引.这是因为数组索引从0而不是1开始,因此您不希望将1添加到模数运算符的右值.
这是一个巧妙的技巧,您可以使用它来使您的代码更易于维护:
template <class T>
T getRandElem( const T[] arr )
{
return arr[ rand() % ( sizeof(arr) / sizeof((arr)[0]) ) ];
}
string CreateCust(){
static string nameArray[] = {"Tom","Timo","Sally","Kelly","Bob","Thomas","Samantha","Maria"};
return getRandElem<string>( nameArray );
}
string CreateFood(){
static string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return getRandElem<string>( nameArray );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
206 次 |
| 最近记录: |