Home > Software design >  the program, receiving an integer (as a string), after converting the data type perceives it as a st
the program, receiving an integer (as a string), after converting the data type perceives it as a st

Time:09-08

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 - consider value < 0 always reports as "The input is an integer\n".

  • (int)temp is UB when temp far out of int 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) ;     
}
  • Related