c ++ удаляет 1 элемент динамического массива? - PullRequest
0 голосов
/ 01 марта 2012

Я работаю над программой, которая вводит данные книги в структуру и удаляет элемент по запросу пользователя.Тем не менее, я испытываю трудности с поиском лучшего способа удалить запрошенную книгу.Как вы думаете, я направляюсь в правильном направлении?

struct Data{                        //struct of data
    string title;
    string author;
    string publisher;
};

void remove (Data *ptr, string title, string author, string publisher, int num)
{
    string book_rem;
    cout << "What book do you want to remove?" << endl;
    getline (cin, book_rem);

    for (int i=0;i<num;i++)
    {
        if (ptr[i].title == book_rem) // check for equality
            {
               for (int j = 0; j < num; j++)  //shift over elements in new array
               ptr[j] = ptr[j+1];
               ptr[j-1] = 0;
            }   
        else 
           {
            cout << "book not found!" << endl;
           }
    }
}

Я знаю, что моя логика отключена? .. но мой преподаватель сказал, что я был близок .. если у вас есть хорошие ресурсы или ссылки, пожалуйста, отправьте их таким образомэти указатели меня немного смущают из-за того, как лучше всего это сделать.

Ответы [ 5 ]

2 голосов
/ 01 марта 2012

В цикле for вы отмечаете, что книга не была найдена сразу после первого if (ptr[i].title == book_rem). Что, если книга присутствует как второй элемент или после него.

Вы должны разделить свою работу на две части следующим образом:

  • Поиск книги.
  • Удалите его, если он найден, в противном случае выведите «Not Found».

Он такой, какой он может быть внутри цикла:

for (int i = 0 ; i < num ; i++) {
    if (ptr[i].title == book_rem) // check for equality
    {
        break;
    }  
}

А затем за пределами цикла проверьте, найдена ли книга, и выполните необходимые действия:

if ( i < num ) {// Book was found as i is less than size.
    /*
        You don't have to shift over elements in the array.
        I'm assuming your list isn't sorted, so you can just transfer 
        the last element in the array to the position pointed by i, and 
        then decrement the size by 1. 
    */
    // Copy all the elements from ptr[num-1] to ptr[1].
    num = num - 1;
}
else {
    cout << "book not found!" << endl;
}
1 голос
/ 01 марта 2012

Вы можете просто заменить вместо копирования.

void swap(Data &d1, Data &d2)
{
  std::swap(d1.title, d2.title);
  std::swap(d1.author, d2.author);
  std::swap(d1.publisher, d2.publisher);
}


void updateIndexes(int oldId, int newId)
{
  // update all indexes that use oldId to newId here
}

void remove (Data *ptr, int & num)
{
    string book_rem;
    cout << "What book do you want to remove?" << endl;
    getline (cin, book_rem);

    for (int i = 0; i < num; ++i)
    {
        if (ptr[i].title == book_rem)
        {
            swap(ptr[i], ptr[num-1]);
            --num;
            updateIndexes(num, i); // optional updating of indexes if any
            return;
        }
    }
    cout << "book not found!" << endl;
}
1 голос
/ 01 марта 2012

Вместо написания собственного контейнера, используйте std::map (сопоставьте название книги с автором + издателем), std::set или std::list. Или, по крайней мере, используйте std::find_if, чтобы найти книгу. С std::set в контейнере может храниться только одна комбинация заголовок + автор + издатель. С std::map вы сможете быстро найти издателя / автора по названию, с std::list вы сможете быстро вставлять / удалять книги (и сможете иметь дубликаты в контейнере).

1 голос
/ 01 марта 2012

Вместо того, чтобы изобретать велосипед, я бы предложил использовать std :: list, учитывая задачу, которую вы выполняете. Список (в отличие от вектора) обеспечивает внутренне эффективное удаление и вставку элементов. Однако, в отличие от вектора, память, используемая списком, не является смежной, то есть не гарантируется, что элементы будут «соседствовать» в памяти. Если вы постоянно удаляете и добавляете элементы, лучше всего использовать список, в то время как если вам нужен постоянный доступ к элементам «случайным образом», вам, скорее всего, будет лучше использовать вектор.

Вы можете легко удалить элемент из списка: используйте list::erase, чтобы удалить элемент с помощью итератора, и list::remove, чтобы удалить элемент по значению (что вам подходит). Более подробную информацию можно найти здесь: http://www.cplusplus.com/reference/stl/list/

1 голос
/ 01 марта 2012
void remove (Data *ptr, int & num)
{
    string book_rem;
    cout << "What book do you want to remove?" << endl;
    getline (cin, book_rem);

    for (int i = 0; i < num; i++)
    {
        if (ptr[i].title == book_rem) // check for equality
        {
            for (int j = j; j + 1 < num; j++)  //shift over elements in new array
            {
                ptr[j] = ptr[j+1];
            }
            num--;        // this will modify the original
            return;
        }
    }
    cout << "book not found!" << endl;
}
  • 2-й, 3-й и 4-й параметры нигде не используются, поэтому я удалил их
  • Передача num по ссылке позволяет изменять исходные
  • Вынеобходимо сдвинуть все элементы после удаленного, поэтому j должен начинаться с i
  • Вы получаете доступ к массиву по индексу j+1, поэтому условие должно быть j+1 < num
  • Оператор return завершил бы функцию, если элемент был удален
  • Если функция достигает последней строки, это означает, что совпадение не найдено
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...