File Path checking and more comments

This commit is contained in:
Frederik Beimgraben 2025-01-13 00:30:11 +01:00
parent f1783f7ce8
commit e84e1d5100
2 changed files with 110 additions and 18 deletions

View File

@ -11,19 +11,35 @@
* https://git.beimgraben.net/MMS-2024-25/MMS-Loesung-2024-25.git * https://git.beimgraben.net/MMS-2024-25/MMS-Loesung-2024-25.git
*/ */
// Standard Libraries
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> // For variadic functions
#include <sys/stat.h> // For checking if a file exists
// Header File for this implementation
#include "MMS24-25.h" #include "MMS24-25.h"
#include "math.h"
// Preprocessor Definitions in case they are not defined
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef NULL
#define NULL 0
#endif
// #region Error Handling and Debugging // #region Error Handling and Debugging
void _error(char *fmt, ...) { void _error(char *fmt, ...) {
fprintf(stderr, "< \x1B[31;4;1mERROR\x1B[0m : \x1B[34m'"); fprintf(stderr, "< \x1B[31;4;1mERROR\x1B[0m : \x1B[34m'");
// Pass the arguments to the vfprintf function
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
// Write to stderr so that the output does not interfere with the output
vfprintf(stderr, fmt, args); vfprintf(stderr, fmt, args);
va_end(args); va_end(args);
@ -34,6 +50,21 @@ void _error(char *fmt, ...) {
#endif #endif
} }
void _mem_error(char *fmt, ...) {
fprintf(stderr, "< \x1B[31;4;1mMEM_ERROR\x1B[0m : \x1B[34m'");
// Pass the arguments to the vfprintf function
va_list args;
va_start(args, fmt);
// Write to stderr so that the output does not interfere with the output
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "'\x1B[0m >\n");
exit(EXIT_FAILURE);
}
void _debug(char *fmt, ...) { void _debug(char *fmt, ...) {
fprintf(stderr, "[ \x1B[37;4;1mDEBUG\x1B[0m ] \x1B[34m'"); fprintf(stderr, "[ \x1B[37;4;1mDEBUG\x1B[0m ] \x1B[34m'");
@ -58,6 +89,11 @@ void _warn(char *fmt, ...) {
// #endregion // #endregion
// #region Aufgabe 1 // #region Aufgabe 1
/*
* Interpolates a line between two points (x1, y1) and (x2, y2) and returns
* the y-coordinate of the point on the line at xq.
*/
double interpolateLine( double interpolateLine(
double dX1, double dX1,
double dY1, double dY1,
@ -66,6 +102,10 @@ double interpolateLine(
double dXq double dXq
) { ) {
if (dX2 == dX1) if (dX2 == dX1)
/*
* If the two x-coordinates are equal, the line is either vertical or
* could have any slope. In this case, we cannot interpolate the line.
*/
_error("interpolateLine: dX1 and dX2 must differ!"); _error("interpolateLine: dX1 and dX2 must differ!");
double y = dY1 * ( double y = dY1 * (
@ -74,15 +114,19 @@ double interpolateLine(
(dXq - dX1) / (dX2 - dX1) (dXq - dX1) / (dX2 - dX1)
); );
#ifdef _DEBUG_ #ifdef _DEBUG_
// DEBUG: print the parameters and result // DEBUG: print the parameters and result
_debug("interpolateLine(%lf, %lf, %lf, %lf, %lf) -> %lf\n", _debug("interpolateLine(%lf, %lf, %lf, %lf, %lf) -> %lf",
dX1,dY1,dX2,dY2,dXq,y); dX1,dY1,dX2,dY2,dXq,y);
#endif #endif
return y; return y;
} }
/*
* Rescales an array of double values so that the minimum value is dMin and
* the difference between any two values is scaled by dFactor.
*/
void rescaleDoubleArray( void rescaleDoubleArray(
double *pdIn, double *pdIn,
int iLen, int iLen,
@ -90,14 +134,21 @@ void rescaleDoubleArray(
double dFactor, double dFactor,
double *pdOut double *pdOut
) { ) {
/* Rescale an array of double values, so that the following rules apply: /*
* Rescale an array of double values, so that the following rules apply:
* Given $ |pdIn| = |pdOut| = iLen $ it should be, that: * Given $ |pdIn| = |pdOut| = iLen $ it should be, that:
* $ min(pdIn) > dMin $, as well as * $ min(pdIn) = dMin $, as well as
* \[ \forall i, j \in (0,\dots,iLen-1): * \[ \forall i, j \in (0,\dots,iLen-1):
* (pdOut_i - pdOut_j) = (pdIn_i - pdIn_j) *dFactor \], * (pdOut_i - pdOut_j) = (pdIn_i - pdIn_j) *dFactor \],
* which naturally results from: * which naturally results from:
* $ pdOut_i = pdIn_i *dFactor + dMin $ * $ pdOut_i = pdIn_i *dFactor + (dMin - min(pdIn)) $.
*/ */
if (iLen == 0) {
_warn("rescaleDoubleArray: iLen is 0");
return;
}
// First find the old minimum // First find the old minimum
double dOldMin = pdIn[0]; double dOldMin = pdIn[0];
for (int i = 1; i < iLen; i++) { for (int i = 1; i < iLen; i++) {
@ -108,6 +159,11 @@ void rescaleDoubleArray(
// Calculate the offset // Calculate the offset
double dOffset = dMin - dOldMin; double dOffset = dMin - dOldMin;
#ifdef _DEBUG_
_debug("rescaleDoubleArray: dOldMin = %lf", dOldMin);
_debug("rescaleDoubleArray: dOffset = %lf", dOffset);
#endif
// Rescale the array // Rescale the array
for (int i = 0; i < iLen; i++) { for (int i = 0; i < iLen; i++) {
pdOut[i] = pdIn[i] * dFactor + dOffset; pdOut[i] = pdIn[i] * dFactor + dOffset;
@ -119,30 +175,47 @@ double *generateSineValues(
int iNumSamplesPerPeriod, int iNumSamplesPerPeriod,
double dAmp double dAmp
) { ) {
/* Generate an array of `iNumValues` double value, so that the values /*
* Generate an array of `iNumValues` double value, so that the values
* represent the Y-coordinates of a sine curve of which one full period * represent the Y-coordinates of a sine curve of which one full period
* occupies `iNumSamplesPerPeriod` values. * occupies `iNumSamplesPerPeriod` values.
*/ */
// Check for invalid input
if (iNumSamplesPerPeriod == 0) if (iNumSamplesPerPeriod == 0)
/*
* This is a fatal error, since we cannot generate a sine wave without
* a period
*/
_error("*generateSineValues: iNumSamplesPerPeriod must be non-0!"); _error("*generateSineValues: iNumSamplesPerPeriod must be non-0!");
if (iNumSamplesPerPeriod < 0) if (iNumSamplesPerPeriod < 0)
/*
* This would result in a flipped sine wave; Wont lead to a fatal error
* but is still invalid; Warn the user.
*/
_warn("*generateSineValues: iNumSamplesPerPeriod is less than 0!"); _warn("*generateSineValues: iNumSamplesPerPeriod is less than 0!");
if (iNumValues < 0) if (iNumValues < 0)
/*
* It is not possible to generate a negative number of values; This is
* a fatal error.
*/
_error("*generateSineValues: iNumValues must be equal to or greater than 0!"); _error("*generateSineValues: iNumValues must be equal to or greater than 0!");
if (iNumValues == 0) if (iNumValues == 0)
/*
* This would result in an empty array; Won't lead to a fatal error but
* is still invalid; Warn the user.
*/
_warn("*generateSineValues: iNumValues is 0!"); _warn("*generateSineValues: iNumValues is 0!");
// Initialize the output array // Initialize the output array
double *sineArray = NULL; double *sineArray = NULL;
sineArray = (double*) malloc(sizeof(double) * iNumValues); sineArray = (double*) malloc(sizeof(double) * iNumValues);
if (sineArray == NULL) if (sineArray == NULL)
_error("*generateSineValues: Failed to allocate memory for Sine Array\n"); _mem_error("*generateSineValues: Failed to allocate memory for Sine Array");
for (int i=0; i<iNumValues;i++){ for (int i=0; i<iNumValues;i++){
sineArray[i] = dAmp * sin(((2*M_PI)/iNumSamplesPerPeriod) * i); sineArray[i] = dAmp * sin(((2*M_PI)/iNumSamplesPerPeriod) * i);
@ -151,17 +224,36 @@ double *generateSineValues(
return sineArray; return sineArray;
} }
// Returns true if the given szFile is a valid file.
int isValidFile(const char* szFile) {
struct stat statBuffer;
return (stat(szFile, &statBuffer) >= 0 && !(statBuffer.st_mode & S_IFDIR));
}
void writeDoubleArray(double *pdOut, int iLen, char *pcOutName) { void writeDoubleArray(double *pdOut, int iLen, char *pcOutName) {
// Write a list of double values to a file /*
* Write an array of double values to a file with the name `pcOutName`.
* Each value is separated by a linebreak.
*/
// Check if the path is NULL
if (pcOutName == NULL)
_error("writeDoubleArray: pcOutName is NULL");
// Check if the path is a valid file
if (!isValidFile(pcOutName))
_error("writeDoubleArray: '%s' is not a valid file", pcOutName);
FILE *file = fopen(pcOutName, "w"); FILE *file = fopen(pcOutName, "w");
if (file == NULL) if (file == NULL)
_error("writeDoubleArray: Error while opening file '%s'.\n", pcOutName); _error("writeDoubleArray: Error while opening file '%s'.", pcOutName);
if (pdOut == NULL) if (pdOut == NULL)
_error("writeDoubleArray: pdOut is NULL\n"); _error("writeDoubleArray: pdOut is NULL");
if (iLen == 0) if (iLen == 0)
_warn("writeDoubleArray: iLen is 0\n"); _warn("writeDoubleArray: iLen is 0");
for (int i = 0; i < iLen; i++) { for (int i = 0; i < iLen; i++) {
fprintf(file, "%f\n", pdOut[i]); fprintf(file, "%f\n", pdOut[i]);

View File

@ -1,6 +1,6 @@
CC=gcc CC=gcc
SOURCE_FILE=MMS24-25.c SOURCE_FILE=MMS24-25.c
OPTS=-lm -D _DEBUG_ OPTS=-lm
all: clean tests run all: clean tests run