C结构和链表挣扎

时间:2017-06-28 23:09:28

标签: c data-structures struct linked-list

所以,我们刚刚开始在我的在线课程中学习链接列表和数据结构,但我一直在努力解决这个问题。我对指针有一个大致的了解但是当你把所有东西组合在一起时,我会完全迷失方向。

因此对于这个程序,我应该处理员工数据并通过使用结构和指针来访问它。但是,我认为我没有将正确的值传递给函数,因为数据没有保存,我无法访问它。任何帮助将不胜感激。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct address {
    char street[49];
    char city[29];
    char state[2];
    char zip[5];
};

struct data{
    char name[39];
    struct address addy;
    float salary;
    struct data *next;
} emp;

void LIST(struct data* head);
void INSERT(struct data* head, char* name, struct address addr, float salary);
void DELETE(char* name, struct data* head);
void EDIT(struct data* head, char* name, struct address addr, float salary);
void CALCPAYROLL(struct data* head);
void HELP();

int main()
{
    char input[15];
    int quitter = 1;
    struct data *head = NULL;
    head = malloc(sizeof(emp));
    if (head == NULL){
        return 1;
    }

    while(quitter == 1)
    {
        printf(" enter command:  \n");
        fgets(input,15, stdin);
        input[strlen(input) -1] = '\0';
        if((strcmp(input, "List") == 0) || (strcmp(input, "list") == 0))
        {
            LIST(head);
        }
        if((strcmp(input, "Insert") == 0) || (strcmp(input, "insert") == 0))
        {
            scanf("%s-%s-%s-%s-%s-%f", head->name, head->addy.street, head->addy.city, head->addy.state, head->addy.zip, &head->salary);
            INSERT(head, head->name, head->addy, head->salary);
        }
        if ((strcmp(input, "Delete") == 0) || (strcmp(input, "delete") == 0))
        {
            DELETE(head->name, head);
        }
        if ((strcmp(input, "Edit") == 0) || (strcmp(input, "edit") == 0))
        {
            EDIT(head, head->name, head->addy, head->salary);
        }
        if ((strcmp(input, "Payroll") == 0) || (strcmp(input, "payroll") == 0))
        {
            CALCPAYROLL(head);
        }
        if ((strcmp(input, "Help") == 0) || (strcmp(input, "help") == 0))
        {
            HELP();
        }
        if ((strcmp(input, "Quit") == 0) || (strcmp(input, "quit") == 0))
        {
            printf("============\nGood bye!\n");
            quitter = 0;
        }
    }
    return 0;
}

void LIST(struct data* head)
{
    struct data* temp = head;
    while (temp) {
        printf("%s\n%s\n%s, %2s %5s\n%9.2f\n-----\n", temp->name, temp->addy.street, temp->addy.city, temp->addy.state, temp->addy.zip, temp->salary);
        temp = temp->next;
        printf("%s\n%s\n%s, %2s %5s\n%9.2f\n-----\n", temp->name, temp->addy.street, temp->addy.city, temp->addy.state, temp->addy.zip, temp->salary);
        temp = temp->next;
    }
}

void INSERT(struct data* head, char* name, struct address addr, float salary)
{
    struct data* newEmployee = NULL;
    newEmployee = (struct data*)malloc(sizeof(emp));

    strcpy(newEmployee->name, head->name);
    newEmployee->salary = head->salary;

    strcpy(newEmployee->addy.street, head->addy.street);

    strcpy(newEmployee->addy.city, head->addy.city);

    strcpy(newEmployee->addy.state, head->addy.state);

    strcpy(newEmployee->addy.zip, head->addy.zip);
    struct data* temp = head;
    while(temp->next && temp->next->name > newEmployee->name) 
    {
        temp = temp->next;
    }
    newEmployee->next = temp->next;
    temp->next = newEmployee;

}

void DELETE(char* name, struct data* head)
{
    char del[39];
    scanf("%39s", del);
    struct data * toBeDeleted = NULL;
    struct data * temp = head;
    while (strcmp(del, temp->name) == 0) 
        {
           strcpy(temp->next->name, temp->name);

           temp->addy = temp->next->addy;
           temp->salary = temp->next->salary;
           toBeDeleted = temp->next;
           temp->next = temp->next->next;
           free(toBeDeleted);
           printf("RECORD DELETED\n");
        }
        temp = temp->next;
        printf("RECORD NOT FOUND\n");
}

void EDIT(struct data* head, char* name, struct address addr, float salary)
{
    char edit[39];
    scanf("%39s", edit);
    struct data* temp = head;
    while (strcmp(edit, temp->name) == 0) 
        {
            temp->addy = addr;
            temp->salary = salary;

            printf("RECORD EDITED\n");
            return;
        }
        temp = temp->next;
    printf("RECORD NOT FOUND\n");
}

void CALCPAYROLL(struct data* head)
{
    struct data* temp = head;
    float total;
    while (temp) 
    {
        total += temp->salary;
        temp = temp->next;
    }
    printf("total payroll: %f", total);
}

void HELP()
{
    printf("commands:\n");
    printf("List - shows the list of employees\n");
    printf("Insert - Creates a new employee record\n");
    printf("Delete - Deletes an existing employee record\n");
    printf("Edit - Modifies the contents of an employee record\n");
    printf("Payroll - Calculates and displays the total payroll\n");
    printf("Help - Displays the set of available commands\n");
    printf("Quit - Prints the message ""good bye!"" and exits the program" );
}

2 个答案:

答案 0 :(得分:1)

首先,我要赞扬你做一个非常简洁的演讲。代码易读且易于理解。我发现它唯一的错误是所有大写名称通常都是为用#define声明的宏和常量保留的。

下面:

struct data{
    char name[39];
    struct address addy;
    float salary;
    struct data *next;
} emp;                  // declaring a variable at the same time as the structure? Not very nice.

我看到在您创建第一个列表项(头部)时发生的问题。 Insert必须能够修改head参数。这需要额外的间接水平。 INSERT还应返回错误代码,如果malloc失败,执行此操作的常用方法是在出错时返回负值(-1)。

void INSERT(struct data* head, char* name, struct address addr, float salary)

// should be 
int INSERT(struct data** head, char* name, struct address addr, float salary)

当条目head为NULL时,您必须稍微更改逻辑以使用新分配的缓冲区设置head。然后调用INSERT成为。

   if (INSERT(&head, name, &addr, salary) < 0)
   {
      // error !
   }

我在INSERT中看到数据分配存在问题。

struct data* newEmployee = NULL;
//newEmployee = (struct data*)malloc(sizeof(emp)); // ?? you allocate a struct data, what's emp?
// should read
newEmployee = (struct data*)malloc(sizeof(struct data)); 

删除和编辑不起作用。他们找不到写的员工。您应该考虑使用find()函数,如下所示:

data* FindEmployeeData(data* head, const char* name)
{
   while (head)
   {
      if (strcmp(head->name, name) == 0)
        break;
      head = head->next;
   }
   return head;
}

在为员工编写新业务时,这可以节省时间。

在INSERT中:

while(temp->next && temp->next->name > newEmployee->name) 

我认为字符串应与strcmp() ...

进行比较

在DELETE中:与INSERT相同,该函数可以更改列表的头部

int DELETE(data** head, const char* name); // returns -1 on error.

下面:

scanf("%s-%s-%s-%s-%s-%f", head->name, head->addy.street, head->addy.city, head->addy.state, head->addy.zip, &head->salary);

当用户输入的名称,地址,州,街道,城市或邮政编码对于您分配的空间而言太长时,会发生

答案 1 :(得分:0)

您无法访问数据,因为在INSERT函数头中必须是双指针,因为当您想在链表的头部插入某些内容时,您必须更改存储的地址在头上。在您的代码中,您正在修改头部的副本。请记住,在C 中,所有内容都是为值传递。这意味着要修改指针中的地址内容,您必须在函数中传递指针的地址。