好吧所以我有两个相同的字符串方法......
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;
}
然而无论我做什么,CreateFood的胆量都会崩溃。我为它创建了一个测试机箱,它始终在cMeal = CreateFood();
Customer Cnow;
cout << "test1" << endl;
cMeal = Cnow.CreateFood();
cout << "test1" << endl;
cCustomer = Cnow.CreateCust();
cout << "test1" << endl;
我甚至用CreateFood切换CreateCust,它仍然在CreateFood函数...
失败注意:如果我使createFood成为一个int方法,它确实有用......
即使我改变了CreateFood来改变消息,也没有更多它仍然崩溃......
答案 0 :(得分:8)
取出两个+ 1
,从0开始访问数组:
int d = rand() % (8 - 1 + 1); // 0-7, not 1-8
int d = rand() % (3 - 1 + 1); // 0-2, not 1-3
否则您正在访问不存在的元素,这是未定义的行为。 (这意味着它似乎可以正常工作,就像CreateCust
一样,像CreateFood
一样崩溃,什么也不做,或做任何事情。)
我不确定减去1然后加1的目的是什么。无论如何,现在是学习的最佳时机:不要重复自己。即使你只做了两次,也可以用它来制作一个功能,它就会变得更加神秘,更简洁:
int random(int min, int max)
{
return rand() % ((b - a) + 1) + a;
}
这是一个简单的函数,可以在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;
}
你甚至可以看到只有一个功能让它更容易阅读;您的目标是让您的代码易于被人类阅读。此外,这更简洁:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return nameArray[random(0, 2)];
}
另一个不好的事情是将魔术数字硬编码到你的程序中。例如,为什么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)];
}
现在,号码的范围很有意义。
剩下的可能有点高级(在你进入模板之前你不会理解),但是展示了我们如何继续:
template <typename T, size_t N>
char (&countof_detail(T (&)[N]))[N];
#define countof(pX) sizeof(countof_detail(pX))
这个漂亮的工具将为您提供数组中元素的数量。代码可能会变成这个
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ no explicit size
return nameArray[random(0, countof(nameArray) - 1)];
}
我们完全摆脱了任何数字,你可以随意操纵阵列。最后,我们再次重复:从数组中获取一个随机元素。我们应该为此做一个功能:
template <typename T, size_t N>
T& random_element(T (&pArray)[N])
{
return pArray[random(0, N - 1)];
}
这会从任何数组中返回一个随机元素。那么你的功能就是:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return random_element(nameArray);
}
请注意,在这个重构中(重构是将代码并将其分解为新的,更简单的部分),它读得更好:为了获得食物,我们有一系列食物,我们随机选择一个。
在工作时记住这些东西,当你学习C ++时,你可以制作更好的代码。任何时候你重复一个不重要的任务,使它成为一个功能。突然之间,这个任务是微不足道的,因为你不关心函数是如何工作的(在函数中),只是关于函数的作用(这是函数名)。
答案 1 :(得分:5)
崩溃正在发生,因为您正在访问无效索引。这是因为数组索引从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 );
}
答案 2 :(得分:2)
看这里:
int d = rand() % (8 - 1 + 1) + 1;
这将返回1到8 包含之间的数字。你需要的是:
int d = rand() % 8;
答案 3 :(得分:1)
你超出了数组的范围。数组对象从0开始。
答案 4 :(得分:0)
我不明白为什么你有
int d = rand() % (8 - 1 + 1) + 1;
为什么不使用
int d = rand() % 8;
答案 5 :(得分:0)
我认为现代c ++编译器仍然允许你使用旧的C技巧来实现静态数组:
string CreateFood()
{
char* nameArray = {"spagetti", "ChickenSoup", "Menudo"};
// note the trick to get the compiler to count the array elements for you:
int d = rand() % (sizeof(nameArray) / sizeof(nameArray[0]));
return std::string( nameArray[d] );
}