购物清单程序:在VIM"分段错误(核心转储)",但代码块工作

时间:2016-06-28 17:06:35

标签: c++ vim codeblocks

希望你的一天顺利。

在编程方面,我有点像诺贝尔,所以请耐心等待。我有两个问题。我正在尝试创建一个由5个文件组成的程序:items.h,items.cpp,list.h,list.cpp和main。有一个Item类和一个List类。该程序的目的是创建一个购物清单,允许用户输入项目名称,项目单位,每单位成本,然后将其添加到列表中。该程序还允许您按名称删除项目。 我们无法使用矢量

问题1:到目前为止,我将在Codeblocks中运行,但是当我在VIM中运行时,我收到错误"分段错误(核心转储)。"

问题2:当我尝试添加另一个要在main中使用的变量时,我也遇到了错误,例如amountToBuy(包含用户想要购买的项目的int数) - 添加时,Codeblocks中的程序赢了&# 39; t run,stating" std :: bad_alloc"。我已经评论过一些东西,所以程序会运行。

我完全失去了,并且不知道哪些线路导致问题或我将如何解决问题。任何投入将不胜感激。非常感谢你!

list.h

#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

list.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;
}

items.h

#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

items.cpp

#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;
}

的main.cpp

#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;
}

2 个答案:

答案 0 :(得分:1)

class List
{
private:
    int arrayPosition;
    int arraySize;
    Item* itemsOnList = new Item[arraySize];
public:
    List();
    void addItem(Item);
    void removeItem(std::string ri);
    void displayList();
}; 

Item* itemsOnList = new Item[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();
}; 

List::List()
{
    arraySize = 4;
    arrayPosition = 0;
    itemsOnList = new Item[arraySize]
}

List::List():
    arrayPosition(0),
    arraySize(4),
    itemsOnList(new Item[arraySize])
{
}

第二个使用了不幸的教育不足Member Initializer List。这通常是最好的方法,因为它确保在进入构造函数体之前完全构造对象。对于复杂对象,这可以防止必须重做默认构造函数执行的任何工作,这些构造函数用于确保对象在使用前有效。

编辑:上面有关“成员初始化列表”链接的说明。前三分之一看起来好像是用火星人写的。跳到说明部分并开始阅读,然后根据需要返回到具体细节。

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

在短暂的时间内tempListitemsOnList指向相同的存储空间,因此delete任一指针都会为两者释放存储空间。解决方案:不要delete[] tempList;

RemoveItem

for (int b = a; b < arrayPosition; b++)
{
    itemsOnList[b] = itemsOnList[b+1];
}

b最高可达arrayPosition - 1,因此itemsOnList[b+1]可以写为itemsOnList[arrayPosition-1+1]itemsOnList[arrayPosition]。如果列表已满,arrayPosition可能是列表末尾结束的一个。

答案 1 :(得分:1)

您的代码有三个突出的问题。

没有初始化'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从零开始。因此,当你加倍时,你得到:零。

删除所有内容。

在addItem中,您执行以下操作:

    delete[] itemsOnList;

    //transferring data from temp List back to Old list
    itemsOnList = tempList;

此时,itemsOnList和tempList都指向同一个数组。所以下一个声明:

    delete[] tempList;

删除你的第二个副本 - 现在旧的和新的数组都被删除了。