Single linked list

牧云@^-^@ 提交于 2019-12-02 05:42:40

From pop()

            if(head->product_code == code)
            {
                    temp = head;
                    head = head->next;
                    free(temp);

                    // Finished Deleting product
                    return;
            }

In the case of there only being one item, 'head' and 'tail' would be pointing to the same node. However, if you pop this one item, 'head' will be adjusted but 'tail' will still be pointing to the free'd node. This will leave a bad pointer, which may cause your computer to explode.

Addendum: Similarly, 'new_product' will be dangling if you ever pop the last node that was pushed, and clean_up() will leave the 'tail' pointer dangling as well. Even if the code sample provided will never dereference these after they're free'd, dangling pointers in C code should always be treated as "potentially dangerous".

strncpy(new_product->product_name, name, sizeof(new_product->product_name));

if the string is longer than the size you have it won't be terminated correctly.

I see no reason why new_product should be global and every reason why it should not be.

It looks like you're on the right track, but there are issues. I would remove the global variables, and instead have a list_t struct (containing head and tail) that you pass into functions. As others have noted, you may also want to make the list generic by using (e.g.) a node_t type and void* data pointer.

Generally push and pop are used to refer to adding or removing an item at the beginning, not an arbitrary location (as you do); this is just a question of naming.

If you had product_name char *product_name instead, that would allow you to remove the length limitation as well as the need for strncpy. You would just have the caller allocate the string, and then free it in clean_up.

You could consider using a enum to improve your menu's readability. For "Check if this is in the first node - deleting from head" (same for tail), you should just compare head to product, not compare the codes.

After "tail = previous", you should set tail->next to NULL.

Agree with the issues raised by goldPseudo and thaggie/Steven.

In push(), replace strncpy() with strlcpy() to ensure the destination string is always NUL terminated.

In cleanup(), I'd suggest that you remove the exit(0); statement -- you don't need it. Exiting a programme from within a subroutine is generally not the best thing to do.

You should take away one lesson from creating your first singly linked list, and that is, singly linked lists are generally not very useful in the real world because:

  • They're too hard to manipulate. Just look at the complexity of your pop() subroutine.
  • Relatively slow because you have to start at the beginning of the list each time you want to retrieve an element from the list.

You should now attempt to write your first doubly linked list. While doubly linked lists are more complex to implement, they are easier to manipulate (especially when deleting an element) than singly linked lists.

Is there any reason you call exit(0) from clean_up function? I think this is potential dangerous, since you don't give a chance to the user to finish program correctly.

As well I would suggest you to use data encapsulation when you building up you data structure:

typedef struct
{
    int product_code;
    char product_name[128];
    int product_cost;
    list_node *next;
} list_node;

typedef struct
{
   list_node* head;
   list_node* tail;
   list_node* current;
   int        size;
} list;

Also it's a good practice to use trail dummy node at the head of your list to make your code more generic.

Following normal naming convensions, push and pop are related to stacks - i.e. push() should add an item to the top of the stack (you add to the tail of the list, which is fine!), and pop() should return and remove the item from the top of the stack (you search for a named item anywhere in the list and remove it.)
Function names aside, I would suggest a more generic (abstract) implementation of the list, where the content of a node is a pointer to arbitrary data (which in your special case will later be a product_data). This way your linked list can be re-used for any content, and is easier to debug, read and to maintain.
It would also be a better idea not to have stuff global, but rather permit multiple instances of a list. The normal C way is to keep the data in a struct, and then to pass an instance as first argument to each function.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!