简体   繁体   中英

Linked List program isn't updating properly

I have created a program that reads in a text file containing integers. It should read these integers in and then create a linked list of them. However, the head pointer of my program continually updates even when just the tail should be. Does anyone know why this is? The input file can be integers separated by spaces or newlines. Here is my code:

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

/*THIS IS THE BASIC NAME STRUCTURE. IT CONTAINS A FIRST AND LAST NAME VARIABLE*/
struct number {
    int * number;          //number
};
/*THIS IS THE BASIC NAME NODE STRUCTURE. IT CONTAINS A NAME STRUCT AS WELL AS STRUCT NAMENODES TO PREVIOUS AND NEXT NODES*/

struct numberNode {
    struct number number;          //name stuct call

    struct numberNode *pNext;    //pointer to next node
    struct numberNode *pPrev;    //pointer to previous node

};

/*THESE NAMENODES WILL BE USED THROUGHOUT THE PRGRAM AS THE HEAD AND TAIL OF THE PROGRAM*/
struct numberNode *pHead = NULL, *pTail=NULL;



/*THIS PROGRAM READS A FILE AND PLACES THE NAMES INTO LINKED LIST*/
void insert_end(int *num)

{

    struct numberNode *var = NULL,*temp = NULL;                   //set temp nodes

    var=(struct numberNode *)malloc(sizeof(struct numberNode));     //allocate memory for new node

    var->number.number= num;                         //set number of number stored in node





    if(pHead==NULL){                                            //check if it is the head


        pHead=var;                                              //set node to head b/c of first element

        pHead->pPrev=NULL;                                      //set node next and prev to null

        pHead->pNext=NULL;

        pTail=pHead;                                            //make head and tail the same

    }else{

        pTail=pHead;                                        //set tail to head

        while(pTail!=NULL)                                  //while tail is not NULL

        {

            temp=pTail;                                     //set temp node to tail pointer

            pTail=pTail->pNext;                             //traverse the linked list

        }

        pTail=var;                                          //set ptail to correct node

        temp->pNext=pTail;                                  //set the temps next to tail

        pTail->pPrev=temp;                                  //set the tail's previous pointer to temp

        pTail->pNext=NULL;                                  //set tail next to NULL

    }


}



/*FUNCTION FOR DISPLAYING LINKED LIST DATA*/
void display(){
    struct numberNode *node;
    node=pHead;
    printf("Displaying Linked List \n ************************************** \n");
    while(node != NULL){
        printf("Number is %d\n", *node->number.number);
        node = node->pNext;
    }
    printf("List is terminated\n ************************************* \n");
}

void displayBackwards(){
    struct numberNode *node;
    node=pTail;
    printf("Displaying Linked List Backwards \n ************************************** \n");
    while(node != NULL){
        printf("Number is %d\n", *node->number.number);
        node = node->pPrev;
    }
    printf("List is terminated\n ************************************* \n");
}




/*DELETE NODE PASSED IN ARGUEMENT*/
void deleteNode(struct numberNode *node){
    if (node!= pHead){
        node->pPrev->pNext=node->pNext;
        node->pNext->pPrev=node->pPrev;
        node->pNext = NULL;
        free(node);
    }else{
        pHead->pNext = pHead;
        free(node);
    }
}

//SWITCH THE LOCATIONS OF THE TWO NODES PASSED AS ARGUEMENTS
void switchNodes(struct numberNode *leftNode, struct numberNode *rightNode){
    struct numberNode temp;
    temp = *leftNode;
    leftNode->number=rightNode->number;
    rightNode->number= temp.number;

}

/*ORGANIZE LINKED LIST IN ALPHABETICAL ORDER*/
void organizeInAscendingOrder(){
    struct numberNode *node = pHead;
    int length=0;
    while(node != NULL){
        node = node->pNext;
        length ++;
    }
    node = pHead;
    int index = 0, secondIndex = 0;
    for (index=0; index<length; index++){
        for (secondIndex=0; secondIndex<length-1; secondIndex++){
            if(node->number.number > node->pNext->number.number){
                switchNodes(node, node->pNext);
            }
            node=node->pNext;
        }
        node=pHead;
    }
}

/*PUSH NODE PASSED AS ARGUEMENT TO THE BACK*/
void pushToBack(struct numberNode *node){
    pTail->pNext = node;
    deleteNode(node);
}


int main() {


    char file[100];
    printf("Enter input file ");
    scanf("%s", file);
    FILE *in_file = fopen(file, "r");


    int number;

    char *buffer;



    while(fscanf(in_file,"%d", &number)!=EOF)

    {

        insert_end(&number);
    }

    display();

    organizeInAscendingOrder();

    display();

    displayBackwards();


}

You are in a bit of a muddle with your data structures - you can just reduce this:

struct number {
    int * number;          //number
};
/*THIS IS THE BASIC NAME NODE STRUCTURE. IT CONTAINS A NAME STRUCT AS WELL AS STRUCT NAMENODES TO PREVIOUS AND NEXT NODES*/

struct numberNode {
    struct number number;          //name stuct call

    struct numberNode *pNext;    //pointer to next node
    struct numberNode *pPrev;    //pointer to previous node

};

to this:

struct numberNode {
    int number;                  //number
    struct numberNode *pNext;    //pointer to next node
    struct numberNode *pPrev;    //pointer to previous node

};

ie you don't need more than one struct for this.

as Paul said you don't necessarily need both struct, but the real problem is that when you read an int from the file you store in the variable "int number;" and each time you call the function insert_end(&number); you send the address of the variable number but in your insert_end function you assign the value of your new number in your new node to the address of number : var->number.number= num;. So in your list all your number element in your numberNode will point the the same address.

a quick fix would be to allocate new memory space for each integer read in the file. ex:

int* number = (int*)malloc(sizeof(int));

while(fscanf(in_file,"%d", number)!=EOF)

{
    insert_end(number);
    number = (int*)malloc(sizeof(int));
}

you could also remove pointers from the struct as suggested by Paul :

struct numberNode {
    int number;                  //number
    struct numberNode *pNext;    //pointer to next node
    struct numberNode *pPrev;    //pointer to previous node
 };

hope it helps,

[EDIT] : +1 for fhsilva who propose a better way to manage the tail, the head should always refere to the first element of the list and the tail should always point to the last one. This ways you don't new to go through the list to insert at the end becaus you already have a reference to the last element.(I couldn't comment on fhsilva's answer because I just subscribed to SO and don't have enough reputation...)

James

Not sure why you are traversing the list since it is double linked. This should work:

if (pHead==NULL){
    (...)
} else {
    pHead->pPrev = var;
    pTail->pNext = var;
    var->pPrev = pTail;
    var->pNext = pPrev;
    pTail = var;
}

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