Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / C++
Article

Validating numbers

Rate me:
Please Sign up or sign in to vote.
1.00/5 (7 votes)
18 Sep 2006CPOL2 min read 22.5K   252   11  
Code sample demonstrating the validation of numbers in C++.

Sample Image

Introduction

This code validates positive numbers. Although I am a novice in C++, I have not yet come across a basic and robust function in C++ that validates numbers. Some functions fail when the input starts with a number and is followed by a character. This code will be very useful to beginners, and maybe gurus as well! You will require the iostream.h and math.h files in your project. As shown in the screenshot above, the function keeps on prompting you for a number until you enter a valid integer.

Background

This function works by manipulating the ASCII code representation of any character typed on the keyboard. First, we filter out the input. We only collect digits, spaces, and points (.).

//
while ( ( character_entered = cin.get() ) != '\n' )
{
  character_in_ascii_code[total_characters_entered] = 
            character_entered; //store every character in array
  total_characters_entered++;
  if (((character_entered < 32) || (total_characters_entered > 57))|| 
      ((total_characters_entered > 32) && 
       (total_characters_entered < 46)) || 
       (total_characters_entered == 47))
     IvalidCharEntered=true;
  if  (IvalidCharEntered==true)
  {
    // ensure that while loop condition is maitained
    get_characters=true;
    // loop again -->> while (get_characters)
    continue;
  }
  else
    get_characters=false;
} // end while ( ( character_entered = cin.get() ) != '\n' )

Then, we remove the leading and trailing spaces.

//
// remove leading & training spaces in array -
// int_counter may change, elements relocated
space_start_point = 0;
space_end_point = total_characters_entered-1;
// remove leading spaces
for (CharCounter = 0; CharCounter < 
     total_characters_entered; CharCounter++)
  temp_character_in_ascii_code[CharCounter] = 
       character_in_ascii_code[CharCounter];
  for (CharCounter = 0; CharCounter < 
      total_characters_entered; CharCounter++)
  {
    if (temp_character_in_ascii_code[CharCounter] == 32) 
      space_start_point = CharCounter + 1;
    else
      break;
  } 

//remove training spaces
for ((CharCounter = (total_characters_entered-1)); 
      CharCounter != 0; CharCounter--)
{
  if (temp_character_in_ascii_code[CharCounter] == 32) 
    space_end_point = CharCounter - 1;
  else
    break;
}

//

Now, we work on the resulting array of elements to check for spaces captured within digits or points. If the array has spaces within, then it is not a valid number.

//
// check if spaces  were entered between digits
for (CharCounter=space_start_point; CharCounter < 
    (space_end_point + 1); CharCounter++)
 if (character_in_ascii_code[CharCounter] == 32) 
 {
   space_within_digits = true;
   get_number_status=-1;
 }
//

If there are no spaces, then we check for the number of points. If there are more than one, then it's not a valid number. We discard it.

if (numer_of_points > 1)
  // error : number  cannot have
  // more than one decimal points
  get_number_status=-1;
else // convert array elements into number
 ....

If it is valid, then do the following:

  1. If there is a decimal point, then work on digits on the left of the point. Convert them to a number. Likewise on the digits on the right.
    //....
    
    //
    else // convert array elements into number
    {
    if (numer_of_points  == 1) {
      if (point_index  < 0) // number started with digit e.g. 8.5 {
      // process integer part first
        for (CharCounter  = 0; CharCounter < point_index ; CharCounter++) {
          for (DigitCounter = 0; DigitCounter < 
               ascii_character_table_columns; DigitCounter++) {
            if (character_in_ascii_code[CharCounter] == 
                ascii_character_table[0][DigitCounter])
          integer_part  += ((pow(10,(point_index - CharCounter)))*
                            (ascii_character_table[1][DigitCounter]))/ 10;
          } 
        } 
       
    
    // then process fraction part
     if ((point_index + 1) == total_characters_entered)
         fraction_part=0.00; // basically do nothing!
       else {  // we have some digits following the point
         for (CharCounter = (point_index + 1); CharCounter < 
              total_characters_entered ; CharCounter++) {
            for (DigitCounter=0; DigitCounter < 
                 ascii_character_table_columns; DigitCounter++) {
               if (character_in_ascii_code[CharCounter] == 
                   ascii_character_table[0][DigitCounter])
               fraction_part += ((pow(10,(point_index - CharCounter)))*
                                 (ascii_character_table[1][DigitCounter]));
            } 
         } 
       } 
     }
    
     if (point_index == 0) { //working on a number like .5 etc
        for (CharCounter = (point_index + 1); CharCounter  <  
             total_characters_entered ; CharCounter++) {
           for (DigitCounter=0; DigitCounter < 
                ascii_character_table_columns; DigitCounter++) {
             if (character_in_ascii_code[CharCounter] == 
                 ascii_character_table[0][DigitCounter])
                fraction_part += ((pow(10,(point_index - CharCounter)))*
                                  (ascii_character_table[1][DigitCounter]));
           } 
        } 
      }
    }
    
    //
  2. If there are no points, then convert the array into a number using the following code:
    if (numer_of_points == 0)
    // number without decimals{
       for (CharCounter=0; CharCounter < 
            total_characters_entered; CharCounter++){
           for (DigitCounter=0; DigitCounter < 
                ascii_character_table_columns; DigitCounter++){
               if (character_in_ascii_code[CharCounter] == 
                   ascii_character_table[0][DigitCounter]){
                   integer_part += 
                     ((pow(10,(total_characters_entered-CharCounter)))*
                      (ascii_character_table[1][DigitCounter]))/ 10;
               }
           } 
       }
    
    ......
  3. Finally, check the range.

Using the code

Below is the complete source code. I will appreciate if guys out there have or can come up with a short and less involving method to achieve the same for console applications (in C++).

//**************************************
// Name: Number Validation
// By:   Edward Z. Lubaini
//**************************************
#include  <iostream.h>
#include  <math.h>

double get_number(char prompt_variable[], 
       double number_lower_bound, 
       double number_upper_bound);

int main()
{
    double my_number;
    double my_min = 0;
    double my_max = 200;
    char my_prompt[20] = "Enter a number :  ";
    my_number = get_number(my_prompt, my_min, my_max);
    cout << "Your number is: " << my_number << "\n";
    return 0;
};

// general purpose function to get positive numers only. 
double get_number(char prompt_variable[], 
       double number_lower_bound = 0, 
       double number_upper_bound = 100)
{
    const int ascii_character_table_rows=2;
    const int ascii_character_table_columns=10;
    const int ascii_character_table[ascii_character_table_rows]
              [ascii_character_table_columns]=
              {{48,49,50,51,52,53,54,55,56,57},
               {0,1,2,3,4,5,6,7,8,9}};
    // use int, because char cannot represent EOF
    int character_entered;
    const int max_chars_allowed=21;
    int character_in_ascii_code[max_chars_allowed] = {0};
    // initialize first element to ZERO and C++
    // will complete the rest with ZERO values
    int temp_character_in_ascii_code[max_chars_allowed] = {0};
    //variable for tracking character position
    int CharCounter;
    //variable for tracking character position
    int temp_CharCounter;
    //variable holding total number of characters entered
    int total_characters_entered=0;
    //variable for tracking digit position
    int DigitCounter;
    //variable indicating number of decimal points (.) entered
    int numer_of_points;
    int point_index;
    int space_start_point=0;
    int space_end_point=0;
    double get_number_status=0;
    double validated_number = 0;
    double integer_part=0;
    double fraction_part=0;
    bool get_characters=true;
    bool IvalidCharEntered;
    bool input_not_accepted=true;
    bool space_within_digits=false;

    while (input_not_accepted)
    // loop to ensure number entered is valid & within range
    {
        while (get_characters)
        // loop to get number(s), point(s), & space(s) only
        {
            cout << prompt_variable; // 
            total_characters_entered = 0;
            get_number_status = 0; //NNN
            validated_number = 0;
            integer_part = 0;
            fraction_part = 0.00;
            IvalidCharEntered=false;
            space_within_digits=false;
            numer_of_points = 0;
            while ( ( character_entered = cin.get() ) != '\n' )
            {
                // store every character in array
                character_in_ascii_code[total_characters_entered]=
                                                character_entered;
                total_characters_entered++;
                if (((character_entered < 32) || 
                     (character_entered > 57))|| 
                    ((character_entered > 32) && 
                     (character_entered < 46)) || 
                     (character_entered == 47))
                    IvalidCharEntered=true;    
                if (IvalidCharEntered==true)
                {
                    // ensure that while loop condition is maitained
                    get_characters=true;
                    continue;
                    // loop again -->> while (get_characters)
                }
                else
                    get_characters=false;
            }    // end while ( ( character_entered
                // = cin.get() ) != '\n' )

        }    // end while (get_characters)
        // loop to get number(s), point(s), & space(s) only

        if (total_characters_entered > max_chars_allowed)
            get_number_status=-1;
        else    
        {
        // remove leading & training spaces in array - 
        //   int_counter may change, elements relocated
            space_start_point = 0;
            space_end_point = total_characters_entered-1;
            for (CharCounter = 0; CharCounter < 
                    total_characters_entered; CharCounter++)
                temp_character_in_ascii_code[CharCounter] = 
                     character_in_ascii_code[CharCounter];
            for (CharCounter = 0; CharCounter < 
                 total_characters_entered; CharCounter++)
            {
                if (temp_character_in_ascii_code[CharCounter] == 32) 
                    space_start_point = CharCounter + 1;
                else
                    break;
            } //end for (CharCounter=0; 
              //         CharCounter<total_characters_entered;
              //         CharCounter++)
            for ((CharCounter = (total_characters_entered-1)); 
                  CharCounter != 0; CharCounter--)
            {
                if (temp_character_in_ascii_code[CharCounter] == 32) 
                    space_end_point = CharCounter - 1;
                else
                    break;
            } //end for (CharCounter=0; 
              //         CharCounter<total_characters_entered;
              //         CharCounter++)
            // check if spaces  were entered between digits
            for (CharCounter=space_start_point; CharCounter < 
                            (space_end_point + 1); CharCounter++)
                if (character_in_ascii_code[CharCounter] == 32)
                {
                    space_within_digits = true;
                    get_number_status=-1;
                }
            if (space_within_digits == false)
            {
                //// relocate items - exclude spaces leading or trailing
                temp_CharCounter=0;
                for (CharCounter=space_start_point; CharCounter < 
                    (space_end_point + 1); CharCounter++)
                {
                    character_in_ascii_code[temp_CharCounter] = 
                        temp_character_in_ascii_code[CharCounter];
                    temp_CharCounter++;
                }
                total_characters_entered=temp_CharCounter;
                // check if there are more than one points - ".".
                for (CharCounter=0; CharCounter<
                     total_characters_entered; CharCounter++)
                {
                    if (character_in_ascii_code[CharCounter] == 46) 
                    {
                        numer_of_points++;
                        point_index = CharCounter;
                        // point_index is useful
                        // when numer_of_points equals 1
                    }
                } //end for (CharCounter=0; 
                  //         CharCounter<total_characters_entered;
                  //         CharCounter++)
                if (numer_of_points > 1)
                    get_number_status=-1;
                    // error : number  cannot have
                    // more than one decimal points
                else // convert array elements into number
                {
                    if (numer_of_points == 1)
                    {
                        // **
                        if (point_index > 0)
                        // number started with digit e.g. 8.5 
                        {
                            // process integer part first
                            for (CharCounter=0; CharCounter<
                                 point_index ; CharCounter++)
                            {
                                for (DigitCounter=0; DigitCounter < 
                                     ascii_character_table_columns; 
                                     DigitCounter++)
                                {
                                  if (character_in_ascii_code[CharCounter] == 
                                      ascii_character_table[0][DigitCounter])
                                    integer_part += 
                                     ((pow(10,(point_index - CharCounter)))*
                                      (ascii_character_table[1][DigitCounter]))/ 10;
                                } //end for (DigitCounter=0;
                                  //  DigitCounter<ascii_character_table_columns;
                                  //  DigitCounter++)
                            } //end for (CharCounter=0;
                              //         CharCounter<total_characters_entered;
                              //CharCounter++)
                            // then process fraction part
                            if ((point_index + 1) == total_characters_entered)
                                fraction_part=0.00; // basically do nothing!
                            else // we have some digits following the point
                            {
                                for (CharCounter = (point_index + 1); 
                                     CharCounter<total_characters_entered ; 
                                     CharCounter++)
                                {
                                    for (DigitCounter=0; DigitCounter < 
                                         ascii_character_table_columns; 
                                         DigitCounter++)
                                    {
                                      if (character_in_ascii_code[CharCounter] == 
                                          ascii_character_table[0][DigitCounter])
                                        fraction_part += 
                                         ((pow(10,(point_index - CharCounter)))*
                                          (ascii_character_table[1][DigitCounter]));
                                    } //end for (DigitCounter=0;
                                      // DigitCounter<
                                      // ascii_character_table_columns;
                                      // DigitCounter++)
                                } //end for (CharCounter=0; CharCounter<
                                  //total_characters_entered; CharCounter++)
                            } //if ((point_index + 1) == total_characters_entered)
                        } //if (point_index > 0)
                          // number started with digit e.g. 8.5 
                        // **
                        if (point_index == 0)  //working on a number like .5 etc
                        {
                            for (CharCounter = (point_index + 1); 
                                 CharCounter<total_characters_entered ; 
                                 CharCounter++)
                            {
                                for (DigitCounter=0; DigitCounter < 
                                     ascii_character_table_columns; 
                                     DigitCounter++)
                                {
                                  if (character_in_ascii_code[CharCounter] == 
                                        ascii_character_table[0][DigitCounter])
                                   fraction_part += ((pow(10, 
                                      (point_index - CharCounter)))*
                                      (ascii_character_table[1][DigitCounter]));
                                } //end for (DigitCounter=0; DigitCounter<
                                  //ascii_character_table_columns;
                                  //DigitCounter++)
                            } //end for (CharCounter=0; CharCounter<
                              //total_characters_entered; CharCounter++)
                        }
                        // **
                    }
                    if (numer_of_points == 0) // number without decimals
                    {
                         for (CharCounter=0; CharCounter<
                              total_characters_entered; CharCounter++)
                        {
                            for (DigitCounter=0; DigitCounter<
                                 ascii_character_table_columns; DigitCounter++)
                            {
                                if (character_in_ascii_code[CharCounter] == 
                                    ascii_character_table[0][DigitCounter])
                                {
                                  integer_part += ((pow(10,
                                   (total_characters_entered-CharCounter)))*
                                   (ascii_character_table[1][DigitCounter]))/ 10;
                                } //end if 
                                  //(character_in_ascii_code[CharCounter] == 
                                  //ascii_character_table[0][DigitCounter])
                            } //end for (DigitCounter=0; DigitCounter<
                              //ascii_character_table_columns; DigitCounter++)
                        } //end for (CharCounter=0; CharCounter<
                          //total_characters_entered; CharCounter++)
                    }
                    // everthing went on well!
                    validated_number = integer_part + fraction_part;
                } //end if (numer_of_points > 1)
            } //if (space_within_digits=false)
        } //if (total_characters_entered > max_chars_allowed) 

        // check if grade is within allowed range
        if ((validated_number < number_lower_bound) || 
            (validated_number > number_upper_bound))
        // we procesed three digits but need to check
        // if they are within acceptable range
            get_number_status=-1;
            // number out of range, set -1 flag
        else
            input_not_accepted=false;
        
        if (get_number_status==-1)
        {
            input_not_accepted=true;
            get_characters=true;
        }
    } // while (input_not_accepted) loop to ensure
      // number entered is within valid & within range
    return validated_number;
}

Points of interest

At the time I was writing the code, I was particularly interested in positive numbers only. The code can be modified to include negative numbers by letting the ASCII code 45 (minus sign) to be an acceptable character.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Malawi Malawi
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --