TheUltimateOptimist
11 months ago
3 changed files with 300 additions and 1 deletions
-
2project.yml
-
220src/userinput.c
-
79src/userinput.h
@ -0,0 +1,220 @@ |
|||
#include "userinput.h" |
|||
|
|||
#include <ctype.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <math.h> |
|||
#include <stdbool.h> |
|||
#include <limits.h> |
|||
#include <float.h> |
|||
|
|||
#define LD(name)\ |
|||
long double name##ldvalue;\ |
|||
long double *name##ld = NULL;\ |
|||
if (name != NULL) {\ |
|||
name##ldvalue = *name;\ |
|||
name##ld = &name##ldvalue;\ |
|||
} |
|||
|
|||
|
|||
void trimLeft(char *input) { |
|||
size_t length = strlen(input); |
|||
int firstIndex = 0; |
|||
while (firstIndex < length && isspace(input[firstIndex])) { |
|||
firstIndex++; |
|||
} |
|||
for (int i = 0; i <= length - firstIndex; i++) { |
|||
input[i] = input[firstIndex + i]; |
|||
} |
|||
} |
|||
|
|||
void trimRight(char *input) { |
|||
size_t length = strlen(input); |
|||
int index = length - 1; |
|||
while (index >= 0 && isspace(input[index])) { |
|||
input[index] = '\0'; |
|||
index--; |
|||
} |
|||
} |
|||
|
|||
char *readInput() { |
|||
size_t bufferSize = 100; |
|||
char *buffer = malloc(bufferSize*sizeof(char)); |
|||
char c; |
|||
int index = 0; |
|||
do { |
|||
c = fgetc(stdin); |
|||
if (!(bufferSize > index)) { |
|||
char *newBuffer = malloc(2*bufferSize*sizeof(char)); |
|||
for (int i = 0; i < bufferSize; i++) { |
|||
newBuffer[i] = buffer[i]; |
|||
} |
|||
bufferSize *= 2; |
|||
} |
|||
buffer[index] = c; |
|||
index++; |
|||
} |
|||
while(c != '\n' && c != EOF); |
|||
buffer[index - 1] = '\0'; |
|||
trimLeft(buffer); |
|||
trimRight(buffer); |
|||
return buffer; |
|||
} |
|||
|
|||
char *gets(char *message, unsigned long *minLength, unsigned long *maxLength) { |
|||
printf("%s", message); |
|||
fflush(stdout); |
|||
char *result = readInput(); |
|||
while (minLength != NULL && strlen(result) < *minLength || maxLength != NULL && strlen(result) > *maxLength) { |
|||
printf("%s", "Ungueltige Eingabe! "); |
|||
if (minLength != NULL && maxLength == NULL) { |
|||
printf("Die Eingabe muss mind. %lu Zeichen lang sein.\n", *minLength); |
|||
} |
|||
else if (maxLength != NULL && minLength == NULL) { |
|||
printf("Die Eingabe darf maximal %lu Zeichen lang sein.\n", *maxLength); |
|||
} |
|||
else { |
|||
printf("Die Eingabe muss %lu bis %lu Zeichen lang sein.\n", *minLength, *maxLength); |
|||
} |
|||
printf("%s", message); |
|||
fflush(stdout); |
|||
result = readInput(); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
void printlf(long double value) { |
|||
if (roundl(value) == value) { |
|||
printf("%.0Lf", value); |
|||
} |
|||
else { |
|||
printf("%Lf", value); |
|||
} |
|||
} |
|||
|
|||
long double getNumber(char *message, long double *min, long double *max, long double *greaterThan, long double *smallerThan, long double leftBorder, long double rightBorder) { |
|||
while (1) { |
|||
char *input = gets(message, NULL, NULL); |
|||
if (strlen(input) == 0) { |
|||
printf("%s\n", "Fehlende Eingabe!"); |
|||
fflush(stdout); |
|||
free(input); |
|||
continue; |
|||
} |
|||
char *endptr; |
|||
long double number = strtold(input, &endptr); |
|||
if (strlen(endptr) > 0) { |
|||
printf("%s\n", "Ungueltige Eingabe! Gib eine gueltige Zahl ein."); |
|||
fflush(stdout); |
|||
free(input); |
|||
continue; |
|||
} |
|||
free(input); |
|||
bool isValid = true; |
|||
if (min != NULL && number < *min) { |
|||
isValid = false; |
|||
} |
|||
if (max != NULL && number > *max) { |
|||
isValid = false; |
|||
} |
|||
if (greaterThan != NULL && !(number > *greaterThan)) { |
|||
isValid = false; |
|||
} |
|||
if (smallerThan != NULL && !(number < *smallerThan)) { |
|||
isValid = false; |
|||
} |
|||
if (number < leftBorder) { |
|||
isValid = false; |
|||
} |
|||
if (number > rightBorder) { |
|||
isValid = false; |
|||
} |
|||
if (isValid) { |
|||
return number; |
|||
} |
|||
printf("Ungueltige Eingabe! Fuer die eingegebene Zahl muss gelten:"); |
|||
if (min != NULL) { |
|||
printf(" >="); |
|||
printlf(*min); |
|||
} |
|||
if (max != NULL) { |
|||
printf(" <="); |
|||
printlf(*max); |
|||
} |
|||
if (greaterThan != NULL) { |
|||
printf(" >"); |
|||
printlf(*greaterThan); |
|||
} |
|||
if (smallerThan != NULL) { |
|||
printf(" <"); |
|||
printlf(*smallerThan); |
|||
} |
|||
if (min == NULL && greaterThan == NULL) { |
|||
printf(" >="); |
|||
printlf(leftBorder); |
|||
} |
|||
if (max == NULL && smallerThan == NULL) { |
|||
printf(" <="); |
|||
printlf(rightBorder); |
|||
} |
|||
printf("\n"); |
|||
fflush(stdout); |
|||
} |
|||
} |
|||
|
|||
short gethd(char *message, short *min, short *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, SHRT_MIN, SHRT_MAX); |
|||
} |
|||
|
|||
int getd(char *message, int *min, int *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, INT_MIN, INT_MAX); |
|||
} |
|||
|
|||
long getld(char *message, long *min, long *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, LONG_MIN, LONG_MAX); |
|||
} |
|||
|
|||
long long getlld(char *message, long long *min, long long *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, LLONG_MIN, LLONG_MAX); |
|||
} |
|||
|
|||
unsigned short gethu(char *message, unsigned short *min, unsigned short *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, 0, USHRT_MAX); |
|||
} |
|||
|
|||
unsigned int getu(char *message, unsigned int *min, unsigned int *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, 0, UINT_MAX); |
|||
} |
|||
|
|||
unsigned long getlu(char *message, unsigned long *min, unsigned long *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, 0, ULONG_MAX); |
|||
} |
|||
|
|||
unsigned long long getllu(char *message, unsigned long long *min, unsigned long long *max) { |
|||
LD(min) |
|||
LD(max) |
|||
return getNumber(message, minld, maxld, NULL, NULL, 0, ULLONG_MAX); |
|||
} |
|||
|
|||
double getlf(char *message, double *min, double *max, double *greaterThan, double *smallerThan) { |
|||
LD(min) |
|||
LD(max) |
|||
LD(greaterThan) |
|||
LD(smallerThan) |
|||
return getNumber(message, minld, maxld, greaterThanld, smallerThanld, -DBL_MAX, DBL_MAX); |
|||
} |
@ -0,0 +1,79 @@ |
|||
#ifndef USERINPUT_H |
|||
#define USERINPUT_H |
|||
|
|||
/// userinput.h provides functions for retrieving user input. |
|||
/// The functions are named get + placeholder used by printf for the given datatype. |
|||
/// string -> gets |
|||
/// short ind -> gethd |
|||
/// int -> getd |
|||
/// long -> getld |
|||
/// long long -> getlld |
|||
/// unsigned short -> gethu |
|||
/// unsigned int -> getu |
|||
/// unsigned long -> getlu |
|||
/// unsigned long long -> getllu |
|||
/// double -> getlf |
|||
/// The provided functions handle validating the user input and ask again for input |
|||
/// with the given message until it is valid. |
|||
|
|||
/// Using the given message gets asks the user to enter a string repeatedly |
|||
/// until its length is between minLength and maxLength (both inclusive). |
|||
/// The obtained string is then returned. |
|||
/// If you don't want to enforce a minLength or a maxLength you can assign it to NULL. |
|||
char *gets(char *message, unsigned long *minLength, unsigned long *maxLength); |
|||
|
|||
/// Using the given message gethd asks the user to enter a short repeatedly |
|||
/// until it is in the valid range for a short and between min and max (both inclusive) if provided. |
|||
/// The obtained short is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
short gethd(char *message, short *min, short *max); |
|||
|
|||
/// Using the given message getd asks the user to enter an int repeatedly |
|||
/// until it is in the valid range for an int and between min and max (both inclusive) if provided. |
|||
/// The obtained int is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
int getd(char *message, int *min, int *max); |
|||
|
|||
/// Using the given message getld asks the user to enter a long repeatedly |
|||
/// until it is in the valid range for a long and between min and max (both inclusive) if provided. |
|||
/// The obtained long is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
long getld(char *message, long *min, long *max); |
|||
|
|||
/// Using the given message getlld asks the user to enter a long long repeatedly |
|||
/// until it is in the valid range for a long long and between min and max (both inclusive) if provided. |
|||
/// The obtained long is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
long long getlld(char *message, long long *min, long long *max); |
|||
|
|||
/// Using the given message gethu asks the user to enter an unsigned short repeatedly |
|||
/// until it is in the valid range for an unsigned short and between min and max (both inclusive) if provided. |
|||
/// The obtained unsigned short is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
unsigned short gethu(char *message, unsigned short *min, unsigned short *max); |
|||
|
|||
/// Using the given message getu asks the user to enter an unsigned int repeatedly |
|||
/// until it is in the valid range for an unsigned int and between min and max (both inclusive) if provided. |
|||
/// The obtained unsigned int is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
unsigned int getu(char *message, unsigned int *min, unsigned int *max); |
|||
|
|||
/// Using the given message getlu asks the user to enter an unsigned long repeatedly |
|||
/// until it is in the valid range for an unsigned long and between min and max (both inclusive) if provided. |
|||
/// The obtained unsigned long is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
unsigned long getlu(char *message, unsigned long *min, unsigned long *max); |
|||
|
|||
/// Using the given message getllu asks the user to enter an unsigned long long repeatedly |
|||
/// until it is in the valid range for an unsigned long long and between min and max (both inclusive) if provided. |
|||
/// The obtained unsigned long long is then returned. |
|||
/// If you don't want to enforce a min or max you can assign it to NULL. |
|||
unsigned long long getllu(char *message, unsigned long long *min, unsigned long long *max); |
|||
|
|||
/// Using the given message getlf asks the user to enter a double repeatedly |
|||
/// until it is in the valid range for a double, between min and max (both inclusive), |
|||
/// greater than the given greaterThan and smaller than the given smallerThan. |
|||
/// The obtained double is then returned. |
|||
/// If you don't want to enforce a min, max, greaterThan or smallerThan you can assign them to NULL. |
|||
double getlf(char *message, double *min, double *max, double *greaterThan, double *smallerThan); |
|||
#endif |
Write
Preview
Loading…
Cancel
Save
Reference in new issue