简体   繁体   中英

Program crashes when printing a linked list on screen

I don't know why I can read the Linked list without problems in LABEL : 1 ; but the program just crashes and print grabage in the LABEL : 0 ; In other terms, why the linked list works fine inside the lecture function , but not outside it ? Here is my code :

/* 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;
}

Here is the printing function :

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++;
    }
}

You're allocating data for the root of the list in the main function, and pass that to the function so that it may populate the list, but the first time you allocate an element you overwrite the ROOT pointer value.

this makes you lose the only connection between the function and the outside world (since the return value is just a number), so the HEAD value in main() is left pointing at nothing meaningful (because your function never uses it), while the list remains allocated in some memory location that no one outside is pointing to, which means it's lost. Running valgrind would have been able to identify this.

You can fix that by changing the (i==0) case from -

ROOT = Data ;

into

ROOT->next = Data ;

but make sure you're ignoring the data of the root node later on.

ps - using capitalized variables and types is not considered a good idea (it's mostly reserved for macros). It also makes your code look like you're shouting :)

The (main) problem is that lecture_data doesn't use it's input parameter ( ROOT ) for storage of the linked list, nor does it return the internal generated list. The correct way to handle this is to have ROOT reference the calling scope's parameter so that it can update it's reference as necessary.

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;
}

Note: print_data didn't do anything with the len parameter, so no need passing it in at all.

This solution is not wasteful in terms of "empty" nodes in the list (as opposed to having an empty head to ignore), and is suitable both for initializing the list from scratch AND for cases where you need to append / insert into an existing list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM