我正在做一个双重链接列表。据我所知,这是有效的,但来到这里是为了确保我是否采取了正确的方式。
另一方面,当我做到这一点时,我遇到了其他与双向链表无关但与C文件之间的结构和“可见性”无关的问题。如果你明白我应该为另外两个问题创造其他问题,请告诉我们。否则请随时赐教。
在我的file1.c上我有这个:
CODE
#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上我有这个
CODE
#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 team
和struct nodeTeam
?既然它们都在同一个项目中,那么声明是否应该对我项目中的所有文件“可见”?
第3季度 - 在struct team
为什么我必须声明char *name
而不是char name[31]
?
答案 0 :(得分:2)
我在您之前的评论之后进行了一些修改,并且在更仔细地分析了您的代码之后。 我错误地解释了关于头部和尾部项目的一个评论,尽管你正在设计一个循环列表
我花时间复制/粘贴/编译您的代码。虽然它几乎正常工作但我必须说我会以另一种方式设计
prev
/ next
指针移至struct team
team
nodeTeam
成员替换为指向第一个head
的{{1}}指针。 这将带来以下好处:
team
复制的numberOfTeams
造成无用的空间浪费,但仅对第一个nodeTeams
与实际的第一个团队之间的混淆通过
添加团队列表中指针的值 head
我发现你的链接可能存在错误:
|一个团队|团队的地方| 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
你可以看到下一个指针没问题,但是前面的指针显示可疑重复(0x101d00920确实是&#39; head&#39;)。
如果您跟踪代码的执行情况并检查它在printf("| %-21s | %-22s | %p - p=%p n=%p\n",listofTeams->team.name, listofTeams->team.teamPlace, listofTeams, listofTeams->prev, listofTeams->next);
中的效果,您可能会注意到一切正常直到第3步(在现有的A&amp; A之后添加C队D):
addNodeTeamsSorted()
是head
并且其修改不会在函数之外传播,但Nodeteam *
是tail
,因此当它变为Nodeteam **
时调用者和下次调用它将是错误的else if
部分中,no
的下一个(*尾部)但不是的上一个,所以你有
这与编译器的想法不同。他只处理编译单位,一次一个。什么未在.c中声明,而不同的.h将保持未知。如果要共享2个模块之间的结构声明,并防止代码维护中的错误,请剪切typedef并将它们放在将包含在.c
no->next)中。 >您必须使用equipa.h
而不是char*
,因为在文件1c的char[]
中,您正在从文字字符串进行直接分配,编译器不会使用让您将文字字符串分配给char数组。如果您想使用main()
而不是更改
char[]
通过字符串复制,如
eq.nome = "D team";
当然,我只处理这个概念,实际上你应该注意使用strcpy(eq.nome, "D team");
和strncpy()