Search code examples
csplitlinked-listsingly-linked-listfunction-definition

split linked list of chars in C


I'm supposed to write a function called - "disAssemblyList" that gets a linked list of chars(without a dummy element). The function should move a nodes with big letters to "bigLetter" linked list (without a dummy element) , move nodes with small letters to "smallLetter" linked list, nums to "nums" linked list and other chars keep into original list.

I need to pass by reference the smallLetter, bigLetter and nums linked lists and return the list with other chars.

I need to scan the original list. The original list can be empty.

for example:

An original linked list:

3-> a-> 7-> M-> K-> u-> 5-> #-> &-> P-> %-> A

bigLetter:

M-> K-> P-> A

smallLetter:

a-> u

nums:

3-> 7-> 5

other chars (original list after the function runs):

#-> &-> %

I wrote this code and I cant seem to understand how to make it work. It does not scan the chars to linked list.

typedef struct chNode
{
    char data;
    struct chNode *next;
}chNode;


chNode * createCharList(char data)
{
    chNode *temp = (chNode*)malloc(sizeof(chNode));
    temp->data = data;
    temp->next = NULL;
    return temp;
}

chNode * addCharToLast(chNode *head, char data)
{
    chNode *p = head;
    chNode *temp = createCharList(data);
    if (head == NULL)
        return temp;
    while (p->next != NULL)
        p = p->next;
    p->next = temp;
    return head;
}

void printf_CharList(chNode *head)
{
    chNode *p = head;
    while (p != NULL)
    {
        printf("%d, ", p->data);
        p = p->next;
    }
    printf("\n\n");
}


chNode* insert_Charlist() // A function that imports numbers into a linked list , till -1
{
    char ch;
    chNode *Head = NULL;
    printf("Enter chars For Linked-List Till 'Enter':\n");
    //5scanf_s("%c", &ch);
    ch = getchar();
    while (ch != "\n")
    {

        Head = addCharToLast(Head, ch); //Makes last number to be First
        //scanf_s("%c", &ch);
        ch = getchar();
    }
    return Head;
}

void add_to_other_list(chNode** head, chNode* p)
{
    static chNode* tail = NULL;

    p->next = NULL;
    if (tail == NULL)
    {
        *head = p;
    }
    else
    {
        tail->next = p;
    }
    tail = p;
}


chNode* disAssemblyList(chNode* p, chNode **bigLetter, chNode **smallLetter, chNode **nums)
{
    chNode* t = NULL;

    if (p == NULL) return p;          // 0 elements
    if (p->next == NULL) return p;    // 1 element
    if (p->next->next == NULL)          // 2 elements
    {

        if ((p->next->data >= 65) && (p->next->data) <= 90)
        {
            // Move p->next to other list
            add_to_other_list(&(*bigLetter), p->next);
            p->next = NULL;
            return p;
        }
    }

    // Repeat as long as the list has minimum 3 elements
    while (p->next)
    {
        if ((p->next->data >= 65) && (p->next->data) <= 90)
        {
            // Move p-next
            t = p->next;
            p->next = p->next->next;
            add_to_other_list(&(*bigLetter), t);
        }

        if ((p->next->data >= 97) && (p->next->data) <= 122)
        {
            t = p->next;
            p->next = p->next->next;
            add_to_other_list(&(*smallLetter), t);
        }

        if ((p->next->data >= 48) && (p->next->data) <= 57)
        {
            t = p->next;
            p->next = p->next->next;
            add_to_other_list(&(*nums), t);

        }
        p = p->next;
    }

    return p;

}


void main()
{

    chNode *Orignial_list = NULL;
    chNode *bigLetter = NULL;
    chNode *smallLetter = NULL;
    chNode *nums = NULL;
    Orignial_list = insert_Charlist(); // Function that imports a list
    printf("You Entered This linked-list:\n");
    printf_CharList(Orignial_list); //Printing the linked list
    Orignial_list = disAssemblyList(Orignial_list,&bigLetter,&smallLetter,&nums);
    printf("The BigLetter Linked-List is:\n");
    printf_CharList(bigLetter);
    printf_CharList(smallLetter);
    printf_CharList(nums);
    printf_CharList(Orignial_list);
    getch();

}

Solution

  • I have not looked through all your code because as I have understood the question is about one function implementation that splits an original list to some other lists.

    Though I am sure that there are drawbacks in your code as for example the function print_CharList outputs internal codes of characters instead of characters stored in a list themselves.

    void printf_CharList(chNode *head)
    {
        chNode *p = head;
        while (p != NULL)
        {
            printf("%d, ", p->data);
            p = p->next;
        }
        printf("\n\n");
    }
    

    Or the function add_to_other_list with a static variable does not make a sense.

    Or this condition in beginning of the function disAssemblyList

    if (p->next == NULL) return p;    // 1 elementNevertheless the function 
    

    also does not make a sense.

    Nevertheless the function that splits a list can look as it is shown in the demonstrative program below.

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    typedef struct chNode
    {
        char data;
        struct chNode *next;
    } chNode;
    
    void clear( chNode **head )
    {
        while ( *head != NULL )
        {
            chNode *tmp = *head;
            *head = ( *head )->next;
            free( tmp );
        }
    }
    
    size_t assign( chNode **head, const char *s )
    {
        if ( *head ) clear( head );
        
        size_t n = 0;
        
        while ( *s && ( *head = malloc( sizeof( chNode ) ) ) != NULL )
        {
            ( *head )->data = *s++;
            ( *head )->next = NULL;
            head = &( *head )->next;
            ++n;
        }
        
        return n;
    }
    
    FILE * display( const chNode *head, FILE *fp )
    {
        for ( ; head != NULL; head = head->next )
        {
            fprintf( fp, "%c -> ", head->data );
        }
        
        fputs( "null", fp );
        
        return fp;
    }
    
    chNode * disAssemblyList( chNode *p, 
                              chNode **bigLetter, 
                              chNode **smallLetter, 
                              chNode **nums )
    {
        while ( *bigLetter ) bigLetter = &( *bigLetter )->next;
        while ( *smallLetter ) smallLetter = &( *smallLetter )->next;
        while ( *nums ) nums = &( *nums )->next;
    
        chNode **head = &p;
        
        while ( *head != NULL )
        {
            if ( isdigit( ( unsigned char )( *head )->data ) )
            {
                *nums = *head;
                *head = ( *head )->next;
                ( *nums )->next = NULL;
                nums = &( *nums )->next;
            }
            else if ( isupper( ( unsigned char )( *head )->data ) )
            {
                *bigLetter = *head;
                *head = ( *head )->next;
                ( *bigLetter )->next = NULL;
                bigLetter = &( *bigLetter )->next;
            }
            else if ( islower( ( unsigned char )( *head )->data ) )
            {
                *smallLetter = *head;
                *head = ( *head )->next;
                ( *smallLetter )->next = NULL;
                smallLetter = &( *smallLetter )->next;
            }
            else
            {
                head = &( *head )->next;
            }
        }
        
        return p;
    }   
    
    int main(void) 
    {
        chNode *head = NULL;
        
        assign( &head, "3a7MKu5#&P%A" );
        
        fputc( '\n', display( head, stdout ) );
        
        putchar( '\n' );
        
        chNode *bigLetter = NULL;
        chNode *smallLetter = NULL;
        chNode *nums = NULL;
        
        head = disAssemblyList( head, &bigLetter, &smallLetter, &nums );
        
        fputc( '\n', display( head, stdout ) );
        fputc( '\n', display( bigLetter, stdout ) );
        fputc( '\n', display( smallLetter, stdout ) );
        fputc( '\n', display( nums, stdout ) );
        
        clear( &head );
        clear( &bigLetter );
        clear( &smallLetter );
        clear( &nums );
    
        return 0;
    }     
    

    The program output is

    3 -> a -> 7 -> M -> K -> u -> 5 -> # -> & -> P -> % -> A -> null
    
    # -> & -> % -> null
    M -> K -> P -> A -> null
    a -> u -> null
    3 -> 7 -> 5 -> null
    

    If you are not allowed to use standard C functions from the header <ctype.h> then the while loop in the function disAssemblyList can look like

        while ( *head != NULL )
        {
            char c = ( *head )->data;
    
            if ( '0' <= c && c <= '9' )
            {
                *nums = *head;
                *head = ( *head )->next;
                ( *nums )->next = NULL;
                nums = &( *nums )->next;
            }
            else if ( 'A' <= c && c <= 'Z' )
            {
                *bigLetter = *head;
                *head = ( *head )->next;
                ( *bigLetter )->next = NULL;
                bigLetter = &( *bigLetter )->next;
            }
            else if ( 'a' <= c && c <= 'z' )
            {
                *smallLetter = *head;
                *head = ( *head )->next;
                ( *smallLetter )->next = NULL;
                smallLetter = &( *smallLetter )->next;
            }
            else
            {
                head = &( *head )->next;
            }
        }