debugcMinor
C library for standard input operations with data validation and error check
Viewed 0 times
erroroperationswithvalidationstandardinputforlibraryandcheck
Problem
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.
GitHub
smartinput.h
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
GitHub
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
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);
#endifsmartinput.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
Solution
Overall, a worth goal and a good coding attempt, yet many problems.
-
Questionable functionality in
-
Questionable functionality in
-
Use of
-
Mis-leading comment
-
There is no function to get a line that includes the potential
A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. C11 7.21.2 1
-
With
-
Not a fan of using a global
-
Integer conversion problems. 1) return value of
-
The get FP routines also fail to detect no conversion. Those FP routines have a special implementation defined (ID) behavior concerning underflow not handled by OP's code. Noted as follows:
If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whether
-
Questionable test code. As
-
Design asymmetry. The get line/string return the value on the others return a
-
Minor:
-
Pedantic:
-
Questionable functionality in
get_line() and get_string(). On EOF, both return a pointer to the supplied char array so the calling code lacks EOF distinguishably. Functions are certainly a problem should a rare input error occur.-
Questionable functionality in
get_line() as it can get more that 1 line with scanf(" "). I'd expect the function to get 1 line of input only.char* get_line(char *_s, int _len) {
....
scanf(" ");-
Use of
int for buffer size when size_t is the right-size for array sizes. //char* get_line(char *_s, int _len);
//char* get_string(char *_s, int _len);
char* get_line(char *_s, size_t _len);
char* get_string(char *_s, size_t _len);-
Mis-leading comment
/ trailing white spaces are preserved /. For both get_line() and char* get_string(), the trailing white spaces (aside from '\n') are preserved.-
There is no function to get a line that includes the potential
'\n'. C library defines a line as including that.A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. C11 7.21.2 1
-
With
smartinput.c, put #include "smartinput.h" first as that will help detect any missing #include that are needed in smartinput.h.#include "smartinput.h"
#include
#include
...-
Not a fan of using a global
char buffer[] especially where a short local array would do.-
Integer conversion problems. 1) return value of
get_line() is not checked - not that it helps much given the above no EOF detect issue. Without detecting EOF, conversion may use the previous contents of global buffer, 2) "No conversion" is not detected. 3) On conversion outside short range, errno is not set. and the value is set to the end of the short range. Similar troubles with all integer conversion functions. Alternative-
The get FP routines also fail to detect no conversion. Those FP routines have a special implementation defined (ID) behavior concerning underflow not handled by OP's code. Noted as follows:
If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whether
errno acquires the value ERANGE is implementation-defined. §7.22.1.3 10-
Questionable test code. As
get_line(s,...) always return s, the following will only print if r->name == NULLwhile (!get_line(r->name,MAX_NAME))
fprintf(stderr,"error: invalid name. try again..\n");-
Design asymmetry. The get line/string return the value on the others return a
bool flag indicating success. I'd expect all to return bool.-
Minor:
() not needed with #define BUF_SIZE (1024)-
Pedantic:
char get_line(char _s, int _len) writes before _s if _len
Alternative get_line()`, something like:char *get_line(char * s, size_t n) {
if (n == 0) {
return NULL; // or TBD on how to handle pathological case.
}
n--;
int ch;
size_t i = 0;
while (i < n && (ch = fgetc(stdin)) != EOF) {
s[i++] = (char) ch;
if (ch == '\n') break;
}
s[i] = '\0';
// Consume rest of line
while (ch != '\n' && ch != EOF) {
ch = fgetc(stdin);
}
if (ch == EOF) {
if (i == 0 || ferror(stdin)) {
return NULL;
}
}
return s;
}Code Snippets
char* get_line(char *_s, int _len) {
....
scanf(" ");//char* get_line(char *_s, int _len);
//char* get_string(char *_s, int _len);
char* get_line(char *_s, size_t _len);
char* get_string(char *_s, size_t _len);#include "smartinput.h"
#include <stdio.h>
#include <string.h>
...while (!get_line(r->name,MAX_NAME))
fprintf(stderr,"error: invalid name. try again..\n");char *get_line(char * s, size_t n) {
if (n == 0) {
return NULL; // or TBD on how to handle pathological case.
}
n--;
int ch;
size_t i = 0;
while (i < n && (ch = fgetc(stdin)) != EOF) {
s[i++] = (char) ch;
if (ch == '\n') break;
}
s[i] = '\0';
// Consume rest of line
while (ch != '\n' && ch != EOF) {
ch = fgetc(stdin);
}
if (ch == EOF) {
if (i == 0 || ferror(stdin)) {
return NULL;
}
}
return s;
}Context
StackExchange Code Review Q#162349, answer score: 6
Revisions (0)
No revisions yet.