austin
austin

Reputation: 101

Trying to determine if a string contains a period

I'm trying to determine if a string contains a certain symbol, specifically a period. I'm using this to determine if a number is a real number or an integer. The first condition is that the string has to contain a number between 0 and 9 to be considered a number, then if it has a period (decimal) it will be considered a real number. If no period, then it is an integer. I can't figure out what I'm doing wrong, thanks in advance!

void typenumber(char *str)
{
  int i=0;

  if(str[i]>='0' && str[i]<='9')
  {
    if(str[i]=='.')
    {    
       printf("String %s is a real number.\n", str);
    }
    else
    {
        printf("String %s is an integer.\n", str);
    }
  }
  return;
}

Upvotes: 4

Views: 4015

Answers (5)

chux
chux

Reputation: 153547

Below is wrong because if str[i]>='0' && str[i]<='9' is true, then str[i] must be a digit and therefore never a '.'

if(str[i]>='0' && str[i]<='9') {
  if(str[i]=='.')

I'm using this to determine if a number is a real number or an integer.

This appears to be the true issue and not "Trying to determine if a string contains a period". Example: "123e4" lacks a '.', yet is usually considered a "real".

A string may successfully be interpreted as an "integer", as "real" , as both or neither. Consider forming 2 independent tests and assess each separately.

C has Standard C library functions strto...() just for this purpose. Best to use the sharpest tools in the shed.

#include <stdlib.h>

bool is_integer(const char *s) {
  char *endptr;
  long long ll = strtoll(s, &endptr, 0);
  if (s == endptr) return false;  // no conversion;
  if (*endptr) return false;  // extra junk, maybe a `.`?
  // maybe add tests for overflow
  return true;
}

bool is_real(const char *s) {
  char *endptr;
  double d = strtod(s, &endptr);
  if (s == endptr) return false;  // no conversion;
  if (*endptr) return false;  // extra junk, maybe an `x`?
  // maybe add tests for overflow
  return true;
}

void classify(const char *s) {
  bool i = is_integer(s);
  bool r = is_real(s);
  if (i) {
    if (r) puts("Both");
    else puts("Integer");
  } else {
    if (r) puts("Real");
    else puts("Neither");
  }
}

When the string is "Both" and the integer conversion does not overflow, "integer" could be favored over "Real". Yet if "Both" occurs with input like "1234567890123456789012345678901234567890", perhaps better to use as a "real" since typically no integer type is wide enough.

Upvotes: 0

H.S.
H.S.

Reputation: 12679

I'm trying to determine if a string contains a certain symbol, specifically a period.

This you can check using strchr(), like this:

if (strchr(str, '.') != NULL) {
   printf("String %s is a real number.\n", str);
}
else {
    printf("String %s is an integer.\n", str);
}

But there is a possibility that your input string may contain multiple '.' character or a character other than digits and period character. So, it is better to loop through the each and every character of the input string and check it, like this:

#define INT_NUM  1
#define REAL_NUM 2

int typenumber(char *str) {
        int num_type = INT_NUM;

        if ((str == NULL) || (*str == '\0')) {
                printf ("Invalid input\n");
                return 0;
        }

        while (*str != '\0') {
                if (!isdigit(*str)) {
                        if ((*str == '.') && (num_type == INT_NUM)) {
                                num_type = REAL_NUM;
                        } else {
                                return -1;
                        }
                }
                str++;
        }

        return num_type;
}

Upvotes: 3

H&#233;ctor M.
H&#233;ctor M.

Reputation: 2392

The problem here is that you are not traveling the chain

int typeNumber(char *str)
{
    if(isNumericDecimal(str))
    {
        if (strchr(str, '.') != NULL) return 1; //Prime, string contain dot
        else return 0; //Integer, string does not contains dot
    }
    else return - 1; //Letter or simbol
}

int isNumericDecimal (const char * s)
{
    if (s == NULL || *s == '\0' || isspace(*s))
      return 0;
    char * p;
    strtod (s, &p);
    return *p == '\0';
}

void typenumber(char *str)
{
    if(typeNumber(str) == 1)
    {    
       printf("String %s is a real number.\n", str);
    }
    if(typeNumber(str) == -1)
    {
        printf("String %s is not a numeric value", str);
    }
    if(typeNumber(str) == 0)
    {
        printf("String %s is an integer.\n", str);
    }
  return;
}

Upvotes: 0

James McPherson
James McPherson

Reputation: 2576

You appear to be hand-rolling an implementation of strtol(), which will efficiently convert a string to a long.

If you really must check through the string elements yourself, then using isdigit() would be a good idea.

Upvotes: 2

Lee Gaines
Lee Gaines

Reputation: 514

There's no loop!

i will always be 0, so you're only checking the first character or str.

Upvotes: 0

Related Questions