Search code examples
cpass-by-referencesingly-linked-listpass-by-valuefunction-definition

Can I use a CreatNode function to return a struct rather than its steps repeated in All other functions?


I want to make a CreatNode() function in C to be called by other functions. I am playing around with code trying to reach great readability and functionality. The professor has a CreatEmptyList() function but not a CreatNode().She is negligent and not the capable of the concepts and C lagnguage and didn't give me an answer.

I don't need this exploration and trying ideas that come to my mind to pass the course, but my aim is to become a Dev not to graduate.

This is the code of the Prof:

typedef struct nodetype
{
    int info;
    struct nodetype *next;
} node;
    node *head;

void createemptylist(node *head)
{
    head=NULL;
}

void insertatbeginning(node *head, int item)
{
    node *newNode;
    /* allocate memory for the new node and initialize the data in it*/
    newNode= malloc(sizeof(node));
    newNode->info=item;
    /* assign the value of head to the “next” of newNode*/
    newNode->next=head;
    /* assign the address of newNode to head */
    head=newNode;
}

void insertatend(node *head, int item)
{
    node *newNode;
    newNode=malloc(sizeof(node));
    newNode->info=item;
    newNode->next=NULL;
    if(head==NULL)
      head=newNode;
    else
    {
     node *prev=head;
     while(prev->next!=NULL)
     prev=prev->next;
     prev->next=newNode;
    }
}

All are the snippets from the PDF she provided not exactly a compilable code.

This is the code I am working on and it keeps giving errors:

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

    typedef struct Node{
        int info;
        struct Node *Next;
    }ListNode;

    ListNode CreatNode(ListNode *Head){///These steps not to be repeated using this function
        printf("\n=================\nEntered CreatNode Function");
        ListNode *NewNode;
        NewNode = malloc(sizeof(ListNode));

        return *NewNode;
    }

    void CreatList(ListNode *Head){
        printf("\n=================\nEntered CreatList Function");
        Head = NULL;
    }


    void InserBeg(ListNode *Head, int item){
        ///CreatNode() steps here

        NewNode=CreatNode(&Head);
        NewNode->info = item; ///Inesrt value
        NewNode->Next = Head;///Insert Adress inside Head to the Next point


        Head = NewNode;
        printf("\nFinished InsertBeg Function");
        printf("\nValue inserted is: %d\n=================\n", NewNode->info);
    }

    void Append(ListNode *Head, int item){
        ///CreatNode() steps here
        ///NewNode=CreatNode(Head);
        NewNode ->info = item;
        NewNode ->Next = NULL;
        
        if (Head==NULL){
            Head=ListNode
        }
        else{
            ListNode *Prev=Head;
            while(while->Prev!=NULL){
                Prev = Prev->Next;
            }
            Prev->Next=NewNode;
        }


    }



int main(){
    ListNode *Head;

    CreatList(&Head);
    InserBeg(&Head, 8);


    return 0;
}



errors:

C:\Users\User\Desktop\all\C\Single Linked List test.c|27|error: incompatible types when assigning to type 'ListNode * {aka struct Node *}' from type 'ListNode {aka struct Node}'|

Undeclared NewNode struct errors since it can't see it

Any help on coding my idea in different ways or make my code work?


Solution

  • The provided by the professor code is very bad.

    For starters she uses a global variable head. As the variable is declared in the file scope then it is already initialized as a null pointer. So this function

    void createemptylist(node *head)
    {
        head=NULL;
    }
    

    does not make a great sense. And moreover it does nothing with the original pointer head because it accepts its argument by value. That is it deals with a copy of the value of the original pointer.

    By this reason other functions insertatbeginning and insertatend are wrong because they do not change the original pointer head that they accept by value.

    void insertatbeginning(node *head, int item)
    {
        //...
        head=newNode;
    }
    
    void insertatend(node *head, int item)
    {
        //...
        head=newNode;
        //...
    }
    

    They change a copy of the value of the original pointer.

    The same problem is present in your functions.

    As for the function CreatNode then as is it does not make a sense.

    ListNode CreatNode(ListNode *Head){///These steps not to be repeated using this function
        printf("\n=================\nEntered CreatNode Function");
        ListNode *NewNode;
        NewNode = malloc(sizeof(ListNode));
    
        return *NewNode;
    }
    

    For starters the parameter head is not used within the function. You need to pass an integer argument to the function that will be used as an initializer for the data member info.

    Instead of an object of the type ListNode you should return a pointer to the dynamically allocated object. Otherwise the function returns a copy of the dynamically allocated object and as a result the function will produce a memory leak.

    Within the functions InserBeg and Append the name NewNode is undefined as for example

    void InserBeg(ListNode *Head, int item){
        ///CreatNode() steps here
    
        NewNode=CreatNode(&Head);
        //...
    

    And you are calling the functions passing expressions of incompatible pointer type ListNode ** instead of ListNode *.

    CreatList(&Head);
    InserBeg(&Head, 8);
    

    Here is a demonstration program that shows how the function CreateNode and for example InsertBeg can be defined.

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Node
    {
        int info;
        struct Node *next;
    } ListNode;
    
    ListNode * CreateNode( int info )
    {
        ListNode *new_node = malloc( sizeof( *new_node ) );
    
        if ( new_node != NULL )
        {
            new_node->info = info;
            new_node->next = NULL;
        }
    
        return new_node;
    }
    
    int InsertBeg( ListNode **head, int info )
    {
        ListNode *new_node = CreateNode( info );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->next = *head;
            *head = new_node;
        }
    
        return success;        
    }
    
    int main( void )
    {
        ListNode *head = NULL;
    
        if ( InsertBeg( &head, 10 ) )
        {
            puts( "New node is added." );
        }
        else
        {
            puts( "Error: not enough memory." );
        }
    }
    

    The program output is

    New node is added.