C++ 购物清单计划:在VIM中;分段故障(堆芯倾倒)“;,但代码块是有效的
希望你的一天过得很好 说到编程,我有点无所事事,所以请容忍我。我有两个问题。我正在尝试创建一个由5个文件组成的程序:items.h、items.cpp、list.h、list.cpp和main。有一个Item类和一个List类。该程序的目标是创建一个购物列表,允许用户输入项目名称、项目单位、单位成本,然后将其添加到列表中。该程序还允许您按项目名称删除项目我们不能使用向量 问题1:到目前为止,我所拥有的将在代码块中运行,但当我在VIM中运行它时,我得到错误“分段错误(内核转储)” 问题2:当我尝试在main中添加另一个要使用的变量时,我也遇到了一个错误,例如amountToBuy(包含用户想要购买的项目的整数)——添加时,代码块中的程序将不会运行,并声明“std::bad_alloc”。我已经注释了一些内容,所以程序将运行 我完全不知所措,不知道是哪些线路导致了问题,也不知道我将如何着手解决问题。如有任何意见,将不胜感激。多谢各位 list.hC++ 购物清单计划:在VIM中;分段故障(堆芯倾倒)“;,但代码块是有效的,c++,vim,codeblocks,C++,Vim,Codeblocks,希望你的一天过得很好 说到编程,我有点无所事事,所以请容忍我。我有两个问题。我正在尝试创建一个由5个文件组成的程序:items.h、items.cpp、list.h、list.cpp和main。有一个Item类和一个List类。该程序的目标是创建一个购物列表,允许用户输入项目名称、项目单位、单位成本,然后将其添加到列表中。该程序还允许您按项目名称删除项目我们不能使用向量 问题1:到目前为止,我所拥有的将在代码块中运行,但当我在VIM中运行它时,我得到错误“分段错误(内核转储)” 问题2:当我尝试
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
#include "items.h"
#include <string>
class List
{
private:
int arrayPosition;
int arraySize;
Item* itemsOnList = new Item[arraySize];
public:
List();
void addItem(Item);
void removeItem(std::string ri);
void displayList();
};
#endif // LIST_H_INCLUDED
#ifndef ITEMS_H_INCLUDED
#define ITEMS_H_INCLUDED
#include <string>
class Item
{
private:
std::string itemName;
//int numberToBuy;
public:
Item();
Item(std::string);
//setters
void setItemName(std::string);
//void setNumberToBuy(int);
//getters
std::string getItemName();
};
#endif // ITEMS_H_INCLUDED
main.cpp
#include "list.h"
#include "items.h"
#include <string>
#include <iostream>
/*******************************************************************
List::List()
Constructor initializes List size to 4 as default
*******************************************************************/
List::List()
{
arraySize = 4;
arrayPosition = 0;
}
/*******************************************************************
void List::addItem(Item)
This function adds the specified Item to the List
*******************************************************************/
void List::addItem(Item i)
{
//x2 arraySize when arrayPosition gets too close to arraySize
if (arrayPosition == arraySize)
{
//doubling arraySize since we need more space
arraySize *= 2;
//tempList to hold the old List's items
Item* tempList = new Item[arraySize];
//transferring information to tempList
for (int a = 0; a < arrayPosition; a++)
{
tempList[a] = itemsOnList[a];
}
delete[] itemsOnList;
//transferring data from temp List back to Old list
itemsOnList = tempList;
delete[] tempList;
//adding next item to list
itemsOnList[arrayPosition++] = i;
}
else
{
//adding next item to list
itemsOnList[arrayPosition++] = i;
}
}
/*******************************************************************
void List::removeItem(std::string)
This function removes the specified Item to the List
*******************************************************************/
void List::removeItem(std::string ri)
{
for (int a = 0; a < arrayPosition; a++)
{
if (itemsOnList[a].getItemName() == ri)
{
//moving the rest of the items down one position
//to take the removed item's spot
for (int b = a; b < arrayPosition; b++)
{
itemsOnList[b] = itemsOnList[b+1];
}
//decreasing arrayPosition by one because Item was removed
--arrayPosition;
}
}
}
/*******************************************************************
void List::displayList()
This function displays the List
*******************************************************************/
void List::displayList()
{
std::cout << "The following Items are on your Grocery List\n\n";
for (int i = 0; i < arrayPosition; i++)
{
std::cout << "Item name: " << itemsOnList[i].getItemName() << std::endl;
//std::cout << "Number to buy: " << itemsOnList[i].getNumberToBuy() << std::endl;
}
std::cout << std::endl;
}
#include "items.h"
Item::Item()
{
itemName = "empty";
//numberToBuy = 0;
}
//this constructor accepts a string and an int
Item::Item(std::string in)
{
itemName = in;
//numberToBuy = ntb;
}
//setters
void Item::setItemName(std::string in)
{
itemName = in;
}
/*
void Item::setNumberToBuy(int ntb)
{
numberToBuy = ntb;
}
*/
//getters
std::string Item::getItemName()
{
return itemName;
}
#include "list.h"
#include "items.h"
#include <iostream>
int main()
{
int menuChoice, subMenuChoice;
std::string itemName, removeItem;
bool exit = false;
List newList;
//introduction
std::cout << "Welcome to your Grocery List!\n\n";
do
{
//menu
std::cout << "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n\n";
std::cout << "To select a menu item, please select its corresponding number.\n\n";
//menu prompts and storing the choice
std::cout << "1. Add items to Grocery List\n";
std::cout << "2. Remove items from Grocery List\n";
std::cout << "3. Display Grocery List\n";
std::cout << "4. Exit\n\n";
std::cout << "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n\n";
std::cout << "Menu choice: ";
std::cin >> menuChoice;
std::cout << std::endl;
//menu choice break-away section
if (menuChoice == 1)
{
do
{
std::cout << "Please enter the name of the item: ";
std::cin >> itemName;
//std::cout << "Please enter the unit (cans, lbs, oz): ";
//std::cin >> itemUnit;
//std::cout << "Please enter number to buy: ";
//std::cin >> amountToBuy;
Item theItem(itemName);
newList.addItem(theItem);
std::cout << "Would you like to add another item? For YES type 1 | For NO type 0: ";
std::cin >> subMenuChoice;
std::cout << std::endl;
}
while(subMenuChoice == 1);
}
else if (menuChoice == 2)
{
std::cout << "Please enter the name of the item you want to remove: ";
std::cin >> removeItem;
std::cout << std::endl;
newList.removeItem(removeItem);
}
else if (menuChoice == 3)
{
newList.displayList();
}
else if (menuChoice == 4)
{
exit = true;
std::cout << "Goodbye!" << std::endl;
}
}
while (exit == false);
return 0;
}
#包括“list.h”
#包括“项目.h”
#包括
int main()
{
int菜单选择,子菜单选择;
std::string itemName,removietem;
bool exit=false;
列表新建列表;
//导言
std::coutIn
Item*itemsOnList=newitem[arraySize];
将在构造函数主体之前执行,因此
List::List()
{
arraySize = 4;
arrayPosition = 0;
}
运行并且arraySize
设置为4,itemsOnList
已被分配一个未知大小的数组,或者程序已崩溃
一个简单的解决方法是
class List
{
private:
int arrayPosition;
int arraySize;
Item* itemsOnList;
public:
List();
void addItem(Item);
void removeItem(std::string ri);
void displayList();
};
及
或
第二种方法使用了令人遗憾的欠教方法。这通常是最好的方法,因为它可以确保在进入构造函数主体之前完全构造对象。对于复杂对象,这可以防止在使用之前必须重做默认构造函数执行的任何工作,默认构造函数用于确保对象有效
编辑:上面的成员初始值设定项列表链接上的注释。前三分之一看起来像是用火星语写的。跳到解释部分并开始阅读,然后返回到细节,如果需要的话
在addItem
中,以下情况也会导致问题:
Item* tempList = new Item[arraySize]; //created new array
//transferring information to tempList
for (int a = 0; a < arrayPosition; a++)
{
tempList[a] = itemsOnList[a]; //copying old to new
}
delete[] itemsOnList; //free old list storage
//transferring data from temp List back to Old list
itemsOnList = tempList; // assign new list to old list
delete[] tempList; // whoops. Freed new list storage
b
的范围可达arrayPosition
-1,因此itemsOnList[b+1]
可以写成itemsOnList[arrayPosition-1+1]
或itemsOnList[arrayPosition]
arrayPosition
如果列表已满,则可能超过列表末尾。您的代码有三个突出问题
不初始化“arraySize”和“arrayPosition”。
您没有为“arraySize”指定初始值,但指定了
Item* itemsOnList = new Item[arraySize];
由于您指定此项的方式,充其量它将始终生成零长度(nullptr)itemsOnList,最坏情况下它将使用一些未初始化的随机值来创建随机大小的数组,并且arrayPosition也将随机小于或大于arraySize值
大小*=2
if (arrayPosition == arraySize)
{
//doubling arraySize since we need more space
arraySize *= 2;
在最好的情况下,您的arraySize从零开始。因此,当您将其加倍时,您将得到:零
删除所有内容。
此外,您还可以执行以下操作:
delete[] itemsOnList;
//transferring data from temp List back to Old list
itemsOnList = tempList;
此时,itemsOnList和tempList都指向同一数组。因此下一条语句:
delete[] tempList;
删除您的第二个副本-现在新旧数组都被删除。重要的一点是,最好及早了解:许多编程错误有时会导致它们看起来像是工作的。这意味着它可能会在一个编译器或一台计算机上“工作”一致,而不会在另一台计算机上工作,或者可能会在部分时间“工作”,然后停止“工作”突然之间,没有明显的原因。事实上,它从来没有“起作用”。无论如何,当你在构建系统1下找到“起作用”而不是构建系统2下的东西时,这几乎从来都不是构建系统的错。当你测试它时,它可能“起作用”,但当老师这样做时就不起作用了。有趣吧?在列表类定义中Item*itemsOnList=newitem[arraySize]
不应该工作。数组大小还没有设置,所以没有人知道会发生什么。你可以构建一个大小为0、40亿、-42或任何其他有效的int
的数组。大多数数组会立即爆炸。@user4581301你不能实际声明一个大小为负的数组,但你已经一针见血了。同意。我同意t会立刻爆炸的。非常感谢你的帮助和解释。信息非常丰富,我学到了一些新东西!祝你有一个美好的一天!:)
Item* itemsOnList = new Item[arraySize];
if (arrayPosition == arraySize)
{
//doubling arraySize since we need more space
arraySize *= 2;
delete[] itemsOnList;
//transferring data from temp List back to Old list
itemsOnList = tempList;
delete[] tempList;