Commit e2271526 authored by Dominik Widhalm's avatar Dominik Widhalm
Browse files

Added example solutions for task 6.08

parent 1b364e7f
/******************************************************************************
* C PROGRAMMING *
* BASIC EXERCISES - EXAMPLE SOLUTIONS *
* *
* Task_6.08: Text Analysis *
* Author: Dominik Widhalm *
* Email: dominik.widhalm@technikum-wien.at *
* Date: 2017-08-20 *
* *
******************************************************************************/
/***** INCLUDES ***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/***** MACROS *****************************************************************/
// Maximum length of strings (respectively of a line)
#define STRING_MAX 400
// (Optional) print the list elements
#define DEBUG 0
/***** TYPEDEFS ***************************************************************/
/* Enumeration type for text file processing return status */
typedef enum {SUCCESS, NOACCESS, NOTEXT, LONGLINE} readin_t;
/* Struct type for the double linked list */
typedef struct line {
// Content of this line (string)
char text[STRING_MAX];
// Number of characters in this line */
int char_count;
// Pointer to next element
struct line *next;
// Pointer to previous element
struct line *prev;
} line_t;
/***** FUNCTION PROTOTYPES ****************************************************/
line_t *line_new (char *text);
void list_add_line (line_t **head, line_t *new);
readin_t list_read_textfile (line_t **head, char *file);
void list_get_char_count (line_t *head);
int list_get_linenum (line_t *head);
int list_get_minimum (line_t *head);
int list_get_maximum (line_t *head);
double list_get_average (line_t *head);
void list_print_information (line_t *head);
void list_print (line_t* head);
/***** LOCAL FUNCTIONS ********************************************************/
/******************************************************************************
* line_new *
* @brief Function to create a new line element with the given content. *
* *
* This function creates a new line element and stores the given string *
* as line inside it. *
* *
* @param text Pointer to the text string to be stored *
* @return Address of the newly created line element *
******************************************************************************/
line_t *line_new (char *text) {
/* Allocate memory for the new entry */
line_t* new = (line_t*)malloc(sizeof(line_t));
/* Copy the given string */
strcpy(new->text,text);
/* Set character counter initially to 0 */
new->char_count = 0;
/* Set the list pointers initially to NULL */
new->next = NULL;
new->prev = NULL;
/* Return the address of the new element */
return new;
}
/******************************************************************************
* list_add_line *
* @brief Function to add a given element to the end of the list. *
* *
* This function adds the new element given by the new pointer to the *
* current list by setting the respective pointers accordingly. *
* *
* @param head Pointer to pointer to the first list element *
* @param new Pointer to the new element to be added *
******************************************************************************/
void list_add_line (line_t **head, line_t *new) {
/* Temporary pointer for the current position in the list */
line_t *curr = *head;
/* Check if the list is empty */
if (*head == NULL) {
/* Add new element as first and only element */
*head = new;
/* If the list is not empty */
} else {
/* Search for the last position */
while (curr->next != NULL) {
/* Go to the next element in list */
curr = curr->next;
}
/* Append the new element to the current element */
curr->next = new;
new->prev = curr;
}
/* A void function has nothing to return */
return;
}
/******************************************************************************
* list_read_textfile *
* @brief Function to read in the given text file. *
* *
* This function reads in the given text file and stores the content *
* line by line in a double linked list. *
* *
* @param head Pointer to pointer to the first list element *
* @param file Pointer to the string holding the file path *
* @retval SUCCESS Text file processed successfully *
* @retval NOACCESS Given file cannot be accessed *
* @retval NOTEXT Given file is no text file *
* @retval LONGLINE Given file contains a too long line *
******************************************************************************/
readin_t list_read_textfile (line_t **head, char *file) {
/* Temporary pointer to the newly created element */
line_t *new;
/* Temporary variables to read in the characters */
char read[STRING_MAX];
int tmp,index = 0;
/* Get the file extension */
char *ext = strrchr(file,'.');
/* Check if file has an extension */
if (ext == NULL) {
/* File is not a text file (no file extension) */
return NOTEXT;
/* Check if the file is a .TXT or .txt file */
} else if (strcmp(ext,".TXT") && strcmp(ext,".txt")) {
/* File is not a text file (according to file extension) */
return NOTEXT;
}
/* Try to open the given file */
FILE *fp = fopen(file,"r");
/* Check if file can be opened */
if (fp == NULL) {
/* File could not be opened */
return NOACCESS;
}
/* Read one character of the text file after the other ...
* You cannot use fgets() here, because it will not break at '\n'! */
while ((tmp = fgetc(fp))) {
/* Check index to avoid a buffer overflow */
if (index >= STRING_MAX) {
/* Close the opened file */
fclose(fp);
/* Return that a too long line was found */
return LONGLINE;
}
/* Check if the end of the file (EOF) has already been reached */
if (tmp == EOF) {
/* Check if index is currently 0 (empty last line) */
if (index > 0) {
/* Terminate the current line (string) */
read[index] = '\0';
/* Create a new element with current line */
new = line_new(read);
/* Add new element to the list */
list_add_line(head,new);
}
/* No more content to be done */
break;
/* Check if current character is a newline '\n' */
} else if (tmp == '\n') {
/* Terminate the current line (string) */
read[index] = '\0';
/* Reset the index to 0 */
index = 0;
/* Create a new element with current line */
new = line_new(read);
/* Add new element to the list */
list_add_line(head,new);
/* Otherwise copy the current character to the temp string */
} else {
read[index++] = (char)tmp;
}
}
/* Reading in the text file was successful */
return SUCCESS;
}
/******************************************************************************
* list_get_char_count *
* @brief Function to get the number of characters per line. *
* *
* This function traverses the given list and obtains the number of *
* characters in every line and stores this information in the *
* respective variable. *
* *
* @param head Pointer to the first list element *
******************************************************************************/
void list_get_char_count (line_t *head) {
/* Temporary pointer for the current position in the list */
line_t *curr = head;
/* Iterate over the entire list */
while (curr != NULL) {
/* Get and store the number of character */
curr->char_count = (int)strlen(curr->text);
/* Go to the next element */
curr = curr->next;
}
/* A void function has nothing to return */
return;
}
/******************************************************************************
* list_get_linenum *
* @brief Function to get the number of lines (elements) in list. *
* *
* This function returns the number of lines (equals number of elements *
* in the current list. *
* *
* @param head Pointer to the first list element *
* @retval Number of lines in the current list *
******************************************************************************/
int list_get_linenum (line_t *head) {
/* Temporary variable for the number of lines */
int linecount = 0;
/* Temporary pointer for the current position in the list */
line_t *curr = head;
/* Count the number of elements in list (equals number of lines) */
while (curr != NULL) {
/* Increase number of lines */
linecount++;
/* Go to the next element */
curr = curr->next;
}
/* Return the obtained number of lines */
return linecount;
}
/******************************************************************************
* list_get_minimum *
* @brief Function to get the minimum line length of the list. *
* *
* This function returns the minimal number of characters of the lines *
* stored in the given list. *
* *
* @param head Pointer to the first list element *
* @retval Minimum number of characters per line *
******************************************************************************/
int list_get_minimum (line_t *head) {
/* Temporary variable with the minimum value (starting with max. value) */
int min = STRING_MAX;
/* Temporary pointer for the current position in the list */
line_t *curr = head;
/* Iterate over the entire list */
while (curr != NULL) {
/* Check if current line is shorter than previously stored minimum value */
if (curr->char_count < min) {
/* Store this count as the new minimum */
min = curr->char_count;
}
/* Go to the next element */
curr = curr->next;
}
/* Returned the obtained minimum number of characters */
return min;
}
/******************************************************************************
* list_get_maximum *
* @brief Function to get the maximum line length of the list. *
* *
* This function returns the maximal number of characters of the lines *
* stored in the given list. *
* *
* @param head Pointer to the first list element *
* @retval Maximum number of characters per line *
******************************************************************************/
int list_get_maximum (line_t *head) {
/* Temporary variable with the maximum value (starting with min. value) */
int max = 0;
/* Temporary pointer for the current position in the list */
line_t *curr = head;
/* Iterate over the entire list */
while (curr != NULL) {
/* Check if current line is longer than previously stored maximum value */
if (curr->char_count > max) {
/* Store this count as the new minimum */
max = curr->char_count;
}
/* Go to the next element */
curr = curr->next;
}
/* Returned the obtained maximum number of characters */
return max;
}
/******************************************************************************
* list_get_average *
* @brief Function to get the average line length of the list. *
* *
* This function calculates the average number of characters of the *
* lines stored in the given list. *
* *
* @param head Pointer to the first list element *
* @retval Average number of characters per line *
******************************************************************************/
double list_get_average (line_t *head) {
/* Temporary variable for sum of characters per line */
long int sum = 0;
/* Temporary variable to store the number of entries */
int num_entries = list_get_linenum(head);
/* Temporary pointer for the current position in the list */
line_t *curr = head;
/* Iterate over the entire list */
while (curr != NULL) {
/* Add current count to the sum */
sum += curr->char_count;
/* Go to the next element */
curr = curr->next;
}
/* Calculate and return the average number */
return ((double)sum / (double)num_entries);
}
/******************************************************************************
* list_print_information *
* @brief Function to print information about the text file processed. *
* *
* This function gathers and prints the minimum, maximum and average *
* number of characters in the lines stored in the given structure. *
* *
* @param head Pointer to the first list element *
******************************************************************************/
void list_print_information (line_t *head) {
/* Print header */
printf("\nThe given text file ...\n");
/* Print number of lines */
printf("... contains %d lines of text\n",list_get_linenum(head));
/* Print minimum number of characters in line */
printf("... has the shortest line with %d characters\n",list_get_minimum(head));
/* Print maximum number of characters in line */
printf("... has the longest line with %d characters\n",list_get_maximum(head));
/* Print average number of characters in line */
printf("... has an average of %.2f characters per line\n\n",list_get_average(head));
/* A void function has nothing to return */
return;
}
/******************************************************************************
* list_print *
* @brief Function to print the current list. *
* *
* This function prints the current list (recursively). *
* *
* @param head Pointer to the first list element *
******************************************************************************/
void list_print (line_t* head) {
/* Print list recursively */
if (head != NULL) {
/* Print current element */
printf("(%3d) -> %s\n",head->char_count,head->text);
/* Call function with next element */
list_print(head->next);
}
/* A void function has nothing to return */
return;
}
/***** MAIN ROUTINE ***********************************************************/
int main (void) {
/*** Local Variables ***/
line_t *head = NULL;
line_t *tmp;
readin_t retval;
char path[STRING_MAX];
/* Ask the user to input the name of the text file */
printf("Please enter the name of the text file: ");
/* Read in the user input */
scanf("%s",path);
/* (Try to) read the given text file */
retval = list_read_textfile(&head,path);
/* Check if reading was successful */
switch (retval) {
case SUCCESS:
/* Reading of file was successful, get the character counts */
list_get_char_count(head);
/* (Optional) print the list elements */
if (DEBUG) {
printf("\nLines contained in text file (with character count):\n");
list_print(head);
}
/* Print the text file information */
list_print_information(head);
/* Finished processing */
break;
case NOACCESS:
/* The given file could not be accessed */
printf("\nThe given file could not be accessed!\n");
/* Finished processing */
break;
case NOTEXT:
/* The given file is not a text file */
printf("\nThe given file is not a text file!\n");
/* Finished processing */
break;
case LONGLINE:
/* The given file had too long line(s) */
printf("\nThe given file had too long line(s) (max. %d characters)!\n",STRING_MAX);
/* Finished processing */
break;
}
/* Release the allocated memory */
while (head != NULL) {
/* Save pointer to current element */
tmp = head;
/* Set head to the next element */
head = tmp->next;
/* Free memory of current element */
free(tmp);
}
/* Notify the user about the termination of the program */
printf("\nThe program will now be terminated...\n");
return 0; /* Return with Success (0) */
}
/******************************************************************************/
# Get the current path(s) (relevant directory on last position)
TASKPATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
CHPATH := $(dir $(TASKPATH:%/=%))
# Variables for text substitution
empty:=
slash:= /
space:= $(empty) $(empty)
task:= task_
ch:= ch_
# Get TASK number
TASK := $(subst $(slash),$(space),$(TASKPATH))
TASK := $(lastword $(TASK))
TASK := $(subst $(task),$(empty),$(TASK))
# Get CH number
CH := $(subst $(slash),$(space),$(CHPATH))
CH := $(lastword $(CH))
CH := $(subst $(ch),$(empty),$(CH))
# Specify SRD directory
SRCDIR = .
# Call superior makefile
include ../../makefile
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment