使用指针在单链表中打印反向

时间:2013-10-20 21:23:51

标签: c linked-list

我一直在尝试这段代码。

我认为逻辑正常但是当调用display_rev函数时程序突然终止

这里是display_rev的代码

void display_rev(emp_node *head) {
    emp_node *p=head, *q;
    while(p->next != NULL)
        p=p->next;
    while(p!=head || p==head){
        q=head;
        display_rec(p);
        while(q->next != p)
            q=q->next;
        p=q;
    }
}

这是我的整个代码

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

//Declarations===============================================================

typedef struct //employee record
{
    int emp_id;
    char name[150];
    char mob_no[11];
    float salary;
    int proj[5];
    struct emp_node *next;
} emp_node;

emp_node* add_rec(emp_node*);
emp_node* create_db(emp_node*);
emp_node* search_db(emp_node*, int);
emp_node* delete_rec(emp_node*, int);
void read_name(emp_node*);
void read_mob(emp_node*);
void display_db(emp_node*);
void display_rec(emp_node*);
void display_rev(emp_node*);
void modify_rec(emp_node*);
void swtch(emp_node*);
//===========================================================================

int main() {
    char ans;
    emp_node *head = NULL;
    head = create_db(head);
    display_db(head);
    do {
        swtch(head);
        printf("\n\n\tDo you want to continue (y/n) : ");
        getchar();
        scanf("%c", &ans);
    } while (ans == 'y' || ans == 'Y');
    return 0;
}

//Definitions================================================================

emp_node* create_db(emp_node *head) //database creation
{
    int i = 1, no;
    emp_node *p;
    printf("Enter number of employees:");
    scanf("%d", &no);
    printf("\n\n");
    head = (emp_node *) malloc(sizeof(emp_node));
    head = add_rec(head);
    head->next = NULL;
    p = head;
    while (i < no) {
        p->next = (emp_node *) malloc(sizeof(emp_node));
        p = p->next;
        p = add_rec(p);
        p->next = NULL;
        i++;
    }
    return head;
}
emp_node* add_rec(emp_node *p)  //new record
{
    int j;
    printf("\n\tEmployee ID : ");
    scanf("%d", &(p->emp_id));
    printf("\n\tFirst Name:");
    read_name(p);
    printf("\n\tMobile No.:");
    read_mob(p);
    printf("\n\tSalary :");
    scanf("%f", &(p->salary));
    printf(
            "\n\tEnter \"1\" for the projects employee is working on, otherwise enter \"0\": \n");
    for (j = 0; j < 5; j++) {
        printf("\n\t\tProject No. %d : ", j + 1);
        scanf("%d", &(p->proj[j]));
        while (p->proj[j] != 1 && p->proj[j] != 0) {
            printf("\n\nInvalid entry!! Please re-enter.");
            printf("\n\t\tProject No. %d : ", j + 1);
            scanf("%d", &(p->proj[j]));
        }
    }
    printf("\n\n\n");
    return p;
}
void read_name(emp_node *p)  //validation for name
{
    int j, len;
    scanf("%s", p->name);
    len = strlen(p->name);
    for (j = 0; j < len; j++) {
        if (!isalpha(p->name[j])) {
            printf(
                    "\n\n\tInvalid name!!Can contain only characters. Please Re-enter.\n");
            printf("\n\tName : ");
            read_name(p);
        }
    }
}
void read_mob(emp_node *p)  //validation for mobile no.
{
    int j;
    scanf("%s", p->mob_no);
    while (strlen(p->mob_no) != 10) {
        printf("\n\nInvalid Mobile No!!Please Re-enter");
        printf("\n\n\tMobile No.:");
        read_mob(p);
    }
    for (j = 0; j < 10; j++) {
        if (!(48 <= p->mob_no[j] && p->mob_no[j] <= 57)) {
            printf(
                    "\n\nInvalid Mobile No!!Can contain only digits. Please Re-enter.");
            printf("\n\n\tMobile No.:");
            read_mob(p);
        }
    }
}
void display_db(emp_node *head) //displaying whole database
{
    emp_node *p;
    p = head;
    printf("\n\n\t\t******    EMPLOYEE DATABASE    ******\n");
    printf(
            "\n==============================================================================");
    printf("\n Id.\t   Name\t\t Mobile No\t Salary\t Projects\n");
    while (p != NULL) {
        display_rec(p);
        p = p->next;
        printf("\n\n\n");
    }
    printf(
            "\n==============================================================================");
}
void swtch(emp_node *head) //function for menu and switch case
{
    int cho, x;
    emp_node *p;
    printf("\n\n\t\t****** MENU ******");
    printf(
            "\n\n\t1. insert Record\n\t2. Search Record\n\t3. Modify Record\n\t4. Delete Record\n\t5. Display Reverse\n\t6. Exit");
    printf("\n\tWhich operation do you want to perform? ");
    scanf("%d", &cho);
    switch (cho) {
    case 1:
        p=head;
        while(p->next != NULL)
            p=p->next;
        p->next = (emp_node *) malloc(sizeof(emp_node));
        p=p->next;
        p = add_rec(p);
        p->next = NULL;
        display_db(head);
        break;
    case 2:
        printf("\n\n\tEnter employee ID whose record is to be Searched :");
        scanf("%d", &x);
        p = search_db(head, x);
        if (p == NULL)
            printf("\n\nRecord not found.");
        else
            display_rec(p);
        break;
    case 3:
        printf("\n\n\tEnter employee ID whose record is to be modified :");
        scanf("%d", &x);
        p = search_db(head, x);
        if (p == NULL)
            printf("\n\nRecord not found.");
        else
            modify_rec(p);
        display_db(head);
        break;
    case 4:
        printf("\n\n\tEnter employee ID whose record is to be deleted :");
        scanf("%d", &x);
        head = delete_rec(head, x);
        display_db(head);
        break;
    case 5:
        display_rev(head);
    case 6:
        exit(0);
    default:
        printf("Invalid Choice!! Please try again.");
    }
}
emp_node* search_db(emp_node *head, int id) //search database
{
    emp_node *p = head;
    while (p != NULL) {
        if (p->emp_id == id)
            return p;
        p = p->next;
    }
    return NULL;
}
void display_rec(emp_node *p) //display a single record
{
    int j;
    printf("\n %d", p->emp_id);
    printf("\t %10s", p->name);
    printf("\t %10s", p->mob_no);
    printf("\t %05.2f", p->salary);
    printf("\t ");
    for (j = 0; j < 5; j++) {
        if (p->proj[j] == 1)
            printf(" %d,", j + 1);
    }
}
void modify_rec(emp_node *p) //modifying a record
{
    int j, cho;
    char ch1, edt;
    do {
        printf(
                "\n\t1. Name\n\t2. Email Address\n\t3. Mobile No.\n\t4. Salary\n\t5. Date of birth\n\t6. Projects\n");
        printf("Enter your choice : ");
        scanf("%d", &cho);
        switch (cho) {
        case 1:
            printf("\n\tPrevious name:%s", p->name);
            printf("\n\tDo you want to edit ? (y/n)");
            getchar();
            scanf("%c", &ch1);
            if (ch1 == 'y' || ch1 == 'Y') {
                printf("\n\tEnter New Name:");
                read_name(p);
            }
            break;
        case 2:
            printf("\n\tPrevious Mobile No. : %s", p->mob_no);
            printf("\n\tDo you want to edit ? (y/n)");
            getchar();
            scanf("%c", &ch1);
            if (ch1 == 'y' || ch1 == 'Y') {
                printf("\n\tEnter New Mobile No. :");
                read_mob(p);
            }
            break;
        case 3:
            printf("\n\tPrevious salary is : %f", p->salary);
            printf("\n\tDo you want to edit ? (y/n)");
            getchar();
            scanf("%c", &ch1);
            if (ch1 == 'y' || ch1 == 'Y') {
                printf("\n\tEnter New salary:");
                scanf("%f", &(p->salary));
            }
            break;
        case 4:
            printf("the employee is currently working on project no. ");
            for (j = 0; j < 5; j++) {
                if (p->proj[j] == 1)
                    printf(" %d,", j + 1);
            }
            printf("\n\tDo you want to edit ? (y/n)");
            getchar();
            scanf("%c", &ch1);
            if (ch1 == 'y' || ch1 == 'Y') {
                printf(
                        "\n\tEnter \"1\" for the projects employee is working on : \n");
                for (j = 0; j < 5; j++) {
                    printf("\n\t\tProject No. %d : ", j + 1);
                    scanf("%d", &(p->proj[j]));
                    while (p->proj[j] != 1) {
                        printf("\n\nInvalid entry!! Please re-enter.");
                        printf("\n\t\tProject No. %d : ", j + 1);
                        scanf("%d", &(p->proj[j]));
                    }
                }
            }
            break;
        default:
            printf("\n\nInvalid Choice!! Please Try again.");
        }
        printf("\n\nDo you want to edit any other fields ?(y/n)");
        getchar();
        scanf("%c", &edt);
    } while (edt == 'y' || edt == 'Y');
}
emp_node* delete_rec(emp_node *head, int id) //physical deletion of record
{
    emp_node *p = head, *q;
    if (head->emp_id == id) {
        head = head->next;
        free(p);
        return head;
    } else {
        q = p->next;
        while (q->emp_id != id) {
            p = p->next;
            q = q->next;
        }
        if (q->next == NULL)
            p->next = NULL;
        else
            p->next = q->next;
        free(q);
        return head;
    }
}
void display_rev(emp_node *head) {
    emp_node *p=head, *q;
    while(p->next != NULL)
        p=p->next;
    while(p!=head || p==head){
        q=head;
        display_rec(p);
        while(q->next != p)
            q=q->next;
        p=q;
    }
}

2 个答案:

答案 0 :(得分:2)

我知道这是“作弊”,但你可以这样做:

void display_rev(emp_node *head) {
    if (head->next != null)
    {
      display_rev(head->next);
    }

    display_rec(head);
}

这是如何工作的:这个例程递归列表中的每个元素直到它结束,然后当它“展开”备份时它会打印每个元素。


void display_rev(emp_node *head) {
    emp_node *p=head, *q;

    if (p == null) return;

    while(p->next != NULL)
        p=p->next;

    while(p != head) {
      q=head;
      display_rec(p);
      while(q->next != p)
        q=q->next;
      p=q;
    }
    display_rec(p);
}

答案 1 :(得分:1)

这个测试总是如此

while(p!=head || p==head)

我认为你应该删除p==head部分

编辑我测试了循环,你还必须添加头部打印:

void display_rev(emp_node *head) {
    emp_node *p=head, *q;
    while(p->next != NULL)
        p=p->next;
    while(p!=head) {// || p==head){
        q=head;
        display_rec(p);
        while(q->next != p)
            q=q->next;
        p=q;
    }
    display_rec(p); // print the head also
}

分段错误(因为我假设您打算'突然终止')可能是由于某些数据在程序中未正确初始化而引起的......