Commit 58a34fc5 authored by Dominik Widhalm's avatar Dominik Widhalm
Browse files

Added example solutions for task 6.14

parent 36723b6f
/******************************************************************************
* C PROGRAMMING *
* BASIC EXERCISES - EXAMPLE SOLUTIONS *
* *
* Task_6.14: *
* Author: Dominik Widhalm *
* Email: dominik.widhalm@technikum-wien.at *
* Date: 2017-09-04 *
* *
******************************************************************************/
/***** INCLUDES ***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/***** MACROS *****************************************************************/
// Maximum length of strings
#define STRING_MAX 80
/***** TYPEDEFS ***************************************************************/
/* Enumeration type for function return values */
typedef enum {SUCCESS, FAILED} retval_t;
/* Structure for a character (list) element */
typedef struct symbol {
/* Character to be stored */
char character;
/* Count of this symbol */
int count;
/* Pointer to the next element */
struct symbol *next;
} symbol_t;
/***** FUNCTION PROTOTYPES ****************************************************/
symbol_t *symbol_new (char character);
symbol_t *symbol_find (symbol_t *head, char character);
void symbol_print (symbol_t *head);
retval_t string_process (symbol_t **head, char *string);
void string_sort (symbol_t **head);
void string_print_stats (symbol_t *head);
/***** LOCAL FUNCTIONS ********************************************************/
/******************************************************************************
* symbol_new *
* @brief Function to create a new symbol element. *
* *
* This function creates a new symbol element and returns its address. *
* *
* @param character Character of the new symbol *
* @return Pointer to the new symbol *
******************************************************************************/
symbol_t *symbol_new (char character) {
/* Allocate memory for the new symbol */
symbol_t* new = (symbol_t*)malloc(sizeof(symbol_t));
/* Check if malloc was successful */
if (new == NULL) {
/* Memory could not be allocated */
return NULL;
}
/* Write given character to new element */
new->character = character;
/* The default count at moment of creation is 1 */
new->count = 1;
/* Initially set its pointer to NULL */
new->next = NULL;
/* Return the address of the new element */
return new;
}
/******************************************************************************
* symbol_find *
* @brief Function to search for a symbol in the current list. *
* *
* This function searches the current list for the availability of a *
* given character. If an element with this character is found the *
* address of this element is returned; otherwise NULL is returned. *
* *
* @param head Pointer to the head of the list *
* @param character Character to be searched for *
* @return Address of the element found; or NULL *
******************************************************************************/
symbol_t *symbol_find (symbol_t *head, char character) {
/* Temporary pointer to traverse the list */
symbol_t *curr = head;
/* Iterate over the list */
while (curr != NULL) {
/* Check if current element contains given characer */
if (curr->character == character) {
/* Current element contains this character */
return curr;
}
/* Go to the next element */
curr = curr->next;
}
/* If this point is reached no element with the character was found */
return NULL;
}
/******************************************************************************
* symbol_print *
* @brief Function to print the list elements recursively. *
* *
* This function prints the list elements recursively. *
* *
* @param head Pointer to the head of the list *
******************************************************************************/
void symbol_print (symbol_t *head) {
/* Print the current element */
printf("|--> '%c' | %3dd | 0x%02X -- %02d occurences\n",head->character,(int)head->character,(int)head->character,head->count);
/* Check if the end of the list has not been reached yet */
if (head->next != NULL) {
/* Call this function recursively with next element */
symbol_print(head->next);
}
/* A void function has nothing to return */
return;
}
/******************************************************************************
* string_process *
* @brief Function to process a given string. *
* *
* This function iterates over a given string and counts the occurrences *
* of the different characters contained dynamically. In the resulting *
* list only the characters available in the string are available. The *
* resulting list is not ordered; the elements appear in the order as *
* the character appear in the string. *
* *
* @param head Pointer to pointer of the head of the list *
* @param string String to be processed *
* @retval SUCCESS Successfully processed the given string *
* @retval FAILED Could not process the given string *
******************************************************************************/
retval_t string_process (symbol_t **head, char *string) {
/* Temporary pointer used to access certain list elements */
symbol_t *elem = NULL;
/* Temporary pointer to traverse the list */
symbol_t *curr = NULL;
/* Temporary character (used to fix letter case) */
char temp;
/* Iterate over the entire string */
while (*string != '\0') {
/* Store the current character */
temp = *string;
/* Check if character is upper case letter */
if ((temp >= 'A') && (temp <= 'Z')) {
/* Make character lower case */
temp += 'a'-'A';
}
/* Search for current character in list */
elem = symbol_find(*head,temp);
/* Check if character is already in list */
if (elem == NULL) {
/* Character is not yet in list ... create a new element */
elem = symbol_new(temp);
/* Check if element was created successfully */
if (elem == NULL) {
/* Could not create element --- return FAILED */
return FAILED;
} else {
/* Check if current list is empty */
if (*head == NULL) {
/* Add new element at the begin */
*head = elem;
} else {
/* Go to the end of the current list */
curr = *head;
while (curr->next != NULL) {
/* Go to the next element */
curr = curr->next;
}
/* Append new element to the list */
curr->next = elem;
}
}
} else {
/* Character is already in list ... increase its count */
elem->count++;
}
/* Continue with the next character in string */
string++;
}
/* Sort the acquired list of symbols */
string_sort(head);
/* String was successfully processed */
return SUCCESS;
}
/******************************************************************************
* string_sort *
* @brief Function to sort the current list in ascending order. *
* *
* This function sorts the current list in ascending order according to *
* the character contained, respectively the ASCII value of the *
* character contained. *
* *
* @param head Pointer to pointer of the head of the list *
******************************************************************************/
void string_sort (symbol_t **head) {
/* Temporary variables */
int swapped; // Remembers if there had been a swap or not
symbol_t* curr = *head; // Pointer to current element
symbol_t* prev; // Pointer to previous element
symbol_t* temp; // Temporary helper pointer
/* Check if the list is long enough to be sorted */
if ((curr == NULL) || (curr->next == NULL)) {
/* List is not long enough for sorting */
return;
}
/* Repeat sorting as long as there are swaps */
do {
/* Reset swapped to 0 */
swapped = 0;
/* Reset curr & prev to head */
curr = *head;
prev = *head;
/* Iterate over the entire list */
while (curr->next != NULL) {
/* Check if entries need to be swapped */
if (curr->character > curr->next->character) {
/* Check if current element is the head (first) element */
if (*head == curr) {
/* Swap elements */
*head = curr->next;
curr->next = (*head)->next;
(*head)->next = curr;
/* Correct curr & prev pointer */
curr = prev;
prev = *head;
} else {
/* Swap elements */
prev->next = curr->next;
curr->next = curr->next->next;
prev->next->next = curr;
/* Correct curr & prev pointer */
temp = curr;
curr = prev;
prev = temp;
}
/* Remember that there have been a swap */
swapped = 1;
/* Continue with next iteration over the entire loop */
break;
/* When not checking the first element */
} else if (*head != curr) {
/* Increment previous pointer */
prev = prev->next;
}
/* Continue with next element */
curr=curr->next;
}
} while (swapped == 1);
/* A void function has nothing to return */
return;
}
/******************************************************************************
* string_print_stats *
* @brief Function to print the statistics of the given string. *
* *
* This function prints the occurring characters as well as their number *
* of occurrences (count) in the given string. *
* *
* @param head Pointer to pointer of the head of the list *
******************************************************************************/
void string_print_stats (symbol_t *head) {
/* Check if there is a valid list of character */
if (head == NULL) {
/* There is no list */
printf("\nThe given list is empty!\n\n");
} else {
/* Print stats output header */
printf("\n========== STRING STATISTICS ==========\n");
/* Print the elements recursively */
symbol_print(head);
/* Print stats output footer */
printf("=======================================\n\n");
}
/* A void function has nothing to return */
return;
}
/***** MAIN ROUTINE ***********************************************************/
int main (void) {
/*** Local Variables ***/
symbol_t *head=NULL;
symbol_t *next=NULL;
char string[STRING_MAX];
/* Ask the user to enter a string */
printf("Please enter a string:\n");
/* Read in the user's input */
fgets(string,STRING_MAX,stdin);
/* Remove trailing newline */
strtok(string,"\n");
/* (Try to) process the string */
if (string_process(&head,string) == SUCCESS) {
/* Print the string statistics */
string_print_stats(head);
} else {
/* Could not process the given string */
printf("\nThe given string could not be processed!\n\n");
}
/* Release the allocated memory (use pointer "next" as helper) */
while (head != NULL) {
/* Save pointer to current element */
next = head;
/* Set head to the next element */
head = next->next;
/* Free memory of current element */
free(next);
}
/* Notify the user about the termination of the program */
printf("The 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
Markdown is supported
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