CS 111 Assignment 6

  1. Files to print out and bring to lecture and recitation
  2. Preparations before you begin your homework
  3. Practice problems
  4. Assigned programming problems
  5. Preparing to hand in your homework

This assignment is due Wednesday, May 3, 2006.


  1. Files to print out and bring to lecture and recitation

    Below are tutorials and example programs and data files. Please make printouts of these and bring them with you to both lecture and recitation. However, please do NOT print them out in an on-campus lab. (On-campus printers are to be used only for your homework, i.e. for files YOU wrote.) If you do not have a computer at home, with a printer, ask a friend or classmate to print out copies of the following files for you.


  2. Preparations before you begin your homework

    On venus, create a directory named hw06 inside your homework directory. Change your present working directory to hw06 and then copy into it the example files for this homework assignment, by typing:

       cp ~nixon/cs111/hw06/* .
    

    Please do NOT copy these files into your home directory, to avoid cluttering your home directory. If you inadvertantly copied them into your home directory, move them out using the mv command. Be very careful about deleting anything in your home directory, to avoid inadvertantly deleting your hidden files (.login, .cshrc, .profile, etc.).


  3. Practice problems

    Answers to practice problems are here.

    1. In textUtility.cpp, the function isNaturalNumber is now a stub. (For more about stubs, see the section on "stubs and drivers" in the totorial on String class objects as parameters to functions . Replace the stub with a function which actually does what it is supposed to do, according to the comment above the function.

      The function must check two things: (1) whether the string contains at least one character (i.e., whether its length is at least 1) and (2) whether all the string's characters are non-digit characters. Note that checking whether all the string's characters are digit characters can be accomplished by checking whether the string contains any non-digit characters. You may use a technique similar to the loop in the isAsciiControl function which checks whether a string contains any control characters. To check whether the character at position i in string text is a non-digit, you may use a negated call to the isAsciiDigit function (defined in textUtility.cpp) as follows:

            if ( ! isAsciiDigit(text[i]) )
      

      Don't blindly copy the isAsciiControl function. Be careful about deciding the circumstances under which your isNaturalNumber function should return true, vs. the circumstances under which it returns false. Remember that a string can represent a natural number only if it contains NO non-digit characters, NOT if your function has succeeded in finding a non-digit character.

      However, if a string contains no non-digit characters, that in itself is not sufficient to guarantee that the string represents a natural number. A string which contains no non-digit characters MIGHT represent a natural number. Itt might also be an empty string, which does not represent a natural number, even though it contains no non-digit characters (because it contains no characters at all). Your function will need to treat the empty string as a special case. It is recommended that your function check for an empty string (and return false if the string is empty) BEFORE the function begins testing whether a non-empty string contains non-degit characters.).

      To test your function, compile the driver program testIsNaturalNumber1.cpp by typing:

         g++ testIsNaturalNumber1.cpp textUtility.cpp
      

      and run it, entering various test strings. First, check the performance of your function for various nonempty strings, some of which represent natural numbers and some of which do not. The strings you check should include the following:

         1234567890
         123456789012345678901234567890
         09
         0
         9
         /
         :
         a2
         2a
      

      Note that '/' is the character whose ASCII/Unicode value is one less than that of the digit '0', and ':' is the character whose ASCII/Unicode value is one greater than that of the digit '9'. When testing a program, it is always a good idea to check boundary cases such as these.

      Your function should recognize very long purely-numeric strings, such as the second one on the list above, as representing natural numbers.

      Now run testIsNaturalNumber1.cpp again, entering an empty string. When used with an empty string, the program should state that it does NOT represent a natural number.

      Then test your function further by compiling another driver program testIsNaturalNumber2.cpp by typing:

         g++ testIsNaturalNumber2.cpp textUtility.cpp
      

      and run it.

    2. In textUtility.cpp, write function isInteger with the following comment and heading:

      /*
       * bool isInteger(const string& text)
       *
       * Tests whether the specified string represents
       * an integer.  A string represents an integer if,
       * and only if, it consists of a string representing
       * a natural number possibly prefixed by an optional
       * leading minus sign. 
       *
       * Parameter:
       *    text -  the string to be tested.
       *
       * Returns:
       *    true if text represents an integer,
       *    false otherwise.
       */
      bool isInteger(const string& text)
      

      and put a suitable declaration (prototype) in the header file textUtility.h. In textUtility.cpp, define the function so that it behaves as advertised in the comment. It should recognize, as representing integers, all strings that are recognized as natural numbers by the function isNaturalNumber, plus all strings that consist of a leading minus sign (-) followed by at least one digit character and no non-digit characters.

      Note that the comment does NOT specify an allowed range of the integer. The function should return true for a string representing any integer, no matter how big.

      Before testing for a leading minus sign, your function should first check whether the string is empty. Otherwise, your function might try to access the nonexistent first character in an empty string, resulting in an unpredicatable runtime error.

      If the string begins with a leading minus sign, you will then want to call isNaturalNumber for a substring consisting of the all the characters in the original string EXCEPT for the leading minus sign. A substring that skips the first character of string text could be generated as follows:

            string restOfText = text.substr(1, text.length()-1);
      

      (For more about the substr function, review the tutorial on string functions in Assignment 4.)

      If the string text does NOT begin with a leading minus sign, then isNaturalNumber should be called for text itself.

      To test your function, compile driver program testIsInteger.cpp by typing:

         g++ testIsInteger.cpp textUtility.cpp
      

      and run it.

      Make sure your function works correctly for all the cases tested by the program.

    3. In textUtility.cpp, write function isForbinInt with the following comment and heading:

      /*
       * bool isForbinInt(const string& text)
       *
       * Tests whether the specified string represents
       * a value of type int on forbin.  A string represents
       * such a value if, and only if, it consists of a
       * string representing an integer and that integer is
       * within the int range on forbin, i.e. within the
       * range -2147483648 to 2147483647, inclusive.
       *
       * Parameter:
       *    text -  the string to be tested.
       *
       * Returns:
       *    true if text represents an int on forbin.
       *    false otherwise.
       */
      bool isForbinInt(const string& text)
      

      and put a suitable declaration (prototype) in the header file textUtility.h. In textUtility.cpp, define the function so that it behaves as advertised in the comment.

      It is recommended that begin by calling your isInteger function to determine whether the string represents an integer. If the string does not represent an integer, then it obviously does not represent an integer within the int range on forbin, either. So, if your call to isInteger returns false, then isForbinInt can go ahead and return false too. Only if the string represents an integer do you need to concern yourself with whether the represented integer is within the appropriate range.

      To determine whether the represented integer is within the appropriate range, you CANNOT simply then convert it to int (say, by calling the parseNaturalNumber function) and then test whether the value is within range. If the value is not within range, it will not be converted correctly to an int. (Any resulting int WILL be within the int range, whether or not the number represented by the original string was within the int range.)

      Instead, you will need to do comparisons of the strings themselves to strings representing the extreme values of the forbin int range. First, review the information about comparison of strings in the tutorial More about characters and strings.

      Before you can compare strings of digit characters, you'll need to strip the leading minus sign, if any, using either the substr function or the erase function. (For information about the erase function, see the tutorial on string functions in Assignment 4.) When removing the minus sign, do not modify the contents of the string text itself. Remember that text has been declared const, which means it cannot be changed. Any attempt to change it will give you a syntax error. So, instead of changing text itself, declare a string local variable which will be a copy of text. You can modify the local variable at will.

      As explained in the Assignment 6 tutorial More about characters and strings, a lexicographical comparison of strings representing natural numbers corresponds to a numeric comparison of the represented numbers only if the two numbers have the same number of digits. So, before you do the lexicographical comparison, you'll first need to check the lengths. But before you can meaninfully check the length, you'll first need to remove all leading zeroes, if any. Again, do not remove leading zeroes from text itself, but only from a local variable copy.

      The numbers at the limits of the int range, -2147483648 to 2147483647, each have 10 digits. So, after you've removed the leading minus sign and leading zeroes, if any, you can tell that the represented integer is in the int range if its length is less than 10, and you can tell that it is NOT in the int range if its length is greater than 10. If its length is equal to 10, then you'll need to do the lexicographical comparison.

      However, to know the exact string to which we need to do our lexicographical comparison ("2147483648" or "2147483647"), we need to know whether our original string was supposed to represent a negative number. To that end, you might want to use a boolean variable to keep track of whether original string text began with a leading minus sign, before you removed it.

      Plan your algorithm carefully in light of all the above considerations.

      Test your function using the driver program testIsForbinInt.cpp. (Remember to compile it together with textUtility.cpp.)

    4. In textUtility.cpp, write function parseForbinInt with the following comment and heading:

      /*
       * bool parseForbinInt(const string& text,
       *                     int& number)
       *
       * Converts a string to an int value, if the
       * string represents an integer within forbin's
       * int range, i.e. within the range
       * -2147483648 to 2147483647, inclusive.
       *
       * Parameters:
       *    text - the string to be converted
       *    number -  the intended int value.
       *       Precondition: none
       *       Postcondition:  number is the intended
       *          integer value represented by the string,
       *          if the string represents a valid forbin
       *          int value.  Otherwise, number is
       *          unchanged.
       *
       * Returns:
       *    true if a non-negative integer was successfully
       *    read from text, false otherwise.
       */
      bool parseForbinInt(const string& text,
                          int& number)
      

      and put a suitable declaration (prototype) in the header file textUtility.h. In textUtility.cpp, define the function so that it behaves as advertised in the comment.

      It is recommended that you begin the body of the parseForbinInt function by calling isForbinInt to determine whether the string represents a valid forbin int value. If it doesn't, then the parseForbinInt function does not need to do anything further, except to return false. Only if the string does represent a valid integer does it make sense to bother doing the actual conversion.

      Then, to do the actual conversion, it is recommended that you call parseNaturalNumber. But first, check whether the string begins with a leading minus sign. If so, a substring should be generated without the leading minus sign, so that parseNaturalNumber can be called for the substring, which will consist of digit characters only.

      Then, make sure the resulting integer value ends up with the correct sign, by subtracting it from zero if the original string began with a leading minus sign. You may want to use a boolean variable to keep track of this.

      Test your function using the driver program testParseForbinInt.cpp. Remember to compile it together with textUtility.cpp.

      Make sure your function works correctly for all values, including -2147483648, the low end of the range.

    5. See again the practice problems for Assignment 5. Make sure you undestand how to do them using functions, if you did not do so earlier.


  4. Assigned programming problem

    Write a program transaction.cpp containing the following functions and a main function which tests them:

    • A boolean function which simulates making a deposit into an account with a specified balance. This function takes a reference parameter of type double representing the account balance. The user should be prompted for an amount of money to deposit. In the event of non-numeric input, an error message is printed and the function returns false. If the input is a valid floating-point number (type double), the function then displays the new balance which results from adding the amount entered by the user. The new balance is also stored in the reference parameter.

      Note that this function will need to use cin and cout as global variables. It should be commented accordingly.

    • A boolean function which makes a withdrawal from a specified account. This function, too, takes a reference parameter of type double representing the account balance It behaves similarly to the function described above, except that the amount entered by the user is subtracted from rather than added to the old balance to obtain the new balance. Also, this function should be defined so as not to allow the user to overdraw. If the amount that the user wants to withdraw is larger than the account balance, an error message should be printed, and the user should be prompted repeatedly for an appropriate amount, until an appropriate amount is entered. The return value should be the error state of cin.

    • A parameterless void function which outputs the following menu and prompt:

      What do you want to do?
      
         D - make a deposit
         W - make a withdrawal
         Q - quit
      
      Enter your selection (D, W, Q):>
      

    Your main function should prompt the user for (1) an account balance and then (2) a character to indicate the transaction. (To output the latter prompt, use your function which outputs the menu and prompt.) The program should then simulate a deposit if the user selected 'D' (or 'd') and simulate a withdrawal if the user selected 'W' (or 'w'). In either case, the modified account balance should be eisplayed. If the user entered any other character besides 'D', 'd', 'W', or 'w', the program should display the account balance and quit.

    Write the program one function at a time. First, just write a trigial, do-nothing main function and make sure that that compiles. Then write your menu/prompt function plus a call to it in the main function, mand make sure that that compiles and runs correctly. Then write the deposit function and a call to it from the main function (and the necessary lines in the main function that are needed to input the account balance), and run the program to test the deposit function. Then likewise for the withdraw function. Then complete the main function so that it does everything it is supposed to do.


  5. Preparing to hand in your homework

    The usual.


Back to: