Jump to content
Sign in to follow this  
benners

Numbers check in C

Recommended Posts

benners

I am trying to add some error checking in a small program for uni. I have done the program which is just entering a series of number and calculating the average but I also want to add error funtions to check for non mumeric characters.

I have found the isDigit() function but that only checks for 0 - 9, I don't think it would work if 22 or 22.6 was inputted. I am new to C and was wondering if there was anything like isNumber in AutoIt.

Thanks

Share this post


Link to post
Share on other sites
Richard Robertson

Write your own.

Just enumerate all characters and check to see if it's 0-9 or '.'.

bool IsNumber(char *text)
{
    for (int i = 0; text[i] != 0; i++)
    {
        if (!(('0' <= text[i] && text[i] <= '9') || text[i] == '.'))
            return false;
    }
    return true;
}

Edit: Just to make it clear, this code expects a null terminated string.

Edited by Richard Robertson

Share this post


Link to post
Share on other sites
Valik

That code is needlessly confusing:

  • You've flipped the lvalue and rvalue in one of the tests making it inconsistent.
  • There are two <= tests (due to the flipped values) which is just horribly confusing.
  • For some reason the code negates the tests instead of just using the correct operators to start with.
This is a hell of a lot easier to follow:

bool IsNumber(char *text)
{
    for (int i = 0; text[i] != 0; i++)
    {
         if ((text[i] < '0' || text[i] > '9') && text[i] != '.'))
             return false;
     }
     return true;
}
Edited by Valik

Share this post


Link to post
Share on other sites
Richard Robertson

Yeah my bad. I've had a long day and I apparently shouldn't be coding right now.

Share this post


Link to post
Share on other sites
wraithdu

While you're at it, should probably add a buffer length parameter in there to be safe and avoid possible buffer overruns from bad input strings.

If the OP wants to take it a step further, he should also test for only one occurrance of a '.', an allowance for scientific notation (2.53E4), and '-' for negative numbers and exponents.

Share this post


Link to post
Share on other sites
benners

Thanks all for the responses and suggestions. I have finished the other questions I had and will play around with the answers you have all provided. :)

Share this post


Link to post
Share on other sites
Authenticity

Still, you need a boolean variable to see if it's not something lime 1.1.2 as wraithdu pointed:

#include <iostream>
using namespace std;

bool IsNumber(char*);

int main()
{
    char num[] = "123456789", anum[] = "12345.00lk";

    cout << "num is ";
    if (IsNumber(num))
        cout << "a number\n";
    else    
        cout << "not a number\n";

    cout << "anum is ";
    if (IsNumber(anum))
        cout << "a number\n";
    else
        cout << "not a number\n";

    return 0;
}

bool IsNumber(char *text)
{
    char *lpstr = text-1;
    
    while (*++lpstr)
         if ((*lpstr > '9' || *lpstr < '0') && *lpstr != '.')
             return false;
     return true;
}
Edited by Authenticity

Share this post


Link to post
Share on other sites
Nutster

There are other ways to do this, without catching a few false positives, like "10.10.42.22". One way is to use sscanf. Keep in mind that bool and cout are part of C++, not C.

#include <stdio.h>

int IsNumber(const char *text) {
    double result;
    char c = '\0';

    /* returns true (1) if there is only one value read (the float). */
    /* returns false (0) if nothing valid was read or if a character followed the floating point value. */
    if (sscanf(text, "%lf%c", &result, &c)==1) {
        return 1;
    }
    else if (c == '\0') {
        /* if c has only a null character, then the string did actually end in the correct spot. */
        return 1;
    }
    else {
        return 0;
    }
}

Another way is to create an interpreter function to read the input string and rejects if the string is not ended by the time the number is finished. I have not included the parts that actually determine the value, just valid syntax.

#include <assert.h>
#include <ctype.h>

int IsNumber(const char *text) {
    char *ptr=text;   /* a pointer to keep track of where in the string we are looking */
    
    /* check for a sign */
    if (*ptr == '-' || *ptr == '+') {
        ++ptr;
    }
    /* Read the part in front (whole number) portion of the string;
    while (isdigit(*ptr)) {
        ++ptr;
    }
    if (*ptr == '.') {
        /* found the decimal point.  Move on to the next part */
        ++ptr;
    }
    /* other characters will actually get trapped later. */
    /* read the decimal (fractional) portion */
    while (isdigit(*ptr)) {
        ++ptr;
    }
    /* String should end, or may be followed by exponent portion, the E-42 part. */
    if (*ptr == '\0') {
        /* end of string.  Valid exit point. */
        return 1;
    }
    else if (toupper(*ptr) != 'E') {
        /* nothing else is valid.  Return false. */
        return 0;
    }
    /* Exponent portion */
    assert(*ptr == 'e' || *ptr == 'E');
    ++ptr;
    if (*ptr == '-' || *ptr == '+') {
        ++ptr;
    }
    while (isdigit(*ptr)) {
        ++ptr;
    }
    /* This has to be the end of the string. */
    if (*ptr == '\0') {
        /* end of string.  Valid exit point. */
        return 1;
    }
    else {
        return 0;
    }
}

David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.