2016-06-29 3 views
-2

Чтобы предисловие к этому, я новичок в программировании. Я пишу простую программу списка покупок, и у меня есть программа, управляемая циклическим меню. При выборе 1 он предлагает пользователю ввести 4 части данных, которые затем отправляю в конструктор класса элемента, чтобы инициировать значения. Затем я добавляю элемент в массив List List, а затем возвращает вас в меню. При выборе 3 из меню он должен отображать список, но по какой-то причине я получаю ошибку сегментации. Я работаю над этим в течение 2 дней прямо сейчас и не могу понять (ни мой TA). Я жестко закодировал данные в своих функциях, чтобы убедиться, что они работают правильно, и у меня не было проблем с отображением списка, добавлением элементов или удалением элементов. Единственная проблема возникает, когда я пытаюсь использовать функции в своем меню. Пожалуйста помоги!!!Сбой сегментации При запуске через меню

Основные функции:

int main() 
{ 
/*List sl1; 

Item Item1("apple", "unit", 3, 2.00); 
Item Item2("grapes", "Pounds", 4, 5.00); 
Item Item3("banana", "unit", 6, 2.00); 
Item Item4("pears", "ounces", 5, 1.00); 

sl1.addItem(&Item1); 
sl1.addItem(&Item2); 
sl1.addItem(&Item3); 
sl1.addItem(&Item4); 

sl1.removeItem("banana"); 
sl1.removeItem("grapes"); 
sl1.removeItem("pears"); 

cout << "Total Price: " << sl1.totalPrice() << endl; 

sl1.displayList(); 
*/ 
int menuChoice; 
List sl; 
     do 
     { 
      cout << endl; 
      cout << "1. Add Item to Shopping List" << endl; 
      cout << "2. Remove Item from Shopping List" << endl; 
      cout << "3. Display Shopping List" << endl; 
      cout << "4. Quit" << endl << endl; 

      cout << "Please Select 1-4: "; 
      cin >> menuChoice; 

      if (menuChoice == 1) 
      { 
       string name; 
       string units; 
       int quantity; 
       double cost; 

       cout << endl; 
       cout << "Enter Item Name: " << endl; 
       cin.ignore(256, '\n'); 
       getline(cin, name); 

       cout << "Enter Item Units (eg. Ounces, Cans): " << endl; 
       getline(cin, units); 

       cout << "Enter Number of Units Needed: " << endl; 
       cin >> quantity; 

       cout << "Enter Cost of Item Per Unit: " << endl; 
       cin >> cost; 

       Item Item1(name, units, quantity, cost); 

       sl.addItem(&Item1); 

       //sl.displayList(); 

      } 

      else if (menuChoice == 2) 
      { 
       string name; 

       cout << "Please enter the name of the Item you wish to remove: " << endl; 
       getline(cin, name); 

       sl.removeItem(name); 
      } 

      else if (menuChoice == 3) 
      { 
       sl.displayList(); 

       cout << "Total Price: " << sl .totalPrice() << endl << endl; 
      } 
     } while (menuChoice != 4); 

return 0; 

}

Список Класс:

List::List() 
{ 
arrayEnd = 0; 
for (int count = 0; count < 4; count++) 
{ 
    shoppingList[count] = NULL; 
} 
} 

void List::addItem(Item* inputItem) 
{ 
shoppingList[arrayEnd] = inputItem; 
arrayEnd++; 
} 

void List::removeItem(string itemName) 
{ 
int removedItem = 0; 

for (int count = 0; count < arrayEnd; count++) 
{ 
    if (itemName == shoppingList[count]->getItemName()) 
    { 
     shoppingList[count] = NULL; 

     removedItem = count; 
    } 
} 

for (int count = 0; count < arrayEnd; count++) 
{ 
    if (count > removedItem) 
    { 
     shoppingList[count - 1] = shoppingList[count]; 
     shoppingList[count] = NULL; 

     arrayEnd = arrayEnd - 1; 
    } 
} 
} 

double List::totalPrice() 
{ 
double totalPrice = 0.0; 

if (shoppingList[0] == NULL) 
{ 
    cout << "There are no items in the list" << endl; 
} 
else 
{ 
    for (int count = 0; count < arrayEnd; count++) 
    { 
     totalPrice += shoppingList[count]->getUnitPrice() * shoppingList[count]->getNumberToBuy(); 
    } 
} 

return totalPrice; 
} 

void List::displayList() 
{ 
if (shoppingList[0] == NULL) 
{ 
    cout << "There are no items in the list" << endl; 
} 
else 
{ 
    for (int count = 0; count < arrayEnd; count++) 
    { 
     cout << "Item: " << shoppingList[count]->getItemName() << endl; 
     cout << "Units: " << shoppingList[count]->getItemUnit() << endl; 
     cout << "Quantity: " << shoppingList[count]->getNumberToBuy() << endl; 
     cout << "Subtotal: " << shoppingList[count]->getUnitPrice()*shoppingList[count]->getNumberToBuy() << endl << endl; 
    } 
} 
} 
+2

'sl.addItem (& Item1);' Вы храните указатели на локальную переменную. Когда эта переменная выходит за пределы области видимости, этот указатель уже недействителен. Почему вы все равно используете указатели? Почему бы просто не хранить объекты? – PaulMcKenzie

+4

'Я работаю над этим в течение 2 дней прямо сейчас и не могу понять это (и не мог бы мой TA)' - Очень грустно, что люди на SO могут выявить проблему в течение нескольких минут, если не секунды, и у вас есть TA что не может определить проблему через 2 дня. – PaulMcKenzie

+0

@PaulMcKenzie Очень хорошо сказано! – vsoftco

ответ

3

Вот проблема:

Item Item1(name, units, quantity, cost); 
sl.addItem(&Item1); 

Item1 находится внутри блока if, поэтому он будет разрушен на выходе из блока. Поэтому вы добавляете указатель на объект, который перестает существовать, и bam, seg fault. Технически вы остаетесь с так называемым болтающимся указателем. Это очень опасный зверь.

PS: Я бы изменил свою TA, если бы я был вами, поскольку это некоторая распространенная ошибка C++, о которой должны знать достойные пользователи C++.

+0

Спасибо, есть ли у вас предложения о том, где мне нужно создать объект Item и где вызывать addItem, чтобы он не удалял его? –

+0

@EvanMace Если вы настаиваете на использовании указателей, вы должны, вероятно, создать объект динамически, используя 'new', например' sl.addItem (новый Item {name, unites, quantity, cost}); 'поэтому он не уничтожается , Но ваш текущий дизайн немного странный, поскольку список не управляет указателями, поэтому ваша ответственность - «удалить» их. Поэтому я предлагаю либо сделать список, управляющий указателями, т. Е. При удалении, 'delete shoppingList [count];' непосредственно перед 'shoppingList [count] = NULL;' в 'List :: removeItem'. – vsoftco

+0

@EvanMace Подумайте больше, если вам действительно нужен список указателей. Вероятно, лучше сохранить копию элементов, а не указателей. Конечной альтернативой является использование списка ['std :: shared_ptr'] (http://en.cppreference.com/w/cpp/memory/shared_ptr). Это «умные указатели» и автоматическое управление их ресурсом. – vsoftco