File Path checking and more comments
This commit is contained in:
parent
f1783f7ce8
commit
e84e1d5100
126
MMS24-25.c
126
MMS24-25.c
@ -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]);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user