简体   繁体   English

如何在C ++中从结构数组中删除项目?

[英]How to remove an item from a structure array in C++?

I have the following array structure (linked list): 我具有以下数组结构(链接列表):

    struct str_pair   
     {  
       char ip  [50] ;  
       char uri [50] ;  
       str_pair *next ;  
     } ;

str_pair *item;

I know to create a new item, I need to use 我知道要创建一个新项目,我需要使用

item = new str_pair;

However, I need to be able to loop through the array and delete a particular item. 但是,我需要能够遍历数组并删除特定项。 I have the looping part sorted. 我有循环部分排序。 But how do I delete an item from an array of structures? 但是,如何从结构数组中删除项目?

What you've shown is not an array of struct , but a linked list of struct containing arrays (of type char ). 您显示的不是struct数组,而是包含数组( char类型)的struct的链表。


An array of struct would look like this: 数组struct如下所示:

str_pair array_of_structs[10];
    // or:
str_pair* dynamically_allocated_array_of_structs = new str_pair[10];

If you actually have something like this, you don't need to delete single items from an array. 如果确实有类似的内容,则无需从数组中delete单个项目。 Let's say you've initialized your array as follows: 假设您已按照以下方式初始化了数组:

str_pair* array_of_structs = new str_pair[10];

Then you delete the whole array (including all of its items) using: 然后,使用以下命令删除整个数组(包括其所有项):

delete[] array_of_structs;

Again, you can't delete single items in an array allocated with new[] ; 同样,您不能delete分配有new[]的数组中的单个项目; you perform a delete[] on the whole array. 您对整个数组执行delete[]


If, on the other hand, you intended to say " linked list of struct ", then you'd generally delete an item similarly to the following: 另一方面,如果您打算说“ struct链表 ”,那么通常将删除与以下内容类似的项目:

str_pair* previous_item = ...;
str_pair* item_to_delete = previous_item->next;

if (item_to_delete != 0)
{
    previous_item->next = item_to_delete->next;  // make the list "skip" one item
    delete item_to_delete;                       // and delete the skipped item
}

Or, in English: Find the item ( A ) preceding the item which you want to delete ( B ), then adjust A 's "next" pointer so that B will be skipped in the list, then delete B . 或者,用英语:找到要删除的项目( B )之前的项目( A ),然后调整A的“下一个”指针,以便将B跳过列表,然后删除B。

You need to be careful with special cases , ie when the item to be removed from the list is the first item or the last one. 您需要注意特殊情况 ,例如,要从列表中删除的项目是第一项还是最后一项。 The above code is not sufficient when you want to delete the first item in the list, because there will be no previous_item . 当您要删除列表中的第一项时,上面的代码是不够的,因为将没有previous_item In this case, you'd need to change the pointer to the list's first element to the second element. 在这种情况下,您需要将指向列表的第一个元素的指针更改为第二个元素。


Your code: 您的代码:

 void deleteitem(char *uri) { str_pair *itemtodelete; curr = head; while (curr->next != NULL) { if ((strcmp(curr->uri, uri)) == 0) { itemtodelete = curr; curr = itemtodelete->next; delete itemtodelete; curr = head; return; } curr = curr->next; } } 

Some things are wrong here: 这里有些错误:

  • If head is null, the test curr->next != NULL will cause a segfault. 如果head为null,则测试curr->next != NULL将导致段错误。 (You must never dereference a null pointer!) (您绝不能取消引用空指针!)

  • Your code for removing an item from the list is completely incorrect. 您用于从列表中删除项目的代码是完全错误的。 Worst of all, you delete a node without changing the previous item's next pointer. 最糟糕的是,您在不更改上一项的下一个指针的情况下删除了一个节点。 The previous item will thus reference an item that's no longer there. 因此,上一项将引用不再存在的项。

  • A detail: curr = head; 详细信息: curr = head; before the return statement doesn't do anything useful at all. return语句之前根本没有任何用处。

Suggested code: 建议的代码:

Do it in two steps: One function to find the node to be deleted via its attached uri , and one function to remove the node. 分两步执行:一种功能是通过连接的uri查找要删除的节点,另一种功能是删除节点。 You could separate it even better than the code below does, but it should be a starting point: 您可以比下面的代码更好地分离它,但这应该是一个起点:

str_pair* finditemwithuri(char* uri)
{
    str_pair* current = head;
    while (current)
    {
        if (strcmp(current->uri, uri) == 0) return current;
        current = current->next;
    }
    return 0;
}

void deleteitem(char* uri)
{
    // find linked list node with that uri; abort if uri not in list
    str_pair* itemtodelete = finditemwithuri(uri);
    if (!itemtodelete) return;

    // special case: node to be deleted is the list's head
    if (itemtodelete == head)
    {
        head = itemtodelete->next;
        delete itemtodelete;
        return;
    }

    // else, iterate over list nodes
    // up to the one preceding the node to be deleted
    str_pair* current = head;
    while (current)
    {
        if (itemtodelete == current->next)
        {
            current->next = itemtodelete->next;
            delete itemtodelete;
            return;
        }
        current = current->next;
    }
}

Just use std::list. 只需使用std :: list。 There's no reason to manually write such a construct. 没有理由手动编写这样的结构。

http://msdn.microsoft.com/en-us/library/802d66bt(VS.80).aspx http://msdn.microsoft.com/zh-CN/library/802d66bt(VS.80).aspx

std::list offers remove. std :: list优惠已删除。

You can delete it using the ordinary delete keyword, but that will not shift all other members of the array. 您可以使用普通的delete关键字将其删除,但这不会移动数组的所有其他成员。 If you want this kind of behaviour take a look at std::vector or something like that. 如果您想要这种行为,请看一下std :: vector或类似的东西。

As others have pointed out, this is a Linked List, not an array. 正如其他人指出的那样,这是一个链表,而不是数组。 To answer your question for linked lists: 要回答链表的问题:

To insert an item: 要插入项目:

str_pair* p = // iterate over the linked list to your insertion point
str_pair* item = new str_pair;
item->next = p->next;
p->next = item;

That inserts a new str_pair after p. 这将在p之后插入新的str_pair

To remove an item: 删除项目:

str_pair* p = // iterate to just before your deletion point
str_pair* item = p->next;
p->next = p->next->next;
delete item;

This will remove the element after p 这将删除p之后的元素

To do this with your code: 要使用您的代码执行此操作:

void deleteitem(char *uri)
{
    str_pair *previous = NULL;
    curr = head;

    while (curr != NULL) {
        if ((strcmp(curr->uri, uri)) == 0) {

            // modify the previous element to skip over our deleted one
            if (previous)
                previous->next = curr->next;
            else
                head = curr->next;

            // safely delete the element, now that no one points to it
            delete curr;

            curr = head;
            return;
        }

        // always remember our previous element, so we can fix its 'next' pointer
        previous = curr;
        curr = curr->next;
    }
}

You need a better add method too: 您还需要更好的添加方法:

void additem(char *uri, char *ip)
{
    curr = head;

    // traverse the list until we're at the last item
    while (curr->next != NULL) {
        curr = curr->next;
    }

    // attach a new element to the list
    curr->next = new str_pair;

    // go to that new element
    curr = curr->next;

    // set the values of the new element
    strcpy(curr->ip, ip);
    strcpy(curr->uri, uri);
    curr->next = NULL;

    curr = head;

}

可能不在主题之列,但是为什么不使用std::list库呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM