C Programing - Reading a text from standard input into dynamic array or a dynamic linked list and print it

Viewed 171
  1. Hi there, I am new to C Programing and I am trying to make a Program to Read and Print text from standard input (file or keyboard) as part of my studies.
  2. The rules are:
    • use two function one for read and one for print.
    • read function should read into dynamic array or dynamic linked list of arrays.
    • read function should ignore enter character ('\n').
    • the user should be able to choose one of two data struct types option (array or linked list).
    • print function should print the text in lines of 60characters.
    • the first memory allocation should be at the main function.
  3. I have been trying to solve this out for few weeks but getting stuck, any step will be helpful.
  4. I am still having problems in both function readText and printText
  5. There are some code that have not written yet because I could not check print function without make read function work out.
  6. The First problem is that the read function failed to allocate new memory after 120 characters.
  7. My Code:
/* This program will pick up text from the standard input store him at one of two data structure types and print it according to the following rules:
 8. every printed line will be at the size of 60 characters.
 9. if there is no more memory to allocate the program will print the text that stored until this moment.
 */

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

#define LINE_SIZE 60
#define BUFFER 1
#define LINKED_LIST 2

/* function prototype */

void readText(void *pointer,int dataStructType); /* function to read text from standard input and store it in a data structure */
void printText(void *pointer,int dataStructType); /* function to print text from a given data structure */

struct linkedList
{
    char data[LINE_SIZE];
    struct linkedList * next;
};

int main()
{ /* start of main function */

    void *pointer = NULL;
    int dataStructType = 0;
   /* message that asking the user to choose one of two functions to use */

    printf("please insert the number of the data structure you want to use and press enter:\n1 - Buffer.\n2 - Linked List.\n");
    scanf("%d",&dataStructType); /* collect the user input into dataStructType variable */

    while(dataStructType != BUFFER && dataStructType != LINKED_LIST) /* while the user put in an invalid option */
    {
        printf("invalid input!\tplease try again.\n\n"); /* print error message to the user and return the process */
        printf("please insert the number of the data structure you want to use and press enter:\n1 - Buffer.\n2 - Linked List.\n");
        scanf("%d",&dataStructType);
    }

    if(dataStructType == BUFFER) /* if the user chose buffer as the data structure type */
    {
        printf("you have chosen option one - Buffer data structure type.\n");
        pointer = (char*) calloc(LINE_SIZE, sizeof(char));
        if(!pointer) /* if pointer is NULL */
        {
            printf("error!\t memory allocation failed.\t please try again later."); /* error message for the user */
            return 0; /* exit main function and the program */
        }else /* if the memory allocation succeeded */
        {
            readText(pointer,dataStructType); /* call readText function with BUFFER dataStructType */
            printText(pointer,dataStructType); /* call printText function with BUFFER dataStructType  */
        }
    }else /* if the user chose linked list as the data structure type */
    {
        printf("you have chosen option two - Linked List data structure type.\n");

        struct linkedList * head = NULL;
        head = calloc(1, sizeof(struct linkedList));

        if(!head) /* if head is NULL */
        {
            printf("error!\t memory allocation failed.\t please try again later."); /* error message for the user */
            return 0; /* exit main function and the program */
        }else /* if the memory allocation succeeded */
        {
            pointer = head;
            readText(&pointer,dataStructType); /* call readText function with linkedList dataStructType */
            printText(pointer,dataStructType); /* call printText function with linkedList dataStructType  */
        }
    }
    return 0;
} /* end of main function */

/* readText function.
 *
 * mission: read text from standard input and store it in a data structure by the following rules:
 *      if there is not enough memory the function will try to find new memory for the structure.
 *      if the function cant find memory she will store the text until the memory is full and print him.
 *
 * parameters:
 *      pointer - points to the pointer that points to the start of the data structure.
 *      dataStructType - an integer that represent the data struct type.
 *
 * available data structures:
 *      1 - Buffer - Array.
 *      2 - linkedList - Linked List.
 */

void readText(void *pointer,int dataStructType)
{ /* start of readText function */
    int cnt = 0; /* count the number of characters collected into the the array until the end of the specific line (limited for 60 characters for a line) */
    int currentCell = 0; /* counter to count the collected characters **/
    char c; /* character variable to collect characters from the input */
    int lines = 1; /* lines counter */
    char *holder = NULL; /* temporary pointer to a new line */
    printf("please enter your text and in the end press cntrl+d\n");
    if(dataStructType == BUFFER) /* if the structure type is a buffer. */
    {
        while((c = getchar()) != EOF)
        {
            if (c != '\n') /* if the character is '\n' skip the character */
            {
                if (cnt == LINE_SIZE - 1) /* if this is the sixty character (starts from index 0) */
                {
                    cnt = 0; /* restart counter value */
                    lines++; /* add a "line" to calculate the memory size */
                    holder = (char *)realloc(pointer,  (lines * LINE_SIZE) * sizeof (char)); /* reallocate new memory including memory for a new "line" */
                    if (holder == NULL) /* if the memory allocation failed */
                    {
                        printf("error!\t memory allocation failed.\n the program will now print the successfully collected text.\n"); /* message for the user */
                        printf("after printing the collected text the program will be finished\n"); /* message for the user */
                        pointer = (pointer - (lines * LINE_SIZE)); /* re-aim the pointer to the buffer start */
                        printText(pointer, BUFFER); /* call printText function to print the collected text */
                    } else /* if the memory allocation succeeded */
                    {
                        free(pointer); /* free the old array memory */
                        pointer = holder; /* re-aim the pointer to the start of the new allocated memory */
                        /* pointer = (pointer + ((lines - 1) * LINE_SIZE)); /* re-aim the pointer to the start of the "new line" on the new allocated memory */
                    }
                } /* if we did not finished to collect text into a line and the character is not '\n' */
                *(char*)(pointer + currentCell) = c; /* place the character in the current cell of the array */
                cnt++; /* increment counter by one */
                currentCell++; /* increment current cell counter by one */
            }
        } *(char*)(pointer + currentCell) = c; /* place the character in the current cell of the array */
    }else /* if the structure type is a linked list. */
    {

    }
} /* end of readText function */



void printText(void *pointer,int dataStructType)
{
    if (dataStructType == BUFFER) /* if the data structure is buffer */
    {
        register int cnt = 0; /* count the number of characters printed from a specific line (limited for 60 characters for a line) */
        register int currentCell = 0; /* counter to count the collected characters */
        while (*(char*)pointer != EOF) /* if its the end of the file finish the printing */
        {
            if (cnt == 59) /* if we printed 60 characters print an enter for a new line */
            {
                printf("\n");
                cnt = 0;
            } else /* if there is more characters to print until 60 characters */
            {
                printf("%c", *(char*)(pointer + currentCell)); /* print the character */
                cnt++; /* count another character that was printed */
                currentCell++; /* increment current cell counter by one */
            }
        }
    } /* else if the data structure is a linked list */
}
2 Answers

Congratulations on working with C, once you're over the learning curve, your experience in it will be invaluable!

Some hints:

  • if you want to read into something dynamic, consider these options: provide a ** parameter, or return a * so that the caller can link to the memory returned by realloc
  • you're using free incorrectly, realloc handles freeing any memory
  • printf has length format specifiers which work with strings, and the function returns the number of bytes written
  1. I made a program that works! (sorry excited a little bit).
  2. Well this is the mistakes I found:
    • using free(); function in an unneeded spot. (following the reference of Yimin Rong).
    • Incorrect use of brackets while trying to get the pointer point value.
    • Incorrect use of printf(); function, instead I used putchar(); function to print the characters.
  3. Added free methods by David C. Rankin advice.
  4. Completed the linked list part in both functions.

Here is the completed code:

/* This program will pick up text from the standard input store him at one of two data structure types and print it according to the following rules:
 * every printed line will be at the size of 60 characters.
 * if there is no more memory to allocate the program will print the text that stored until this moment.
 */

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

#define LINE_SIZE 60
#define BUFFER 1
#define LINKED_LIST 2

/* function prototype */

void readText(void *pointer,int dataStructType); /* function to read text from standard input and store it in a data structure */
void printText(void *pointer,int dataStructType); /* function to print text from a given data structure */

struct Node
{
    char data[LINE_SIZE];
    struct Node * next;
};

int main()
{ /* start of main function */

    void *pointer = NULL;
    struct Node * head = NULL;
    int dataStructType = 0;
   /* message that asking the user to choose one of two functions to use */

    printf("please insert the number of the data structure you want to use and press enter:\n1 - Buffer.\n2 - Linked List.\n");
    scanf("%d",&dataStructType); /* collect the user input into dataStructType variable */

    while(dataStructType != BUFFER && dataStructType != LINKED_LIST) /* while the user put in an invalid option */
    {
        printf("invalid input!\tplease try again.\n\n"); /* print error message to the user and return the process */
        printf("please insert the number of the data structure you want to use and press enter:\n1 - Buffer.\n2 - Linked List.\n");
        scanf("%d",&dataStructType);
    }

    if(dataStructType == BUFFER) /* if the user chose buffer as the data structure type */
    {
        printf("you have chosen option one - Buffer data structure type.\n");
        pointer = calloc(LINE_SIZE, sizeof(char));
        if(!pointer) /* if pointer is NULL */
        {
            printf("error!\t memory allocation failed.\t please try again later."); /* error message for the user */
            return 0; /* exit main function and the program */
        }else /* if the memory allocation succeeded */
        {
            readText(pointer,dataStructType); /* call readText function with BUFFER dataStructType */
            printText(pointer,dataStructType); /* call printText function with BUFFER dataStructType  */
        }
    }else /* if the user chose linked list as the data structure type */
    {
        printf("you have chosen option two - Linked List data structure type.\n");


        head = (struct Node*)calloc(1, sizeof(struct Node));

        if(!head) /* if head is NULL */
        {
            printf("error!\t memory allocation failed.\t please try again later."); /* error message for the user */
            return 0; /* exit main function and the program */
        }else /* if the memory allocation succeeded */
        {
            pointer = head;
            readText(pointer,dataStructType); /* call readText function with linkedList dataStructType */
            printText(pointer,dataStructType); /* call printText function with linkedList dataStructType  */
        }
    }
    if(dataStructType == BUFFER) /* if the data struct type is buffer */
        free(pointer); /* free the program memory */
    else /* if data struct type is linked list */
    {
        pointer = head; /* re-aim the pointer to the first Node */
        while(head->next != NULL) /* if we have more unfree memory that used by Nodes */
        {
            pointer = (head->next); /* set the pointer to the next Node */
            free(head); /* free the node that pointed by head */
            head = NULL; /* safety step */
            head = pointer; /* re-aim head to the node that was not freed yet */
        }
    }
    return 0;
} /* end of main function */

/* readText function.
 *
 * mission: read text from standard input and store it in a data structure by the following rules:
 *      if there is not enough memory the function will try to find new memory for the structure.
 *      if the function cant find memory she will store the text until the memory is full and print him.
 *
 * parameters:
 *      pointer - points to the start of the data structure.
 *      dataStructType - an integer that represent the data struct type.
 *
 * available data structures:
 *      1 - Buffer - Array.
 *      2 - linkedList - Linked List.
 */

void readText(void *pointer,int dataStructType)
{ /* start of readText function */
    register int cnt = 0; /* count the number of characters collected into the the array until the end of the specific line (limited for 60 characters for a line) */
    register int currentCell = 0; /* counter to count the collected characters **/
    char c; /* character variable to collect characters from the input */
    int lines = 1; /* lines counter */
    void *holder = NULL; /* temporary pointer to a new line */
    printf("please enter your text and in the end press cntrl+d\n");
    if(dataStructType == BUFFER) /* if the structure type is a buffer. */
    {
        while((c = getchar()) != EOF)
        {
            if (c != '\n') /* if the character is '\n' skip the character */
            {
                if (cnt == LINE_SIZE - 1) /* if this is the sixty character (starts from index 0) */
                {
                    cnt = 0; /* restart counter value */
                    lines++; /* add a "line" to calculate the memory size */
                    holder = realloc(pointer,  ((lines * LINE_SIZE) * sizeof (char))); /* reallocate new memory including memory for a new "line" */
                    if (holder == NULL) /* if the memory allocation failed */
                    {
                        printf("error!\t memory allocation failed.\n the program will now print the successfully collected text.\n"); /* message for the user */
                        printf("after printing the collected text the program will be finished\n"); /* message for the user */
                        printText(pointer, BUFFER); /* call printText function to print the collected text */
                    } else /* if the memory allocation succeeded */
                    {
                        pointer = holder; /* re-aim the pointer to the start of the new allocated memory */
                     } /* if we did not finished to collect text into a line and the character is not '\n' */
                (*(((char*)pointer) + currentCell)) = c; /* place the character in the current cell of the array */
                cnt++; /* increment counter by one */
                currentCell++; /* increment current cell counter by one */
            }
        } *(((char*)pointer) + currentCell) = c;  /* place the EOF character to sine the end of the array */
    }else /* if the structure type is a linked list. */
    {
        holder = pointer; /* save the address of the first Node */
        while((c = getchar()) != EOF)
        {
            if (c != '\n') /* if the character is '\n' skip the character */
            {
                if(cnt == LINE_SIZE - 1) /* if this is the sixty character (starts from index 0) */
                {
                    cnt = 0; /* restart counter value */
                    lines++; /* in this case adding a new Node to calculate the memory size */
                    (((struct Node *)pointer)->next) = (struct Node*) calloc(1,sizeof (struct Node)); /* allocate new memory for another new Node and point the "last" Node pointer to the new Node */
                    if ((((struct Node *)pointer)->next) == NULL) /* if the memory allocation failed */
                    {
                        printf("error!\t memory allocation failed.\n the program will now print the successfully collected text.\n"); /* message for the user */
                        printf("after printing the collected text the program will be finished\n"); /* message for the user */
                        printText(pointer, LINKED_LIST); /* call printText function to print the collected text */
                    } else /* if the memory allocation succeeded */
                    {
                        pointer = ((struct Node*)pointer)->next; /* re-aim the pointer to the new node that allocated */
                    }
                } /* if we did not finished to collect text into a line and the character is not '\n' */
                (((struct Node *) pointer)->data[cnt]) = c;  /* place the character in the current cell of the array */
                cnt++; /* increment counter by one */
            }
        } (((struct Node *) pointer)->data[cnt]) = c; /* place the EOF character to sine the end of the array */
        pointer = holder; /* re-aim the pointer to the first Node */
    }
} /* end of readText function */


/* printText function.
 *
 * mission: print the text that was collected by readText function to one of two data struct types:
 *      print until the end of the file (the end of the collected text).
 *      print sixty characters per a line.
 *
 * parameters:
 *      pointer - points to the start of the data structure.
 *      dataStructType - an integer that represent the data struct type.
 *
 * available data structures:
 *      1 - Buffer - Array.
 *      2 - linkedList - Linked List.
 */

void printText(void *pointer,int dataStructType)
{ /* start of printText function */
    register int cnt = 0; /* count the number of characters printed from a specific line (limited for 60 characters for a line) */
    register int currentCell = 0; /* counter to count the collected characters */

    if (dataStructType == BUFFER) /* if the data structure is buffer */
    {
        while (*(((char*)pointer) + currentCell) != EOF) /* while we still have characters to print */
        {
            if (cnt == LINE_SIZE - 1) /* if we printed 60 characters print an enter for a new line */
            {
                printf("\n"); /* print a new line */
                cnt = 0; /* restart the counter */
            } else /* if there is more characters to print until 60 characters */
            {
                putchar(*(((char*)pointer) + currentCell)); /* print the character */
                cnt++; /* count another character that was printed */
                currentCell++; /* increment current cell counter by one */
            }
        }
    } else /* else if the data structure is a linked list */
    {
        while((((struct Node*)pointer)->data[cnt]) != EOF) /* while we still have characters to print */
        {
            if (cnt == LINE_SIZE - 1) /* if we printed 60 characters print an enter for a new line */
            {
                printf("\n"); /* print a new line */
                cnt = 0; /* restart the counter */
                if(((struct Node*)pointer)->next == NULL) /* if there are no more Nodes in the linked list */
                    exit(EXIT_FAILURE); /* exit the program because we finished to print the text */
                else /* if there are more nodes in the linked list */
                    pointer = ((struct Node*)pointer)->next; /* set the pointer to the next Node */
            }else /* if there is more characters to print until 60 characters */
            {
                putchar(((struct Node*)pointer)->data[cnt]); /* print the character */
                cnt++; /* count another character that was printed */
            }
        }
    }
} /* end of printText function */





Thank to anyone that was trying to help, love that community

Related