Initial commit

This commit is contained in:
github-classroom[bot] 2025-01-07 06:46:34 +00:00 committed by GitHub
commit 15c381aaae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 828 additions and 0 deletions

85
.gitignore vendored Normal file
View file

@ -0,0 +1,85 @@
# specific name of executable generated
algos
test_algos
# Created by https://www.gitignore.io/api/c++,macos,linux
# Edit at https://www.gitignore.io/?templates=c++,macos,linux
### C++ ###
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# End of https://www.gitignore.io/api/c++,macos,linux

26
Readme.md Normal file
View file

@ -0,0 +1,26 @@
## IF.03.22 POSE - Procedural Programming
# Assignment: Recursive vs. Iterative Algorithms
The assignment focusing on various problems that can be solved with an recursive as well as with an iterative algorithm.
## Tasks
Implement the algorithms of the problems defined in the following files:
1. sum_of_digits.c
1. count_char.c
1. reverse_string.c
Each problem shall be implemented using an recursive as well as an iterative algorithm. The functions are suffixed with '_recursive' and '_iterative' accordingly.
The detailed description can be found in the file header.
> Note: The corresponding header files are basically complete and
> do not need to be changed, except of entering your name.
## Expected result:
* All unit tests are passed
* Code is clean and follows coding guidelines
* Commit at least after implementing each single function

25
count_char.c Normal file
View file

@ -0,0 +1,25 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Count Character Occurrence
* Author: */ your name /*
* ----------------------------------------------------------
* Description:
* Recursive and iterative implementation of an algorithm that
* counts the occurrences of a specific character within a string.
* ----------------------------------------------------------
*/
/*
Instructions:
Define a function count_char(s, c) that takes a string `s` and the character 'c' to count as input.
Increase the counter by one, if the character matches the character at
the current position within the string and add the count of that character in the remaining string
until the end of the string ('\0').
*/
// TODO: the recursive implementation
// TODO: the iterative implementation

23
count_char.h Normal file
View file

@ -0,0 +1,23 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Count Character Occurrence
* Author: */ your name /*
* ----------------------------------------------------------
* Description:
* Recursive and iterative implementation of an algorithm that
* counts the occurrences of a specific character within a string.
* ----------------------------------------------------------
*/
/* *************************************************************
* see corresponding c-file for instructions
***************************************************************/
#ifndef ___COUNT_CHAR_H
#define ___COUNT_CHAR_H
int count_char_recursive(const char* str, char c);
int count_char_iterative(const char* str, char c);
#endif

36
main_driver.c Normal file
View file

@ -0,0 +1,36 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Running recursive and iterative algorithms
* Author: S. Schraml
* ----------------------------------------------------------
*/
#include "sum_of_digits.h"
#include "count_char.h"
#include "reverse_string.h"
#include <stdio.h>
#include <string.h>
int main() {
printf("\n===========================================\n");
printf("Executing recursive and iterative algorithms:\n");
int num = 1234;
printf("Sum of digits of %d is: %d (recursive) / %d (iterative)\n", num,
sum_of_digits_recursive(num), sum_of_digits_iterative(num));
char str[] = "banana";
char target = 'a';
printf("The character '%c' appears %d (recursive) / %d (iterative) times in \"%s\".\n", target,
count_char_recursive(str, target), count_char_iterative(str, target), str);
char str1[] = "hello";
char str2[] = "world";
reverse_string_recursive(str1, 0, strlen(str1) - 1);
reverse_string_iterative(str2, 0, strlen(str2) - 1);
printf("Reversed string: %s (recursive) / %s (iterative)\n", str1, str2);
printf("===========================================\n\n");
return 0;
}

84
makefile Normal file
View file

@ -0,0 +1,84 @@
CC = gcc
CCLINK = g++
LIBS =
CCOPTIONS = -Wall -pedantic -std=gnu11 -g
LDOPTIONS =
TEST = test_algos
PROGRAM = algos
LIBRARY_FILES = shortcut
ASSIGNMENT_FILES = sum_of_digits count_char reverse_string
MAIN_DRIVER = main_driver
TEST_DRIVER = test_driver
LIBRARY_H = $(addsuffix .h, $(LIBRARY_FILES))
ASSIGNMENT_H = $(addsuffix .h, $(ASSIGNMENT_FILES))
ASSIGNMENT_C = $(addsuffix .c, $(ASSIGNMENT_FILES)) $(MAIN_DRIVER).c
HDRS = $(ASSIGNEMT_H) $(SHARED_HDRS) $(COMMON_HDRS) $(LIBRARY_H)
TESTOBJECT = $(TEST_DRIVER).o
MAINOBJECT = $(MAIN_DRIVER).o
LIBRARY_OBJS = $(addsuffix .o, $(LIBRARY_FILES))
TEST_OBJS = $(addprefix test_, $(addsuffix .o, $(ASSIGNMENT_FILES)))
MAIN_OBJ = $(addsuffix .o, $(ASSIGNMENT_FILES))
OBJS = $(LIBRARY_OBJS) $(MAIN_OBJ) $(TEST_OBJS)
DOXY = doxygen
all: $(PROGRAM)
./$(PROGRAM)
$(TEST): $(OBJS) $(TESTOBJECT)
$(CCLINK) -o $@ $(LDOPTIONS) $(OBJS) $(TESTOBJECT)
$(PROGRAM): $(OBJS) $(MAINOBJECT)
$(CCLINK) -o $@ $(LDOPTIONS) $(OBJS) $(MAINOBJECT)
.PHONY: clean cleanall doxy test setsample setassignment definesample defineassignment assignmentfolder
clean:
rm -f $(PROGRAM) $(TEST) $(TESTOBJECT) $(MAINOBJECT) $(OBJS)
cleanall:
rm -f $(PROGRAM) $(TEST) $(TESTOBJECT) $(MAINOBJECT) $(OBJS) index.html
rm -R html
doxy:
$(DOXY)
rm -f index.html
ln -s html/index.html index.html
test: $(TEST)
./$(TEST)
%.o: %.c
$(CC) $(CCOPTIONS) -c $<
#sets project as sample solution
setsample:
$(foreach name, $(ASSIGNMENT_H) $(ASSIGNMENT_C), cp $(name).sample $(name);)
#sets project as assignment
setassignment:
$(foreach name, $(ASSIGNMENT_H) $(ASSIGNMENT_C), cp $(name).assignment $(name);)
# defines current state of project as sample solution
definesample:
$(foreach name, $(ASSIGNMENT_H) $(ASSIGNMENT_C), cp $(name) $(name).sample;)
# defines current sate of project as assignment
defineassignment :
$(foreach name, $(ASSIGNMENT_H) $(ASSIGNMENT_C), cp $(name) $(name).assignment;)
# creates a folder which can serve as a publishable assignment
assignmentfolder:
make setassignment
make doxy
rm -rf ../assignment
mkdir ../assignment
cp -R * ../assignment
cp .gitignore ../assignment
rm ../assignment/*.sample
rm ../assignment/*.assignment
make cleanall

25
reverse_string.c Normal file
View file

@ -0,0 +1,25 @@
/*----------------------------------------------------------
* HTBLA-Leonding / Class: <your class>
* ---------------------------------------------------------
* Title: Reverse String
* Author: */ your name /*
* ----------------------------------------------------------
* Description:
* Recursive and iterative implementation of an algorithm that
* reverses a given string.
* ----------------------------------------------------------
*/
/*
Instructions:
Define a function reverse_string(s) that takes a string `s` as input.
Take the last character of `s` and concatenate it with the result of reversing the rest of the string until the string has less than two characters.
Note that strings that are stored on heap or stack are provided - they can be directly manipulated.
*/
// TODO: the recursive implementation
// TODO: the iterative implementation

25
reverse_string.h Normal file
View file

@ -0,0 +1,25 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Reverse String
* Author: */ your name /*
* ----------------------------------------------------------
* Description:
* Recursive and iterative implementation of an algorithm that
* reverses a given string.
* ----------------------------------------------------------
*/
/* *************************************************************
* see corresponding c-file for instructions
***************************************************************/
#ifndef ___REVERSE_STRING_H
#define ___REVERSE_STRING_H
#include <stdbool.h>
void reverse_string_recursive(char* str, int start, int end);
void reverse_string_iterative(char* str, int start, int end);
#endif

151
shortcut.c Normal file
View file

@ -0,0 +1,151 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: shortcut.c
* Author: P. Bauer
* Date: November 08, 2010
* ----------------------------------------------------------
* Description:
* Test driver.
* ----------------------------------------------------------
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "shortcut.h"
#define MAX_TEST_FUNCTIONS 256
static char assert_msg_buffer[1024];
static int tc_count = 0;
static int tc_fail_count = 0;
static struct TestCase test_cases[MAX_TEST_FUNCTIONS];
const char* version()
{
return "ShortCut v. 1.3.0";
}
char* format_msg(char* format, ...) {
va_list args;
va_start (args, format);
vsprintf(assert_msg_buffer, format, args);
return assert_msg_buffer;
}
void assert_true(bool bool_expr, struct TestCase *tc, const char *msg,
const char* file, int line)
{
if (!bool_expr) {
if (tc->success) {
tc->success = false;
tc_fail_count++;
}
printf("\n\tFailure (file: %s, line %d): %s: %s", file, line, tc->name, msg);
}
}
void assert_false(bool bool_expr, struct TestCase *tc, const char *msg,
const char* file, int line)
{
assert_true(!bool_expr, tc, msg, file, line);
}
static void assert_string_failure(const char *expected, char *actual, struct TestCase *tc,
const char *msg, const char* file, int line);
void assert_equals_str(const char *expected, char *actual, struct TestCase *tc,
const char *msg, const char* file, int line)
{
if (expected == actual) {
return;
}
if (expected == 0 || actual == 0) {
assert_string_failure(expected, actual, tc, msg, file, line);
return;
}
if (strcmp(actual, expected) != 0) {
assert_string_failure(expected, actual, tc, msg, file, line);
return;
}
}
#define MAX_MSG_LEN 128
static void assert_string_failure(const char *expected, char *actual, struct TestCase *tc,
const char *msg, const char* file, int line)
{
char new_msg[MAX_MSG_LEN];
sprintf(new_msg, "Expected \"%s\", actual \"%s\". %s", expected, actual, msg);
assert_true(false, tc, new_msg, file, line);
}
void assert_equals(int expected, int actual, struct TestCase *tc,
const char *msg, const char* file, int line)
{
char new_msg[MAX_MSG_LEN];
sprintf(new_msg, "Expected %d, actual %d. %s", expected, actual, msg);
assert_true(expected == actual, tc, new_msg, file, line);
}
void assert_equals_f(double expected, double actual, double tolerance, struct TestCase* tc,
const char* msg, const char* file, int line)
{
char new_msg[MAX_MSG_LEN];
sprintf(new_msg, "Expected %f, actual %f. %s", expected, actual, msg);
double min_val = expected - tolerance;
double max_val = expected + tolerance;
assert_true(min_val <= actual && actual <= max_val, tc, new_msg, file, line);
}
int get_test_count()
{
return tc_count;
}
bool add_test(void (*test_function)(struct TestCase *tc), const char *test_name)
{
if (tc_count == MAX_TEST_FUNCTIONS) {
return false;
}
else {
test_cases[tc_count].success = true;
test_cases[tc_count].name = test_name;
test_cases[tc_count].test_function = test_function;
tc_count++;
return true;
}
}
void run_tests()
{
int i;
printf("\n%s: Running tests\n", version());
for (i = 0; i < get_test_count(); i++) {
printf("Running test %s ...", test_cases[i].name);
test_cases[i].test_function(&test_cases[i]);
if (test_cases[i].success) {
printf("\033[32m OK\033[m");
}
else {
printf("\033[31m ... FAIL\033[m");
}
printf("\n");
}
printf("\nTotal tests run: %d\n", tc_count);
if (tc_fail_count > 0) {
printf("\033[31mTests failed: %d\033[m\n", tc_fail_count);
}
else {
printf("\033[32mAll tests run successfully\033[m\n");
}
}

110
shortcut.h Normal file
View file

@ -0,0 +1,110 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: shortcut
* Author: P. Bauer
* Date: November 03, 2010
* ----------------------------------------------------------
* Description:
* A simple unit testing frame work for C.
* ----------------------------------------------------------
*/
#ifndef ___SHORTCUT_H
#define ___SHORTCUT_H
#include <stdbool.h>
/** TestCase is the struct to define one test case. A test case can
*** be added to a test. If the test is run all added test cases are
*** run and the result of the run of each test case is checked automatically.
*/
struct TestCase {
const char *name;
/** true if the test passed, false otherwise. */
bool success;
/** The test function which is executed by the test framework. */
void (*test_function)(struct TestCase *tc);
};
/**
*** @return Version of shortcut as string
***/
const char* version();
/**
*** @return The formatted string as generated using sprintf(format, ...)
***/
char* format_msg(char* format, ...);
/** assert_true checks, whether a boolean expression passed is true or false.
*** in case it is false the test case stating the assertion is marked
*** as failed and msg is printed.
*** @param bool_expr Expression which is evaluated.
*** @param tc Pointer to the test case which states this assertion.
*** @param msg Message to be printed if assertion evaluates to false.
*** @param file File in which the assert is given.
*** @param line Line in which the assert is given.
*/
void assert_true(bool bool_expr, struct TestCase *tc, const char *msg,
const char* file, int line);
/** assert_false does the same as assert() but the boolean expression
*** has to evaluate to false. If it evaluates to true the assertion
*** fails.
*** @see assert
*/
void assert_false(bool bool_expr, struct TestCase* tc, const char* msg,
const char* file, int line);
/** assert_equals checks whether two values are equal. Currently the following
*** data formats are supported:
*** - strings
*** - integer
*** @param expected The expected string value
*** @param actual The actual string value
*** @param tc Pointer to the test case which states this assertion.
*** @param msg Message to be printed if assertion evaluates to false.
*** @param file File in which the assert is given.
*** @param line Line in which the assert is given.
*** @see assert
*/
void assert_equals(int expected, int actual, struct TestCase* tc,
const char* msg, const char* file, int line);
void assert_equals_str(const char* expected, char* actual, struct TestCase* tc,
const char* msg, const char* file, int line);
void assert_equals_f(double expected, double actual, double tolerance, struct TestCase* tc,
const char* msg, const char* file, int line);
/** @return The total number of test cases added to the test.
*/
int get_test_count();
/** add_test creates a new test case and adds the a test function to
*** this test case.
*** @param test_function Pointer to the test function to be added
*** to the newly created test case.
*** @param test_case_name Name which should be assigned to the newly
*** created test case.
*/
bool add_test(void (*test_function)(struct TestCase *tc), const char *test_case_name);
void run_tests();
#define TEST(testname) void testname(struct TestCase *tc)
#define MSG(format, ...) format_msg(format, ##__VA_ARGS__)
#define ASSERT_TRUE(condition, msg) assert_true(condition, tc, msg, __FILE__, __LINE__)
#define ASSERT_FALSE(condition, msg) assert_false(condition, tc, msg, __FILE__, __LINE__)
#define ASSERT_EQUALS(expected, actual) assert_equals(expected, actual, tc, "", __FILE__, __LINE__)
#define ASSERT_EQUALS_STR(expected, actual) assert_equals_str(expected, actual, tc, "", __FILE__, __LINE__)
#define ASSERT_EQUALS_TOLERANCE(expected, actual, tolerance) assert_equals_f(expected, actual, tolerance, tc, "", __FILE__, __LINE__)
#define ADD_TEST(testfunction) add_test(testfunction, #testfunction)
#endif

23
sum_of_digits.c Normal file
View file

@ -0,0 +1,23 @@
/*----------------------------------------------------------
* HTBLA-Leonding / Class: <your class>
* ---------------------------------------------------------
* Title: Sum of Digits
* Author: */ your name /*
* ----------------------------------------------------------
* Description:
* Recursive and iterative implementation of an algorithm that calculates
* the sum of the digits of a given positive integer.
* ----------------------------------------------------------
*/
/*
Instructions:
Define a function sum_of_digits(n) that takes a positive integer `n` as input.
The sum of digits can be calculated as n mod 10 + sum of digits of n / 10 as long as n is larger than ten.
*/
// TODO: the recursive implementation
// TODO: the iterative implementation

25
sum_of_digits.h Normal file
View file

@ -0,0 +1,25 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Sum of Digits
* Author: */ your name /*
* ----------------------------------------------------------
* Description:
* Recursive and iterative implementation of an algorithm that calculates
* the sum of the digits of a given positive integer.
* ----------------------------------------------------------
*/
/* *************************************************************
* see corresponding c-file for instructions
***************************************************************/
#ifndef ___SUM_OF_DIGITS_H
#define ___SUM_OF_DIGITS_H
#include <stdbool.h>
int sum_of_digits_recursive(int n);
int sum_of_digits_iterative(int n);
#endif

43
test_count_char.c Normal file
View file

@ -0,0 +1,43 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Unit tests for 'Count Char'
* Author: S. Schraml
* ----------------------------------------------------------
*/
#include "test_count_char.h"
#include <stdio.h>
#include <string.h>
#include "count_char.h"
TEST(test_count_char_rec) {
char str1[] = "coconut";
int res = count_char_recursive(str1, 'o');
ASSERT_EQUALS(2, res);
res = count_char_recursive(str1, 'a');
ASSERT_EQUALS(0, res);
char str2[] = "Y";
res = count_char_recursive(str2, 'y');
ASSERT_EQUALS(0, res);
char str3[] = "";
res = count_char_recursive(str3, 'z');
ASSERT_EQUALS(0, res);
}
TEST(test_count_char_itr) {
char str1[] = "coconut";
int res = count_char_recursive(str1, 'o');
ASSERT_EQUALS(2, res);
res = count_char_recursive(str1, 'a');
ASSERT_EQUALS(0, res);
char str2[] = "Y";
res = count_char_recursive(str2, 'y');
ASSERT_EQUALS(0, res);
char str3[] = "";
res = count_char_recursive(str3, 'z');
ASSERT_EQUALS(0, res);
}

16
test_count_char.h Normal file
View file

@ -0,0 +1,16 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Unit tests for 'Count Char'
* Author: S. Schraml
* ----------------------------------------------------------
*/
#ifndef ___TEST_COUNT_CHAR_H
#define ___TEST_COUNT_CHAR_H
#include "shortcut.h"
TEST(test_count_char_rec);
TEST(test_count_char_itr);
#endif

27
test_driver.c Normal file
View file

@ -0,0 +1,27 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Test Driver recursive and iterative algorithms
* Author: S. Schraml
* ----------------------------------------------------------
*/
#include "shortcut.h"
#include "test_sum_of_digits.h"
#include "test_reverse_string.h"
#include "test_count_char.h"
int main(int argc, char *argv[])
{
ADD_TEST(test_sum_of_digits_rec);
ADD_TEST(test_sum_of_digits_itr);
ADD_TEST(test_count_char_rec);
ADD_TEST(test_count_char_itr);
ADD_TEST(test_reverse_string_rec);
ADD_TEST(test_reverse_string_itr);
run_tests();
return 0;
}

39
test_reverse_string.c Normal file
View file

@ -0,0 +1,39 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Unit tests for 'Reverse String'
* Author: S. Schraml
* ----------------------------------------------------------
*/
#include "test_reverse_string.h"
#include <stdio.h>
#include <string.h>
#include "reverse_string.h"
TEST(test_reverse_string_rec) {
char str1[] = "testing";
reverse_string_recursive(str1, 0, strlen(str1) - 1);
ASSERT_EQUALS_STR("gnitset", str1);
char str2[] = "X";
reverse_string_recursive(str2, 0, strlen(str2) - 1);
ASSERT_EQUALS_STR("X", str2);
char str3[] = "";
reverse_string_recursive(str3, 0, strlen(str3) - 1);
ASSERT_EQUALS_STR("", str3);
}
TEST(test_reverse_string_itr) {
char str1[] = "testing";
reverse_string_recursive(str1, 0, strlen(str1) - 1);
ASSERT_EQUALS_STR("gnitset", str1);
char str2[] = "X";
reverse_string_recursive(str2, 0, strlen(str2) - 1);
ASSERT_EQUALS_STR("X", str2);
char str3[] = "";
reverse_string_recursive(str3, 0, strlen(str3) - 1);
ASSERT_EQUALS_STR("", str3);
}

16
test_reverse_string.h Normal file
View file

@ -0,0 +1,16 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Unit tests for 'Reverse String'
* Author: S. Schraml
* ----------------------------------------------------------
*/
#ifndef ___TEST_REVERSE_STRING_H
#define ___TEST_REVERSE_STRING_H
#include "shortcut.h"
TEST(test_reverse_string_rec);
TEST(test_reverse_string_itr);
#endif

33
test_sum_of_digits.c Normal file
View file

@ -0,0 +1,33 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Unit tests for 'Sum of Digits'
* Author: S. Schraml
* ----------------------------------------------------------
*/
#include "test_sum_of_digits.h"
#include <stdio.h>
#include <string.h>
#include "sum_of_digits.h"
TEST(test_sum_of_digits_rec) {
int res = sum_of_digits_recursive(5);
ASSERT_EQUALS(5, res);
res = sum_of_digits_recursive(42);
ASSERT_EQUALS(6, res);
res = sum_of_digits_recursive(1234);
ASSERT_EQUALS(10, res);
}
TEST(test_sum_of_digits_itr) {
int res = sum_of_digits_iterative(3);
ASSERT_EQUALS(3, res);
res = sum_of_digits_iterative(20);
ASSERT_EQUALS(2, res);
res = sum_of_digits_iterative(4321);
ASSERT_EQUALS(10, res);
}

16
test_sum_of_digits.h Normal file
View file

@ -0,0 +1,16 @@
/*----------------------------------------------------------
* HTBLA-Leonding
* ---------------------------------------------------------
* Title: Unit tests for 'Sum of Digits'
* Author: S. Schraml
* ----------------------------------------------------------
*/
#ifndef ___TEST_SUM_OF_DIGITS_H
#define ___TEST_SUM_OF_DIGITS_H
#include "shortcut.h"
TEST(test_sum_of_digits_rec);
TEST(test_sum_of_digits_itr);
#endif