The program receives the data, but treats the string ("20x") as an integer.(This is not my code, I found it on the internet.)
// C program to find data type
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
# define MAX_INPUT 100
int main()
{
// To read input
char value[MAX_INPUT] = "";
// To store numeric value of input if a
// number (float or integer)
double temp;
// To store integral value of input
int n;
// To store string value of input
char str[MAX_INPUT] = "";
// Precision for integer checking
double val = 1e-12;
fgets(value, 100, stdin); // Read input
// Check for integers.
if (sscanf(value, "%lf", &temp) == 1)
{
n = (int)temp; // typecast to int.
if (fabs(temp - n) / temp > val)
printf("The input is a floating point\n");
else
printf("The input is an integer\n");
}
// Check for string
else if (sscanf(value, "%s", str) == 1)
printf("The input is a string\n");
else // No match.
printf("input not recognized\n");
}
So, If we enter "20x" for example, we will get a message "The input is an integer". I tried changing datatypes and array values, but it still didn't work as it should. Maybe it's a bug of this language. Thank you.
CodePudding user response:
OP's code fails to check for trailing non-numeric text.
Further, the
fabs(temp - n) / temp > val
is at best - dodgy. At worst, it is worthless - considervalue < 0
always reports as"The input is an integer\n"
.(int)temp
is UB whentemp
far out ofint
range.A robust test of a string for a valid
int
does not need a floating point test.
To check if the input string is a integer, directly use strtol()
instead of sscanf()
. It is more tightly defined.
char *endptr;
errno = 0;
long lval = strtol(value, &endptr, 0);
// If no conversion or out of range.
if (endptr == value || errno == ERANGE) {
printf("The input is not an `long`\n");
} else {
// Tolerated trailing white-space.
while (isspace(*(unsigned char *)endptr)) {
endptr ;
}
// If junk at the end or out of int range.
if (*endptr != 0 || lval < INT_MIN || lval > INT_MAX) {
printf("The input is not an `int`\n");
} else {
printf("The input is an int\n");
}
}
Or not quite as robust, use "%n"
to record scanning offset. It does not certainly detect overflow (UB).
int n = 0;
int val;
// v---- Optional spaces
// | v-- Scanning offset
sscanf(value, "%d %n", &val, &n);
if (n && value[n] == 0) {
puts("Success");
} else {
puts("Fail");
}
CodePudding user response:
The key of this program is sscanf()
and what the function returns. The sscanf()
function returns the number of fields that were successfully converted and assigned. The return value does not include fields that were read but not assigned.
The return value is EOF when the end of the string is encountered before anything is converted. source
The program first checks if there are any double or integer values on the string. Then it checks for non-numeric character strings. So if the input is "20X" or any "1234abcd" the temp value is successfully assigned as 20(for 20X input) or 1234 (for 1234abcd input). So the final verdict is an integer.
Hope this code will help in your purpose to find the datatype of input.
// C program to find data type
#include <stdio.h>
#include <string.h>
# define MAX_INPUT 100
void check_type(char strIn[]){
int dotFlag = 0 ;
int dotPos = 0 ;
int firstSignCheck = 1 ;
int len = strlen(strIn) ;
//checking for string and counting '.'
for (int i = 0 ; i < len ; i ) {
if((strIn[i] == ' ' || strIn[i] == '-') && firstSignCheck == 1 ) //skipping first ' ' and '-'
continue ;
else
firstSignCheck = 0 ;
if((strIn[i] < '0' || strIn[i] > '9') && strIn[i] != '.') { //if any character out of 0-9 and '.' it is string
printf("The input is string") ;
return ;
}
if(strIn[i] == '.'){ //counting dots and keeping the position
dotFlag ;
dotPos = i ;
}
}
if(firstSignCheck == 1) { // if all are ' ' or '-'
printf("The input is string") ;
return ;
}
if(dotFlag > 1) { //if several '.' its a string
printf("The input is string") ;
return ;
}
else if(dotFlag == 0 ) { // no '.' integer
printf("The input is integer") ;
return ;
}
else{
for (int i = dotPos 1 ; i < len ; i ) { // after '.' checkin for zeros
if(strIn[i] != '0') { // any nonzeros float
printf("%c" ,strIn[i] ) ;
printf("The input is float/double") ;
return ;
}
}
printf("The input is integer") ; // no non zero ineger
return ;
}
}
int main()
{
// To read input
char value[MAX_INPUT] = "";
// To store string value of input
char str[MAX_INPUT] = "";
//input string
scanf("%s" , value) ;
//checking datatype
check_type(value) ;
}