[英]Program crashes when printing a linked list on screen
我不知道為什么我可以在LABEL中沒有問題地閱讀鏈接列表:1; 但該程序只是在LABEL中崩潰並打印了垃圾:0; 換句話說,為什么鏈接列表在講座功能中工作正常,但不在其外? 這是我的代碼:
/* including libraries */
#define V 20
typedef struct DATA{
char* NomP;char* NomA;
struct DATA *Next;
}DATA;
// Prototypes .
int main(void)
{
char FileName[V];
puts("Data file ? : ");gets(FileName);
FILE* fs = fopen(FileName,"r"); // Check if fs is NULL
DATA *HEAD = MALLOC(sizeof (DATA)); int len = lecture_data(fs,HEAD);
print_data(HEAD,len); //LABEL : 0
return 0;
}
int lecture_data(FILE *fs,DATA *ROOT)
{
char cNom[V],cArticle[V];
int eofs=0;int i=0;
while(!eofs)
{
DATA *Data = MALLOC(sizeof (DATA));
fscanf(fs,"%s %s",cNom,cArticle);
Data->NomA = MALLOC(strlen(cArticle)+1);
Data->NomP = MALLOC(strlen(cNom)+1);
strcpy(Data->NomA,cArticle);
strcpy(Data->NomP,cNom);
if( i==0 )
{
Data -> Next = NULL ;
ROOT = Data ;
}
else
{
DATA* Ptr = ROOT ;
while( (Ptr->Next) != NULL )
{
Ptr = (Ptr -> Next);
}
Data -> Next = NULL ;
Ptr -> Next = Data ;
}
i++;
eofs = feof(fs) ;
// check ferror(fs) here
}
puts("Start of reading :");
print_data(ROOT,len); // LABEL : 1
puts("End Of Reading ");
fclose(fs);
return i;
}
這是打印功能:
void print_data(DATA *L_ROOT,int len)
{
int i = 0 ;
DATA* LINK;
LINK = L_ROOT;
while( LINK != NULL )
{
printf("%d : DATA->NomA : %s\n",i,LINK->NomA);
printf("%d : DATA->NomP : %s\n",i,LINK->NomP);
LINK = LINK -> Next ;
i++;
}
}
您正在為main函數中的列表根分配數據,並將其傳遞給函數,以便它可以填充列表,但是第一次分配元素時會覆蓋ROOT指針值。
這使你失去了函數和外部世界之間的唯一連接(因為返回值只是一個數字),所以main()中的HEAD值指向沒有任何意義(因為你的函數從不使用它),而list仍然分配在某個內存位置,沒有人指向外部,這意味着它丟失了。 運行valgrind本來可以識別這個。
您可以通過更改(i == 0)案例來解決這個問題 -
ROOT = Data ;
成
ROOT->next = Data ;
但請確保稍后忽略根節點的數據。
ps - 使用大寫變量和類型不被認為是一個好主意(它主要是為宏保留的)。 它也使你的代碼看起來像你在喊:)
(主要)問題是lecture_data
不使用它的輸入參數( ROOT
)來存儲鏈表,也不返回內部生成的列表。 處理此問題的正確方法是讓ROOT
引用調用范圍的參數,以便它可以根據需要更新它的引用。
int main(void)
{
char FileName[V];
puts("Data file ? : ");gets(FileName);
FILE* fs = fopen(FileName,"r"); // Check if fs is NULL
DATA *HEAD = NULL;
int len = lecture_data(fs, &HEAD);
print_data(HEAD); //LABEL : 0
return 0;
}
int lecture_data(FILE *fs,DATA **ROOT)
{
char cNom[V],cArticle[V];
int i=0;
DATA *current = *ROOT; // grab the passed in reference
while(!feof(fs))
{
if(fscanf(fs,"%s %s",cNom,cArticle) <= 0) // This call is only successful if the return value is > 0
{
// check ferror(fs) here
continue; // Can also "break;" here, essentially, it's eof already
}
DATA *Data = MALLOC(sizeof (DATA));
Data->NomA = MALLOC(strlen(cArticle)+1);
Data->NomP = MALLOC(strlen(cNom)+1);
strcpy(Data->NomA,cArticle);
strcpy(Data->NomP,cNom);
if(NULL == current) // ROOT was uninitialized before the call
{
Data -> Next = NULL;
*ROOT = Data;
}
else
{ // We don't need to iterate the list in every step.
Data->Next = current->Next; // This part allows the function to insert nodes in the middle / end of an existing list
current->Next = Data;
current = Data;
}
i++;
}
puts("Start of reading :");
print_data(ROOT); // LABEL : 1
puts("End Of Reading ");
fclose(fs);
return i;
}
注意: print_data
沒有對len
參數做任何事情,因此根本不需要傳入它。
對於列表中的“空”節點而言,此解決方案並不浪費(而不是忽略空頭),並且適用於從頭開始初始化列表以及需要追加/插入現有列表的情況名單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.