Browse Source

Merge branch 'userinput'

remotes/origin/userinput
TheUltimateOptimist 11 months ago
parent
commit
15fd87b930
  1. 2
      project.yml
  2. 220
      src/userinput.c
  3. 79
      src/userinput.h

2
project.yml

@ -88,7 +88,7 @@
:placement: :end :placement: :end
:flag: "-l${1}" :flag: "-l${1}"
:path_flag: "-L ${1}" :path_flag: "-L ${1}"
:system: [] # for example, you might list 'm' to grab the math library
:system: [m] # for example, you might list 'm' to grab the math library
:test: [] :test: []
:release: [] :release: []

220
src/userinput.c

@ -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);
}

79
src/userinput.h

@ -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
Loading…
Cancel
Save