CSCE 2004 - Laboratory Assignment 9

The objective of this laboratory assignment is to give you some experience with slightly more advanced File I/O as well as an introduction to string operations in C++. We will learn how to precisely read individual characters from files and manipulate strings on a character-by-character basis. This lab has following steps:

  1. Review of Basic File I/O Operations and Concepts:
  2. Making Copies of Files
  3. The following program makes a copy of a file. It reads one character at time from the input file and writes it to the output file.

    Copy/paste, compile, and run this program. Note that you will need to supply your own text file for its use. The simplest mechanism for doing so is to create a new empty file in the same Netbeans project, and copy/paste the contents of TheFallOfTheLeaf.txt from the front page of the class website.

    Recall that open() and close() require character arrays (a.k.a., "C strings") for the filenames. You can extract a C-style character array from a C++ string by calling stringVariable.c_str() as was done with the In and Out string parameters inside copyChar().

    #include <iostream>
    #include <fstream>
    using namespace std;
    // copyChar function
    void copyChar(const string in, const string out)
       // Declare file stream variables 
       ifstream din;
       ofstream dout;
       char ch;
       // Open the input and output files in their respective modes with
       // appropriate error checking.
  ;     // convert from C++ string to C character array
       if (!din)
          cerr << "Could not open " << in << " for reading.\n";
;     // convert from C++ string to C character array
          if (!dout)
             cerr << "Could not open " << out << " for writing.\n";
             // Read one char at a time from the input file and copy it to output
             // file till end of file.
             while (din >> ch)
                dout << ch;
    // Main program
    int main()
       string inFilename, outFilename;
       // Get the input and output file names.
       cout << "Enter the input file name: ";
       cin >> inFilename;
       cout << "Enter the output file name: ";
       cin >> outFilename;
       // Call the CopyChar function which does the copying.
       copyChar(inFilename, outFilename);
       return 0;

  4. Now, One Character at a Time!
  5. Now, add the newly generated text file (whatever name you chose when running the above program) to your Netbeans project by right-clicking the "Resource Files" sub-menu, selecting "Add Existing Item..." and selecting the appropriate file. Open and view your file in Netbeans.

    Notice the (obvious) problem -- << and >> skip ALL whitespace, so any blanks have been removed. To fix this, modify the program to use get instead of >> and put instead of <<. Use the class's online C++ notes, Google (;)), or your book to figure out the syntax. Do not ask the TA or your labmates up front -- see what you are able to figure out on your own first.

    Once the program is working properly, make an addition to copyChar() so that it also counts the number of characters read and returns that number to the main program. Then, have the main program output that number to the screen.

  6. Strings? Substrings!
  7. One of the challenges in managing strings on a fine-grained scale is that their behavior is somewhat more complex than a normal character array. In particular, every string is composed not only of its constituent char values located in subsequent memory locations, but every string is also null-terminated, meaning there is a final char value of '\0' (read as "the NULL character"). In addition, string variables are implicitly objects in the string "class" (again, more on objects, classes, and the like next week). As a result, there are a number of methods (or, functions) that can be used with strings.

    Some of these methods you will already be familiar with. For instance, there is the .c_str() method that is applied to strings for use with open() from File I/O. .c_str() temporarily treats a C++ string as a C-style string (i.e. a character array). There are many other such methods, such as .substr(), which returns some piece of the interior of a string. It has two parameters: (1) the first, required parameter specifies the "position" at which we will begin the substring, and (2) the second, optional parameter specifies the "length" of the substring that we will use. Note that if the second parameter is omitted, the implicitly-used length will be the remainder of the string.

    Copy/paste, compile, and run the following program.

    #include <iostream>
    #include <string> //NOTE: this #include is redundant!
                      //<string> is a subset of <iostream> 
    using namespace std;
    int main()
       string str = "We think in generalities, but we live in details.";
                    //quoting Alfred N. Whitehead
       string clever, insight;     //cute names for two "partial" strings
       clever = str.substr(12,12); //"generalities"
       insight = str.substr(33);   //get from "live" to the end
       cout << clever << " " << insight << endl;
       return 0;

  8. Manipulating strings
  9. In order to really excel with strings, however, we would like to be able to do all of the same operations on them that we can with other data types. However, simple operations such as assignment (the '=' operator) generally fail. Recall that strings have character arrays underlying them, and that a naive use of '=' fails with arrays as well. Therefore, we will make use of the following two ideas:

    1. Strings can be subscripted just as arrays can. For instance:
      string str = "TEST";
      cout << str[2] << endl; //outputs 'S'
      Importantly, this will also allow you to change individual characters in strings on a case-by-case basis -- just as you might with an array.

    2. Strings or chars can be concatenated to the end of another string. For instance:
      string str1 = "TE";
      string str2 = "ST";
      str1 += str2; //equivalently, str1 = str1 + str2;
      cout << str1 << endl; //outputs "TEST"
      Importantly, if you have a string-valued function (one that returns a string value), an easy way to gain access to the returned value again in main() is to concatenate it to the end of an empty (in this case, uninitialized) string variable.

    Using any combination of the above ideas, write a program that prints out the 3-bit binary values from 0 to 7. That is,

    Your program should use a single string variable initialized to "000", along with (nested) looping and if-else logic to manipulate the value of the variable appropriately. Use the above concepts to access and change individual character values in different positions of the string as necessary. Do not hard-code any values except "000", "0", and "1" at any point in your solution.

  10. Submit Your Work
  11. To submit your lab work, have your TA check over any code/output that you've done during this lab session and record that you completed the lab assignment.

    Important Note: It is your responsibility, not the TA's, to ensure that your lab is recorded as being completed before you leave! Although the labs are intended to be completed in the alloted lab time, if you need additional time to finish the lab assignment, you have 24 hours from the end of the lab meeting time to finish. If so, you should ask your TA for instructions on how to submit the lab assignment after the lab ends.

  12. Logout of the System
  13. After making sure that you submitted the code correctly and you have done the entire assignment, logout of the system by clicking on the menu button in the lower left hand side of the desktop. Then, click on Log Off. Wait a few seconds for a window to pop up and then click Log Off.