2

我正在做一个双向链表。据我所知,它正在工作,但来到这里是为了确保并查看我是否以正确的方式进行操作。

另一方面,当我做这个时,我遇到了其他与双向链表无关但与 C 文件之间的结构和“可见性”有关的问题。如果您了解我应该对这两个其他疑问提出其他问题,请告诉。否则请随时启发我。

在我的 file1.c 我有这个:

代码

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

typedef struct team{
    char *name;
    char *teamPlace;
}Team;

typedef struct nodeTeam{
    int numberOfTeams;
    Team team;
    struct nodeTeam *next;
    struct nodeTeam *prev;
}NodeTeam;

int createsListOfTeams(NodeTeam **head, NodeTeam **tail);
void printListOfTeams(NodeTeam *listofTeams);
int addNodeTeamsSorted(NodeTeam *head, NodeTeam **tail, Team team);

int main()
{
    NodeTeam *headEquipas,*tailEquipas;
    Team eq;
    /*Creates the doubly linked list*/
    if(createsListOfTeams(&headEquipas,&tailEquipas)){
        printf("\nError\n");
        return 0;
    }
    /*Add the teams to the doubly linked list. At the end, all teams will be sorted by name*/
    eq.name = "D team";
    eq.teamPlace = "D team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    eq.name = "A team";
    eq.teamPlace = "A team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    eq.name = "C team";
    eq.teamPlace = "C team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    eq.name = "B team";
    eq.teamPlace = "B team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\nError\n");
        return 0;
    }

    /*Will print all the teams*/
    printListOfTeams(headEquipas);

    return 0;
}

在我的 file2.c 我有这个

代码

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

    typedef struct team{
        char *name;
        char *teamPlace;
    }Team;

    typedef struct nodeTeam{
        int numberOfTeams;
        Team team;
        struct nodeTeam *next;
        struct nodeTeam *prev;
    }NodeTeam;

    /*Add the teams to the doubly linked list. At the end, all teams will be sorted by name*/
    int createsListOfTeams(NodeTeam **head, NodeTeam **tail){
        (*head) = (NodeTeam *)malloc(sizeof(NodeTeam));

        if ((*head) == NULL){
            return -1;
        }
        (*head)->numberOfTeams = 0;
        (*head)->team.teamPlace = "";
        (*head)->team.name = "";
        (*head)->next = NULL;
        (*head)->prev = NULL;

        *tail = *head;
        return 0;
    }

    /*Creates the doubly linked list*/
    int addNodeTeamsSorted(NodeTeam *head, NodeTeam **tail, Team team){
        NodeTeam *no,*listIni;


        no = (NodeTeam*) malloc(sizeof(NodeTeam));
        if (no == NULL){
            return -1;
        }

        /*copy of my list*/
        listIni = head;

        no->team = team;
        /*to see is it's the first element of my list*/
        if(head->numberOfTeams == 0)
        {
            no->next = head->next;
            no->prev = head;
            head->next = no;
            *tail = no;

        }
        else{ /*If not the first element*/
            head = head->next;
            while(head->prev != *tail && strcmp(head->team.name,no->team.name) < 0 && strcmp((*tail)->team.name,no->team.name)>0){
                head = head->next;
                (*tail) = (*tail)->prev;
            }
            if(strcmp(head->team.name,no->team.name) >= 0 || head->prev == *tail){
                no->next = head;
                no->prev = head->prev;
                (head->prev)->next = no;
                head->prev = no;

            }
            else if(strcmp((*tail)->team.name,no->team.name) <= 0){
                no->next = (*tail)->next;
                no->prev = (*tail);
                (*tail)->next = no;
                *tail = no;

            }
        }

        /*Updates the number of element of the list*/
        head = listIni;
        head->numberOfTeams++;

        return 0;
    }
    /*Prints my lists*/
    void printListOfTeams(NodeTeam *listofTeams){
        printf("|   number of teams %22d |\n",listofTeams->numberOfTeams);
        printf("|      team name      |        team place      |\n");
        printf("--------------------------------------------------\n");
        listofTeams = listofTeams->next;
        while (listofTeams != NULL){
            printf("| %-21s | %-22s |\n",listofTeams->team.name,listofTeams->team.teamPlace);
            listofTeams = listofTeams->next;
        }
        printf("--------------------------------------------------\n\n");
    }

所以这是我的树问题:

Q1 - 这是实现一个头和尾分别指向列表开头和结尾的双向链表的正确方法吗?

Q2 - 为什么要在我的两个文件上声明struct teamstruct nodeTeam?既然它们都在同一个项目中,那么声明不应该对我项目中的所有文件“可见”吗?

Q3 -struct team为什么我必须申报char *name而不是char name[31]

4

1 回答 1

2

在您之前的评论和更仔细地分析了您的代码之后,我进行了一些编辑。我错误地解释了关于头部和尾部项目的一个评论,虽然你正在设计一个循环列表

  1. 我花时间复制/粘贴/编译您的代码。虽然它几乎可以工作,但我必须说我会以另一种方式设计

    • prev/next指针移动到struct team
    • 并用指向 first的指针替换team成员。nodeTeamheadteam

    这将有以下好处:

    • numberOfTeams防止对每个重复nodeTeams但仅对第一个有意义的空间浪费无用的空间
    • 避免概念head和实际第一团队之间的混淆

    通过在团队列表中添加指针的值

    printf("| %-21s | %-22s | %p - p=%p n=%p\n",listofTeams->team.name, listofTeams->team.teamPlace, listofTeams, listofTeams->prev, listofTeams->next);

    我注意到您的链接中可能存在错误:

    | 一个团队 | 一个团队的地方| 0x101d00980 - p=0x101d00920 n=0x101d009e0

    | B组 | B队名额 | 0x101d009e0 - p=0x101d00980 n=0x101d009b0

    | C队 | C队名额 | 0x101d009b0 - p=0x101d00980 n=0x101d00950

    | D组| D队名额| 0x101d00950 - p=0x101d009b0 n=0x0

    你可以看到 next 指针没问题,但 prev 指针显示可疑重复(0x101d00920 确实是“头”)。

    如果您跟踪代码的执行并检查它所做的事情,addNodeTeamsSorted()您可能会注意到在第 3 步之前一切正常(在现有 A 和 D 之后添加团队 C):

    • 由于 head 和 tail 奇怪的双重修改以找到插入新项目的位置,head 和 tail 正在交叉:tail 实际上指向 'A' 并且 head 指向 'D' (不要忘记 while headisNodeteam *和它的修改赢了' 不会在函数之外传播,tail是 a Nodeteam **,因此当它更改为调用者并进行下一次调用时,它将是错误的
    • 在测试部分的第 4 步(添加“B”)中else if,您正确更改了 prev/next no、 (*tail) 的下一个但不是prev ofno->next所以你有
      • 'B' -> 下一个 = 'C' :好的
      • 'B' -> prev = 'A' :好的
      • *tail (='A') -> next = 'B' : 好的
      • 'C' -> prev 仍然 = 'A' :错误
  2. 这与编译器的想法不同。他只处理编译单元,一次一个。.c 中未声明的内容和包含的不同 .h 将保持未知。如果您想在 2 个模块之间共享结构声明,并防止代码维护中的错误,请剪切 typedef 并将它们放在一个公共头文件(例如equipa.h)中,该文件将包含在两个 .c 中

  3. 您必须使用char*而不是char[]因为在您的main()in file1.c 中您正在从文字字符串进行直接分配,并且编译器不会让您将文字字符串分配给 char 数组。如果你想char[]改用改变你的

    eq.nome = "D team";

    通过字符串复制

    strcpy(eq.nome, "D team");

    当然,我只是在处理这个概念,实际上你应该注意要复制的字符串不会比缓冲区长,使用strncpy()andsizeof(eq.nome)

于 2012-05-12T10:24:17.360 回答