我想创建一个数组,我只能在运行时知道其大小,然后在程序执行期间进一步增加该大小。
这是来自/r/dailyprogrammer 挑战,可以在这里找到 https://www.reddit.com/r/dailyprogrammer/comments/3twuwf/20151123_challenge_242_easy_funny_plant/
MSVisual 给了我错误 std::badd_array_new_length这意味着它在实例化数组时遇到问题?
我厌倦了经常从它工作的网站复制代码字母,而且我经常收到错误。Visual 是一个糟糕的学习C++平台吗?我应该尝试QT吗?
#include <iostream>
#include <string>
void main(int argc, char* argv[]) {
int currentPlants = std::stoi(argv[2]), targetPeople = std::stoi(argv[1]), currentProduce = 0, week = 0;
int * plants;
plants = new int[currentPlants];
for (int i = 0; i < currentPlants; i++) {
plants[i] = 0;
}
if (plants == nullptr) EXIT_FAILURE;
while (currentProduce < targetPeople) {
currentProduce = 0;
for (int i = 0; i < currentPlants; i++) {
currentProduce += plants[i];
plants[i]++;
}
if (currentProduce >= targetPeople) break;
else {
plants = new int[currentProduce];
for (; currentPlants < currentProduce; currentPlants++) {
plants[currentPlants] = 0;
}
}
week++;
}
std::cout << week;
}
您应该使用std::vector
.
总结一下:
// Create an array of size 10
std::vector<int> my_vector(10);
// Add '3' to my_vector
my_vector.push_back(3);
// Remove the last element
my_vector.pop_back();
这里的解释和示例:www.cplusplus.com/reference/vector/vector/
编辑 :构造对象时无需指定数组大小。
// Create an array
std::vector<int> my_vector;
不能在运行时增加数组的大小。您可以创建一个新的更大的数组,并将旧数组的内容复制到新数组。
代码的问题在于,在第一次通过plants
时,所有plants[x]
都为零。您将所有这些加在一起并得到零 => currentProduce == 0
。然后,您尝试new plants[currentProduce aka 0]
这是非法的。
您的第二个问题是,每次new
时,您都会创建一个丢弃旧值的新数组; new
创建一个新数组,它对旧数组一无所知。
我使用 std::vector
重写了您的代码,它修复了崩溃但产生了一个无限循环,因为在第一次传递时,currentProduce
变为零,因此数组被截断。
#include <iostream>
#include <string>
#include <vector>
int main(int argc, const char* argv_real[])
{
const char* argv[] = { "programname", "5", "25" };
int currentPlants = std::stoi(argv[2]), targetPeople = std::stoi(argv[1]), currentProduce = 0, week = 0;
std::cout << "targetPeople = " << targetPeople
<< ", currentPlants = " << currentPlants
<< "n";
std::vector<int> plants;
// Option 1:
// plants.resize(currentPlants);
// Option 2:
for (auto i = 0; i < currentPlants; ++i) {
plants.push_back(0);
}
while (currentProduce < targetPeople) {
std::cout << "cp: " << currentProduce
<< ", tp: " << targetPeople
<< "n";
currentProduce = 0;
// plantCount is a reference to plants[i] for each i
for (auto& plantCount : plants) {
std::cout << plantCount << ", ";
currentProduce += plantCount;
plantCount++;
}
std::cout << " cp: " << currentProduce << "n";
if (currentProduce >= targetPeople)
break;
// Option 1:
plants.resize(currentProduce);
// Option 2:
// while (currentPlants < currentProduce) {
// plants.push_back(0);
// }
week++;
}
std::cout << week;
}
现场演示:http://ideone.com/xGpoF6
除了使用 std::vector
之外,您需要在堆上分配一个新数组,复制内容并删除旧数组。然后将int*
指向新分配的阵列。
这在技术上不会改变数组大小,但访问对象的人会看到它好像正在改变。
这很危险:
int * plants;
plants = new int[currentPlants];
for (int i = 0; i < currentPlants; i++) {
plants[i] = 0;
}
if (plants == nullptr) EXIT_FAILURE;
这是发生的事情(如果你幸运的话):
- 程序尝试创建一些内存,如果不能,则返回 nullPTR
- 然后,程序在循环中使用内存,即使返回了 nullptr。(如果返回nullptr,这将导致程序崩溃,静默损坏内存,因此您得到错误的结果或以其他方式执行您不想要的操作)
- 然后,程序检查是否返回了 nullPTR。
如果你运气不好,编译器会进行时间旅行并摧毁整个宇宙。 我不是在开玩笑,看看:
- https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633
- 导致时间旅行的未定义行为