Cstring-to-Number Conversions

  1. The function atoi, atol, and atof, have a cstring argument and can be used to convert a cstring of digits to the corresponding numeric value, i.e. to a value of type int, long, and double, respectively.

  2. The name atoi stands for "alphabets to integers".

  3. If the cstring is such that conversion cannot be done, these functions returns a zero of the appropriate type.

  4. For example,

    int x = atoi("666");
    int y = atoi("SlaughterHouse5");

    sets the integer x to 666 and y to 0,and

    double z = atof("3.1416");

    sets the double z to 3.1416.

  5. These functions are in the cstdlib header file.

  6. These functions can be used to improve the robustness of reading numeric inputs.

  7. For example the company in which you are working needs a program to read in an amount of money. The program has to work properly with many sensible inputs such as: 1234, or 1,234, or $1,234, or US$1,234. Failure to read the correct dollar amount can cause the company to lose millions of dollars and can even get you fired.

  8. A robust way is to read the input first as a cstring which has been declared to a sufficiently large size to capture the entire input.

    The program can then strip away all unwanted characters, such as the comma and the dollar sign, leaving a cstring of digits.

    The atoi or atof function can then be used to convert this cstring of digits to a pure numerical value that can be used in computation involving the amount of money.

  9. //Demonstrates the function read_and_clean for robust input.
    #include <iostream>
    #include <cstdlib>
    #include <cctype>
    using namespace std;

    void read_and_clean(int& n);
    //Reads a line of input. Discards all symbols except the digits.
    //Converts the string of digits to an integer and
    //sets n equal to the value of this integer.

    void new_line( );
    //Discards all the input remaining on the current input line.
    //Also discards the '\n' at the end of the line.

    int main( )
    {
       int n;
       char ans;
       do
       {
          cout << "Enter an integer and press return: ";
          read_and_clean(n);
          cout << "That string converts to the integer " << n << endl;
          cout << "Again? (yes/no): ";
          cin >> ans;
          new_line( );
       } while ( (ans != 'n') && (ans != 'N') );
       return 0;
    }

    //Uses iostream, cstdlib, and cctype:
    void read_and_clean(int& n)
    {
       const int ARRAY_SIZE = 6;
       char digit_string[ARRAY_SIZE];
       int index = 0;
       char next;

       cin.get(next);
       while (next != '\n')
       {
          if ( (isdigit(next)) && (index < ARRAY_SIZE - 1) )
          {
             digit_string[index] = next;
             index++;
          }
          cin.get(next);
       }
       digit_string[index] = '\0';

       n = atoi(digit_string);
    }

    //Uses iostream:
    void new_line( )
    {
       char symbol;
       do
       {
          cin.get(symbol);
       } while (symbol != '\n');
    }

  10. Note that the new_line function is needed to discard all the input remaining on the current line, including the '\n' at the end.

  11. Note that the program fails TRAGICALLY if the user types in a decimal point! Do you see a way to improve the program?

  12. //Demonstration program for improved version of get_int.
    #include <iostream>
    #include <cstdlib>
    #include <cctype>
    using namespace std;

    void read_and_clean(int& n);
    //Reads a line of input. Discards all symbols except the digits. Converts
    //the digit string to an integer and sets n equal to the value of this integer.

    void new_line( );
    //Discards all the input remaining on the current input line.
    //Also discards the '\n' at the end of the line.

    void get_int(int& input_number);
    //Gives input_number a value that the user approves of.

    int main( )
    {
       int input_number;
       get_int(input_number);
       cout << "Final value read in = " << input_number << endl;
       return 0;
    }

    //Uses iostream and read_and_clean:
    void get_int(int& input_number)
    {
       char ans;
       do
       {
          cout << "Enter input number: ";
          read_and_clean(input_number);
          cout << "You entered " << input_number
                << " Is that correct? (yes/no): ";
          cin >> ans;
          new_line( );
       } while ((ans != 'y') && (ans != 'Y'));
    }

    //Uses iostream, cstdlib, and cctype:
    void read_and_clean(int& n)
    {
       const int ARRAY_SIZE = 6;
       char digit_string[ARRAY_SIZE];
       int index = 0;
       char next;

       cin.get(next);
       while (next != '\n')
       {
          if ( (isdigit(next)) && (index < ARRAY_SIZE - 1) )
          {
             digit_string[index] = next;
             index++;
          }
          cin.get(next);
       }
       digit_string[index] = '\0';

       n = atoi(digit_string);
    }

    //Uses iostream:
    void new_line( )
    {
       char symbol;
       do
       {
          cin.get(symbol);
       } while (symbol != '\n');
    }