I have implemented a C library to perform basic input operations on built-in data types with various error checks of more complexity. Any improvements or suggestions are appreciated.
smartinput.h
/*
* This library 'smartinput' is written in c programming.
* by @venudayyam (binary_10)
*
* The library contains subroutines which perform basic input
* operations on a built-in data types and provide robust
* error checking.
*
* It is recommend not to mix the stadard input functions with these
* library functions when performing operations on standard input stream
*
* routines are meant to be used only when input stream is connected to keyboard.
* routines expect valid arguments to be passed (if any).
*
*
*
*
* PROS:
*
* - data overflow and underflow check on input
*
* - input buffer is flushed(empty) after each operation.
*
* - input value is said to be valid only when
* it can be stored in the specified variable (data type) `as it is`.
* otherwise it is invalid.
*
*/
#ifndef SMARTINPUT_H
#define SMARTINPUT_H
#include <stdbool.h>
bool get_char(char *ch);
char* get_line(char *_s, int _len);
/* trailing white spaces are preserved */
char* get_string(char *_s, int _len);
bool get_short(short *value);
bool get_ushort(unsigned short *value);
bool get_int(int *value);
bool get_uint(unsigned int *value);
bool get_long(long *value);
bool get_ulong(unsigned long *value);
bool get_ullong(unsigned long long *value);
bool get_llong(long long *value);
bool get_float(float *value);
bool get_double(double *value);
bool get_ldouble(long double *value);
#endif
smartinput.c
/*
* This library 'smartinput' is written in c programming.
* by @venudayyam (binary_10)
*
* The library contains subroutines to perform basic input
* operations on a built-in data types and provide robust
* error checking.
*
* It is recommend not to mix the stadard input functions with these
* library functions when performing operations on standard input stream
*
* routines are meant to be used only when input stream is connected to keyboard.
* routines expect valid arguments to be passed (if any).
*
*
*
*
* PROS:
*
* - data overflow and underflow check on input
*
* - input buffer is flushed(empty) after each operation.
*
* - input value is said to be valid only when
* it can be stored in the specified variable (data type) `as it is`.
* otherwise it is invalid.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include "smartinput.h"
#define BUF_SIZE (1024)
static char buffer[BUF_SIZE];
char* get_line(char *_s, int _len)
{
int ch;
size_t i = 0;
scanf(" ");
while ((ch=getc(stdin)) != EOF && ch != '\n')
{
if (i < _len-1)
_s[i++] = ch;
}
_s[i] = '\0';
return _s;
}
char* get_string(char *_s, int _len)
{
int ch;
size_t i = 0;
while ((ch=getc(stdin)) != EOF && ch != '\n')
{
if (i < _len-1)
_s[i++] = ch;
}
_s[i] = '\0';
return _s;
}
bool get_char(char *value)
{
fgets(buffer,3,stdin);
*value = buffer[0];
if ((buffer[1] == '\0' && buffer[0] == '\n') ||
(buffer[2] == '\0' && buffer[1] == '\n'))
{
return true;
}
else
{
if (buffer[0] != '\0')
{
scanf("%*[^\n]");
getchar();
}
return false;
}
}
bool get_short(short *value)
{
char *temp;
long v;
get_line(buffer, BUF_SIZE);
errno = 0;
v = strtol(buffer,&temp,10);
*value = v;
if (errno == ERANGE || v > SHRT_MAX || v < SHRT_MIN
|| *temp != '\0')
return false;
else
return true;
}
bool get_ushort(unsigned short *value)
{
char *temp;
unsigned long v;
get_line(buffer, BUF_SIZE);
errno = 0;
v = strtoul(buffer,&temp,10);
*value = v;
if (errno == ERANGE || v > USHRT_MAX || *temp != '\0')
return false;
else
return true;
}
bool get_int(int *value)
{
char *temp;
long v;
get_line(buffer, BUF_SIZE);
errno = 0;
v = strtol(buffer,&temp,10);
*value = v;
if (errno == ERANGE || v > INT_MAX || v < INT_MIN
|| *temp != '\0')
return false;
else
return true;
}
bool get_uint(unsigned int *value)
{
char *temp;
unsigned long v;
get_line(buffer, BUF_SIZE);
errno = 0;
v = strtoul(buffer,&temp,10);
*value = v;
if (errno == ERANGE || v > UINT_MAX || *temp != '\0')
return false;
else
return true;
}
bool get_long(long *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtol(buffer,&temp,10);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
bool get_ulong(unsigned long *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtoul(buffer,&temp,10);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
bool get_llong(long long *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtoll(buffer,&temp,10);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
bool get_ullong(unsigned long long *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtoull(buffer,&temp,10);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
bool get_float(float *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtof(buffer,&temp);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
bool get_double(double *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtod(buffer,&temp);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
bool get_ldouble(long double *value)
{
char *temp;
get_line(buffer, BUF_SIZE);
errno = 0;
*value = strtold(buffer,&temp);
if (errno == ERANGE || *temp != '\0')
return false;
else
return true;
}
sample.c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "smartinput.h"
#define MAX_NAME 256
typedef struct _record
{
char name[MAX_NAME];
size_t id;
char section;
}record;
void get_record(record *r)
{
printf("name : ");
while (!get_line(r->name,MAX_NAME))
fprintf(stderr,"error: invalid name. try again..\n");
printf("section : ");
while (!(get_char(&r->section) && r->section >= 'A'
&& r->section <= 'E'))
fprintf(stderr,"error: invalid section. (select 'A'-'E'). try again..\n");
printf("id : ");
while (!get_ulong(&r->id))
fprintf(stderr,"error: invalid id. try again..\n");
}
int main(void)
{
record r;
get_record(&r);
printf("name : %s\nsec : %c\nid : %lu",r.name,r.section,r.id);
}
.
/* sample inputs and outputs of `get_int()` (note. sizeof(int) = 4) */
"2147483647\n" -- true (INT_MAX)
"2147483648\n" -- false
"-2147483648\n" -- true (INT_MIN)
"-2147483649\n" -- false
"25ds\n" -- false
"asdjkljasdf\n" -- false
"25 256\n" -- false
"+1\n" -- true
"-1\n" -- true
EOF -- false
" 1\n" -- true
"123\n"
," 123\n"
,"123 x\n"
,"\n123\n"
. \$\endgroup\$