0

So, I have to read a linked list from a binary file and then add new elements to it. It reads from the binary as expected, but when I try to add new elements to the list, it adds only the last one, which I enter.

Here is the code in main() responsible for reading, creating and inserting a new element into the List

    int main()
{
    int choice=0;
    int confirmation=0;
    t_Node *temp_node1, *temp_node2, *temphead;
    unsigned int ID1, ID2;

    FILE *fp;
    fp = fopen("Data.bin","rb");
    if(fp==NULL)
    {
        printf("File error");
        exit(6);
    }
        while(1)
        {
            if(feof(fp))
            {
                break;
            }
            if (head == NULL)
            {
                head = readNode(fp);
                temphead = head;
            }else
            {
                temphead = readlist(temphead, fp);
            }
        }
    fclose(fp);
    while(1)
    {
    printf("\n\n");
    printf("Hello world!\n\n 1-Enter a new element/s.\n 2-Copy data from one element to another (by ID).\n 3-Switch data between two elements (by ID).\n 4-Delete an element (by ID)\n 5-Print all elements\n 6-Delete all elements\n 0-Exit\n");
    scanf("%d",&choice);
    if(choice==0)
    {
        system("cls");
        delete_List(head);
        printf("EXIT BY USER");
        break;
    }
    switch(choice)
    {
        case 1:
            system("cls");
            int temp=0;
            t_Node *temphead1, *searched1, *searched2;
            do
            {
                temphead1=makelist(temphead);
                printf("press 0 to stop, any other key to go on\n");
                fflush(stdin);
                scanf("%d",&temp);
            }while (temp!=0);
            break;
        case 2:
            system("cls");
            confirmation=0;
            ID1=0;
            ID2=0;
            do
            {
                do
                {
                    printf("Enter ID of the element you want to copy\n");
                    scanf("%u",&ID1);
                    temp_node1=Find_By_Id(ID1);
                }while( temp_node1==NULL);
                printNode(temp_node1);
                printf("\nAre you sure?\n 1 for yes, 0 for no\n");
                scanf("%d",&confirmation);
            }while (confirmation==0);
            confirmation=0;
            do{
                do{
                    printf("Enter ID of the element you want to copy to\n");
                    scanf("%u",&ID2);
                    temp_node2=Find_By_Id(ID2);
                }while(temp_node2==NULL);
                printNode(temp_node2);
                printf("\nAre you sure?\n 1 for yes, 0 for no\n");
                scanf("%d",&confirmation);
            }while (confirmation==0);
            confirmation=0;
            Copy_first_to_second(temp_node1, temp_node2);
            break;
        case 3:
            system("cls");
            ID1=0;
            ID2=0;
            do{
                do{
                    printf("Enter ID of the first element you want to switch data with\n");
                    scanf("%u",&ID1);
                    temp_node1=Find_By_Id(ID1);
                }while( temp_node1==NULL);
                printNode(temp_node1);
                printf("\nAre you sure?\n 1 for Yes, 0 for No\n");
                scanf("%d",&confirmation);
            } while (confirmation==0);
            confirmation=0;

            do
                {
                do
                {
                    printf("Enter ID of the second element you want to switch data with\n");
                    scanf("%u",&ID2);
                    temp_node2=Find_By_Id(ID2);
                } while( temp_node2==NULL);
                printNode(temp_node2);
                printf("\nAre you sure?\n 1 for yes, 0 for no\n");
                scanf("%d",&confirmation);
            }while(confirmation==0);
            confirmation=0;
            Copy_first_to_second(temp_node1, temp_node2);
            break;
        case 4:
            system("cls");
            ID1=0;
            do
                {
                do
                {
                    printf("Enter ID of the element you want to delete\n");
                    scanf("%u",&ID1);
                    temp_node1=Find_By_Id(ID1);
                } while( temp_node1==NULL);
                printNode(temp_node1);
                printf("\nAre you sure?\n 1 for yes, 0 for no\n");
                scanf("%d",&confirmation);
            }while (confirmation==0);
            confirmation=0;
            Delete_Element(temp_node1);
            break;
        case 5:
            system("cls");
            if (head==NULL)
            {
                printf("\nEnter elements first");
                break;
            }
            printlist(head);
            break;
        case 6:
            system("cls");
            delete_List(head);
            printf("List deleted");
            break;
        default:
            delete_List(head);
            exit(1);
        }
    }
    return 0;
}

The structures:

typedef struct something
{
    char name[50];
    double value;
    unsigned int ID;
}t_Something;
typedef struct node
{
    t_Something smth;
    struct node *next;
}t_Node;

And the functions:

t_Something readElement (FILE *file)
{
    t_Something t_Struct;
    int check=0;
    unsigned int t_ID;
    fread(&t_Struct,sizeof(t_Struct),1,file);
    do{
    t_ID=t_Struct.ID;
    check=checkID(t_ID);
    if (check==1)
    {
        break;
    }
    }while(1);
    return t_Struct;
}
t_Something addElement() 
{
    t_Something t_Struct;
    int check=0;
    unsigned int t_ID;
    printf("\nInput name\t");
    fflush(stdin);
    gets(t_Struct.name);
    printf("\nInput value\t");
    fflush(stdin);
    scanf("%0.2lf",&t_Struct.value);
    printf("\nInput ID, must be unique\t");
    fflush(stdin);
    do
    {
        scanf("%u",&t_Struct.ID);
        t_ID=t_Struct.ID;
        check=checkID(t_ID);
        if (check==1)
        {
            break;
        }
    }while (1);
    return t_Struct;
}

t_Node* addNode (t_Node *temphead)
{
    t_Node *pNode;
     pNode = (t_Node*)malloc(sizeof(t_Node));
    if (pNode==NULL)
    {
        printf("\nMemory error\n");
        delete_List(head);
    }
    pNode->smth=addElement();
    pNode->next=NULL;
    return pNode;
}
t_Node* makelist(t_Node *temphead)
{
    t_Node *temp2=addNode(temphead);
    temphead->next=temp2;
    return temp2;
}
t_Node* readNode (FILE *file)
{
    t_Node *pNode;
    pNode = (t_Node*)malloc(sizeof(t_Node));
    if (pNode==NULL)
    {
        printf("\nMemory error\n");
        delete_List(head);
    }
    pNode->smth=readElement(file);
    pNode->next=NULL;
    return pNode;
}
t_Node* readlist (t_Node *temphead, FILE *file)
{
    t_Node *temp2=readNode(file);
    temphead->next=temp2;
    return temphead->next;
}
void printlist (t_Node* current){
    for (;;){
        printNode(current);
        current=current->next;
        if (current==NULL) break;
    }
}

void printNode (t_Node* current)
{
        printf("\n--------\n");
        printf("name: %s\n", current->smth.name);
        printf("value: %lf", current->smth.value);
        printf("\nID: %u\n", current->smth.ID);
}

void delete_List (t_Node* current)
{
    t_Node *temp;
    for (;;){
        temp=current->next;
        free(current);
        current=temp;
        if (current==NULL)
        {
            break;
        }
    }
}

int checkID (unsigned int number)
{
    t_Node *current=head;
    int pass=1;
    if (head!=NULL)
    {
        for(;;)
        {
            if(current->smth.ID==number)
            {
                pass=0;
                return pass;
            }
            current=current->next;
            if (current==NULL)
            {
                break;
            } 
        }
    }
    return pass;
}

t_Node* Find_By_Id (unsigned int searched)
{
    t_Node* current=head;
    for (;;)
    {
        if (searched==current->smth.ID)
        {
            return current;
        }
        current=current->next;
        if (current==NULL)
        {
            break;
        }
    }
    printf("\nThere is no element with this ID\n");
    return NULL;
}

void Change_two_elements (t_Node* first, t_Node* second)
{
    t_Something temp;
    temp=first->smth;
    first->smth=second->smth;
    second->smth=temp;
}

void Copy_first_to_second (t_Node* first, t_Node* second)
{
    second->smth=first->smth;
}

void Delete_Element (t_Node* element)
{
    t_Node* temp;
    if (element==head)
    {
        head=element->next;
        free(element);
    }else
    {
        for(temp=head;;)
        {
            if (temp->next==element)
            {
                break;
            }
            temp=temp->next;
        }
        temp->next=element->next;
        free(element);
    }
}


Sorry for the large amount of code, but otherwise it wouldn't be possible to see the full picture

  • regarding: `fflush(stdin);` the function: `fflush()` is for output streams. The C standard states that using `fflush()` with an input stream is undefined behavior. Suggest: `int ch; while( (ch = getchar() ) != EOF && ch != '\n' ){;}` – user3629249 May 24 '20 at 16:41
  • regarding: `gets(tempstruct.name);` the function: `gets()` has been depreciated for years and competely removed from the language since (about) 2009. Suggest using `fgets()` (which has a different parameter list, so read the MAN page for `fgets()` ) – user3629249 May 24 '20 at 16:43
  • 1
    OT: for ease of readability and understanding: 1) please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces. 2) Please follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* 3) separate code blocks: `for` `if` `else` `while` `do...while` `switch` `case` `default` via a single blank line – user3629249 May 24 '20 at 16:46
  • OT: regarding: `printf("\nmalloc crash\n");` Error messages are to be output to `stderr`, not `stdout`. When the error indication is from a C library function (like `malloc()` ) also output to `stderr` the text reason the system thinks the error occurred. The function: `perror()` is made for that purpose. – user3629249 May 24 '20 at 16:48
  • regarding; `if (NodeP==NULL){ printf("\nmalloc crash\n"); delete_List(head); }` the call to `malloc()` failed, so cannot use the returned value, as if the call were successful. Suggest, at least, exiting the function and (preferable) cleanup and exit the program. – user3629249 May 24 '20 at 16:51
  • regarding: `fread(&tempstruct,sizeof(tempstruct),1,file);` Always check the returned value to assure the operation was successful. Note: if the returned value does not match the third parameter, then some error occurred. – user3629249 May 24 '20 at 16:53
  • OT: for ease of readability and understanding: 1) use meaningful variable names. 2) separate functions by 2 or 3 blank lines (be consistent) – user3629249 May 24 '20 at 16:55
  • the posted code does not compile! please post a [mcve] so we can reproduce the problem and help you debug it. – user3629249 May 24 '20 at 16:57
  • regarding: `NodeP = (t_Node*)malloc(sizeof(t_Node));` in C, the function: `malloc()` returns a type: `void*` which can be assigned to any pointer. Casting just clutters the code and is error prone. Suggest removing that cast. – user3629249 May 24 '20 at 20:21
  • OT: regarding the three separate statements: `printf("Hello world!\n\n 1-Enter a new element/s.\n 2-Copy data from one element to another (by ID).\n 3-Switch data between two elements (by ID).\n 4-Delete an element (by ID)\n 5-Print all elements\n 6-Delete all elements\n 0-Exit\n");` (cont) – user3629249 May 24 '20 at 20:41
  • (cont) Good programming practice is to honor the right margin. (amongst other things, this makes it much easier to pass the code to a printer.) suggest: `printf("Hello world!\n\n"` newline `"1-Enter a new element/s.\n"` newline `"2-Copy data from one element to another (by ID).\n"` newline `"3-Switch data between two elements (by ID).\n"` newline `"4-Delete an element (by ID)\n"` newline `"5-Print all elements\n"` newline `"6-Delete all elements\n"` newline `"0-Exit\n");` which results in the CPU expensive `printf()` being called only once and the right margin not being exceeded – user3629249 May 24 '20 at 20:44
  • Now it adds only a single element at the end of the list, no matter how many I enter – Jordan Baller May 25 '20 at 08:10
  • What you are doing `while(1) if (feof(fp)) break; ...`, boils down to `while (!feof(file))` so you will want to look at [**Why is while ( !feof (file) ) always wrong?**](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) – David C. Rankin May 25 '20 at 08:24

0 Answers0