简体   繁体   中英

C Program Sorted Linked List

This program is supposed to create a sorted list and sort each user by first and last name. I cant seem to figure out how to sort the names properly.

I only have an issue with the append_to_list function, the rest of the functions work fine.

When I first start inputting names:

user ID:    Last Name:    First Name:
3                Alex          Alex
2                Jones         Alex
1                andrew        john

it sorts fine until I enter a name that should sort inbetween two of the names when I enter the name Andrew, Alex this happens.

 user ID:    Last Name:    First Name:
 4                Andrew        Alex
 3                Alex          Alex
 2                Jones         Alex
 1                andrew        john

but Andrew, Alex should be between user 2 and 3


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "user.h"
#include "readline.h"

// function append_to_list takes user input from user, id, name and puts it     to the end of the list
// as well as sorts each name alphabetically
struct user *append_to_list(struct user *family)
{
    struct user *cur, *prev, *new_node;

    // generate memory
    new_node = malloc(sizeof(struct user));

    if (new_node == NULL) { 
        printf("malloc failed in append\n");
        return family;
    }

    printf("Enter user ID: \n");
    scanf("%d", &new_node->number);
    printf("Enter user last name: \n");
    read_line(new_node->last_name,NAME_LEN);
    printf("Enter user first name: \n");
    read_line(new_node->first_name,NAME_LEN);

    for( cur=family; cur != NULL; cur = cur->next) {
        if (new_node->number == cur->number) {
                printf("user already exists: %s, %s\n",new_node->first_name,     new_node->last_name);
                free(new_node);
                return family;
        }   
    }       
    for (cur=family, prev = NULL; cur != NULL 
        && (strcmp(new_node->first_name,cur->first_name) < 0) 
        && (strcmp(new_node->last_name,cur->last_name) < 0); 
            prev = cur, cur = cur->next) { 

        if((strcmp(new_node->last_name,cur->last_name) < 0)) break;

        if((strcmp(new_node->first_name,cur->first_name) == 0)) 

        if((strcmp(new_node->first_name,cur->first_name) < 0)) break;
        ;
        }
        // use strcmp == 0 to see if name already exists
        if (cur != NULL && (strcmp(new_node->first_name,cur->first_name) == 0)
            && (strcmp(new_node->last_name,cur->last_name)) == 0) 
        {
                printf("user already exists: %s, %s\n",new_node->first_name, new_node->last_name);
                free(new_node);
                return family;
        }

    // append the linkedlist to the end
    new_node->next = cur;
    // check to see if the node is empty
    if (prev == NULL) {
        return new_node;
    } else  {
        prev->next = new_node->next;
        return family;
    }
}
// function delete_from_list removes a user from the family
struct user* delete_from_list(struct user *family) 
{
    struct user *prev, *cur;
    int id;
    int not_found = 0;
    printf("Enter user ID: \n");
    scanf("%d", &id);

    for (cur = family, prev = NULL; cur != NULL; prev = cur, cur = cur->next) {
        if (id == cur->number) {
                // if only one user on family
            if (prev == NULL) {
                family = cur->next;
            // if user is in the middle of family
            // connects prev node to cur node
            } else {
                prev->next = cur->next;
            }
            printf("user deleted: %s ,%s\n",cur->first_name, cur->last_name);
            free(cur);
        }
        else 
            not_found = 1;
    }
    if (not_found == 1) {
        printf("user not found\n");
    }
    return family;
}   
// function find_user searches the family by ID and matches it with the users name
void find_user(struct user *family)
{
    struct user *p = family;
    int id;
    int count = 0;
printf("Enter user ID: \n");
scanf("%d", &id);

    // compares the family with the user entered ID
    // if the ID is the same count set to 1
    if (p != NULL) {
        for (p = family; p != NULL; p = p->next) {
            if (id == p->number) {
                count = 1;
                break;
            }
        }
    }
    // if count is 1 we know the function found that specific user
    if ( count == 1) {
        printf("user found: %s, %s\n", p->last_name, p->first_name);
    } else {
        printf("user not found");
    }
}

// function printList prints the entire family
void printList(struct user *family)
{
    struct user *p;
    printf("user ID:\tLast Name:\tFirst Name:\n");
    for (p = family; p != NULL; p = p->next) {
        printf("%d\t\t%s\t\t%s\n", p->number, p->last_name, p->first_name);
    }

}

// function clearList clears the entired linked list
void clearList(struct user *family)
{
    struct user *p;
    while (family != NULL) {
        p = family;
        family = family->next;
        if (p != NULL) {
            free(p);
        }
    }
}

The problem is in the way you compare nodes:

for (cur=family, prev = NULL; cur != NULL 
    && (strcmp(new_node->first_name,cur->first_name) < 0) 
    && (strcmp(new_node->last_name,cur->last_name) < 0); 
        prev = cur, cur = cur->next) { ... }

You should skip nodes that have a lesser family or (the same family name AND a lesser first name). Fix the comparison this way:

for (cur=family, prev = NULL;
     cur != NULL 
     && ((strcmp(new_node->first_name, cur->first_name) < 0) 
     ||  ((strcmp(new_node->first_name, cur->first_name) == 0)
     &&   (strcmp(new_node->last_name,cur->last_name) < 0))); 
     prev = cur, cur = cur->next) { ... }

And simplify the subsequent code. You actually do not need any code. The loop will stop at the insertion point. Just check if the same last name and first name exists (but what if there are 2 John Does?) and insert between prev and cur , or before family if prev is NULL .

The for loop looks ugly: hard to read, easy to get wrong. Write a separate comparison function that takes 2 nodes and returns -1, 0, +1 according to the phone book order. You will use this function for append_to_list and delete_from_list , writing less code, more readable and more consistent.

我认为重叠比较运算符是一个更好的主意,然后用一些现有算法对您的列表进行排序。

You have problem with conditions in this loop:

 for (cur=family, prev = NULL;
        cur != NULL && (strcmp(new_node->first_name,cur->first_name) < 0) 
                    && (strcmp(new_node->last_name,cur->last_name) < 0); 
                prev = cur, cur = cur->next) 

Loop will not execute:

(cur=family, family exist)
cur != NULL -> True
(Alex == Alex)
((strcmp(new_node->first_name,cur->first_name) -> 0) < 0 -> False
(Andrew > Alex)
((strcmp(new_node->last_name,cur->last_name) -> 1) < 0 -> False
True && False && False -> False

As a result, you will add new record at the beginning.

Furthermore in the loop you have a bad 'if' code:

if((strcmp(new_node->first_name,cur->first_name) == 0)) 

if((strcmp(new_node->first_name,cur->first_name) < 0)) break;
;

Doc. strcmp

Tip: Delete useless code in question. Cheer!

The for loop will stop right at the point of insertion (between the previous and cur node).

The next part will sort the list even if the new_node is greater than the last node. If the new node is greater than the last node, cur becomes null, which is //assigned to new_node_>next. prev is therefore equal to cur; thus, prev->next = new_node;

           for (cur=family, prev = NULL; cur!=NULL && ((strcmp(new_node->first_name,
           cur->first_name)>0) || ((strcmp(new_node->first_name,
            cur->first_name)==0)&&(strcmp(new_node->last_name,
            cur->last_name)>0))); prev = cur, cur = cur->next);

      new_node->next = cur;
           if(prev==NULL)
            return new_node;
           else {
           prev->next = new_node;
           return family;
           }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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