【问题标题】:How to pass a linked list to a function in C如何将链表传递给C中的函数
【发布时间】:2017-05-03 19:12:44
【问题描述】:

所以我已经制作了一个工作程序,用于从文件中获取数据并根据您希望在 main 中的文件的哪一部分打印出文件。但我的目标是通过创建用户界面并从文件中附加到链接列表或根据要求打印出该链接列表的一部分(如果有)来使这个模块化。 只有一个问题:我似乎无法找到一种方法来成功地将链表传递给函数,这样当你在函数中创建新节点(附加)时,它也可以在 main 中工作,然后在 (打印)。

这是工作代码:

#include <stdio.h>
#include <stdlib.h>      /* has the malloc prototype      */
#define TSIZE 100        /* size of array to hold title   */
struct book {
    char title[TSIZE], author[TSIZE],year[6];
    struct book * next;  /* points to next struct in list */
};
//typedef struct book ITEM;
typedef struct book * Node;     // struct book *
void Append(Node *List, Node *Lcurrent,char filename[]);
void ClearGarbage(void);
int main(void){
    Node head=NULL;
    Node current;
    current=head;
    char fname[]="HW15Data.txt";
    char op;
    do{
        puts("Select operation from the following list:");
        puts("a. Append    p. Print q. quit");
        op = getchar();
        ClearGarbage();
        if (op=='a'){
            /* Gather  and store information          */
            Append(&head,&current,fname);
        }
        else if (op=='q'){
            /* User quit, so free allocated memory */
            current = head;
            while (current != NULL)
            {
                free(current);
                current = current->next;
            }
            printf("Bye!\n");
            return 0;
        }
        else{
            /* Program done, so free allocated memory */
            current = head;
            while (current != NULL)
            {
            free(current);
            current = current->next;
            }
            printf("Invalid characted entered. Bye!\n");
            return 0;
        }
    } while (op!='q');
    return 0;
}
void Append(Node *List, Node * Lcurrent,char filename[TSIZE]){
    FILE * fp;
    Node head=*List;
    Node current=*Lcurrent;
    int loops=0;
    fp=fopen(filename,"r");
    if (head==NULL){
        head=(Node) malloc(sizeof(struct book));
        current=head;
        current->next=NULL;
    }
    do{
        current->next = (Node) malloc(sizeof(struct book));
        current=current->next;
        loops++;
    } while(fgets(current->title,sizeof(current->title),fp) && fgets(current->author,sizeof(current->title),fp) && fgets(current->year,sizeof(current->year),fp));;
    free(current);
    printf("Number of records written: %d\n",loops);
//Same as Print function in the nonworking code
    int num;
    int i=0;
    if (head == NULL){
        printf("No data entered. ");
    }
    else{
        printf("Enter record # to print: ");
        scanf("%d",&num);
        ClearGarbage();
        num=num+1;
        current = head;
        while (current != NULL && i<num)
        {
            for (i=0;i<num;i++)
                current = current->next;
            printf("Book: %sAuthor: %sYear: %s\n",
            current->title, current->author, current->year);
            }
    }
}
void ClearGarbage(void){
    while (getchar()!='\n');
}

好吧,这很有效,但我的猜测是,一旦 Append 完成,在 Append 中创建的节点在 main 中就没有用了,因为它们现在已经消失了。所以当我尝试在下面的代码中创建一个打印函数时,没有什么可以打印的。

#include <stdio.h>
#include <stdlib.h>      /* has the malloc prototype      */
#define TSIZE 100        /* size of array to hold title   */
struct book {
    char title[TSIZE], author[TSIZE],year[6];
    struct book * next;  /* points to next struct in list */
};
//typedef struct book ITEM;
typedef struct book * Node;     // struct book *
void Append(Node *List, Node *Lcurrent,char filename[]);
int Print(Node *List,Node *Lcurrent);
void ClearGarbage(void);
int main(void){
    Node head=NULL;
    Node current;
    current=head;
    char fname[]="HW15Data.txt";
    char op;
    do{
        puts("Select operation from the following list:");
        puts("a. Append    p. Print q. quit");
        op = getchar();
        ClearGarbage();
        if (op=='a'){
            /* Gather  and store information          */
            Append(&head,&current,fname);
        }
        else if (op=='p'){
            /*Print book record of user's choice*/
            Print(&head,&current);
        }
        else if (op=='q'){
            /* User quit, so free allocated memory */
            current = head;
            while (current != NULL)
            {
                free(current);
            current = current->next;
            }
            printf("Bye!\n");
            return 0;
        }
        else{
            /* Program done, so free allocated memory */
            current = head;
            while (current != NULL)
            {
            free(current);
            current = current->next;
            }
            printf("Invalid characted entered. Bye!\n");
            return 0;
        }
    } while (op!='q');
    return 0;
}
void Append(Node *List, Node * Lcurrent,char filename[TSIZE]){
    FILE * fp;
    Node head=*List;
    Node current=*Lcurrent;
    int loops=0;
    fp=fopen(filename,"r");
    if (head==NULL){
        head=(Node) malloc(sizeof(struct book));
        current=head;
        current->next=NULL;
    }
    do{
        current->next = (Node) malloc(sizeof(struct book));
        current=current->next;
        loops++;
    } while(fgets(current->title,sizeof(current->title),fp) && fgets(current->author,sizeof(current->title),fp) && fgets(current->year,sizeof(current->year),fp));
    free(current);
    printf("Number of records written: %d\n",loops);
}
int Print(Node *List,Node *Lcurrent){
    int num;
    int i=0;
    Node head=*List;
    Node current=*Lcurrent;
    if (head == NULL){
        printf("No data entered.\n");
        return -1;
    }
    printf("Enter record # to print: ");
    scanf("%d",&num);
    ClearGarbage();
    num=num+1;
    current = head;
    while (current != NULL && i<num)
    {
        for (i=0;i<num;i++){
            current = current->next;
        }
        printf("Book: %sAuthor: %sYear: %s\n",
        current->title, current->author, current->year);
        }
    return 0;
}
void ClearGarbage(void){
    while (getchar()!='\n');
}

感谢任何人的帮助!

编辑:为了清楚起见,去掉了一个未使用的 typedef

【问题讨论】:

  • 嗯,像typedef struct book * Node; 这样的点的类型定义在某些编码风格中是不受欢迎的做法。
  • typedef struct Node List; 这还有效吗?
  • @chux 我认为typedef struct Node List 正在创建一个不完整的类型struct Node 并将其类型定义为List。与上一行的Node无关。
  • 无论如何List 类型不在任何地方使用。这只会造成混乱。
  • @chux 你说得对,后来我被while 和for 弄糊涂了。

标签: c function linked-list


【解决方案1】:

似乎大多数人都在关注缺乏组织(这也让我很困扰)而不是您的实际问题。

似乎问题的根源在于您分配变量头的位置。 当您定义“Node head = *List”并且 List 为 NULL 时,因为它第一次初始化,它失去了与您从 main 发送的原始列表的连接,您只需创建一个仅具有本地引用的链表。

我刚刚在 Append 和 Print 函数中将“head”的用法更改为“*List”,它似乎已经解决了。

这是我更改后的代码:

#include <stdio.h>
#include <stdlib.h>      /* has the malloc prototype      */
#define TSIZE 100        /* size of array to hold title   */
struct book {
    char title[TSIZE], author[TSIZE], year[6];
    struct book * next;  /* points to next struct in list */
};
//typedef struct book ITEM;
typedef struct book * Node;     // struct book *
void Append(Node *List, Node *Lcurrent, char filename[]);
int Print(Node *List, Node *Lcurrent);
void ClearGarbage(void);
int main(void) {
    Node head = NULL;
    Node current;
    current = head;
    char fname[] = "HW15Data.txt";
    char op;
    do {
        puts("Select operation from the following list:");
        puts("a. Append    p. Print q. quit");
        op = getchar();
        ClearGarbage();
        if (op == 'a') {
            /* Gather  and store information          */
            Append(&head, &current, fname);
        }
        else if (op == 'p') {
            /*Print book record of user's choice*/
            Print(&head, &current);
        }
        else if (op == 'q') {
            /* User quit, so free allocated memory */
            current = head;
            while (current != NULL)
            {
                free(current);
                current = current->next;
            }
            printf("Bye!\n");
            return 0;
        }
        else {
            /* Program done, so free allocated memory */
            current = head;
            while (current != NULL)
            {
                free(current);
                current = current->next;
            }
            printf("Invalid characted entered. Bye!\n");
            return 0;
        }
    } while (op != 'q');
    return 0;
}
void Append(Node *List, Node * Lcurrent, char filename[TSIZE]) {
    FILE * fp;
    Node head = *List;
    Node current = *Lcurrent;
    int loops = 0;
    char line[256];
    fp = fopen(filename, "r");
    if (*List == NULL) {
        *List = (Node)malloc(sizeof(struct book));
        current = *List;
        current->next = NULL;
    }
    do {
        current->next = (Node)malloc(sizeof(struct book));
        current = current->next;
        loops++;
    } while (fgets(current->title, sizeof(line), fp) && fgets(current->author, sizeof(line), fp) && fgets(current->year, sizeof(line), fp));
    free(current);
    printf("Number of records written: %d\n", loops);
}
int Print(Node *List, Node *Lcurrent) {
    int num;
    int i = 0;
    Node head = *List;
    Node current = *Lcurrent;
    if (*List == NULL) {
        printf("No data entered.\n");
        return -1;
    }
    printf("Enter record # to print: ");
    scanf("%d", &num);
    ClearGarbage();
    num = num + 1;
    current = *List;
    while (current != NULL && i<num)
    {
        for (i = 0; i<num; i++) {
            current = current->next;
        }
        printf("Book: %sAuthor: %sYear: %s\n",
            current->title, current->author, current->year);
    }
    return 0;
}
void ClearGarbage(void) {
    while (getchar() != '\n');
}

还有很多逻辑错误和一些错误,但它解决了您寻求帮助的问题。

【讨论】:

  • 这个答案没有考虑fgets(current-&gt;title, sizeof(line),... 评论here ,因此继续潜在的未定义行为(UB)。
  • 我说还有很多其他的错误和Bug,但他问他发送链表的问题。
  • *List = (Node)malloc(sizeof(struct book)); 是对 OP 代码的重要改进。
  • 做到了!谢谢你,@NK_loco 和 chux!我目前正在做很多修复以使其更具可读性和错误修复。我只是看不到函数传递问题的方法,所以我主要需要清除它。如果那是一大堆糟糕的代码,我很抱歉,所以感谢你在那个问题上对我的包容。
  • np ^.^ 指针有时可能很棘手,只要确保您了解什么指向什么以及什么分配给什么。用指针在本地改变东西是很常见的,但你会通过足够的练习得到它;)
猜你喜欢
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 2013-10-06
  • 1970-01-01
相关资源
最近更新 更多