Educational Objectives: After completing this assignment the student should have the following knowledge, ability, and skills:
Operational Objectives: Create a file formatting program bases.cpp as described in the code requirements and specifications below.
Deliverables: One file bases.cpp.
The goal for this assignment is learn about and use I/O manipulators. We will use the standard I/O manipulators defined in the namespace std.
An I/O manipulator may seem mysterious at first, but it is really a simple function. (The manipulators that take parameters are somewhat more complex, requiring function objects.) Here's how it works:
Various properties of I/O are controlled by "flags", which are public member variables of the base class std::ios and hence inherited by other classes such as std::istream, std::ostream, std::ifstream, and std::ofstream. These flag names are:
boolalpha , dec , fixed , hex , internal , left , oct , right , scientific , showbase , showpoint , showpos , skipws , unitbuf , uppercase , adjustfield , basefield , floatfield
These names can be manipulated as if they were single bits (and in most implementations they are single bits, although this is not specified by the language). There are also member functions of class ios
void setf (ios::flag F); void unsetf (ios::flag F);
that take a flag as argument and either set or unset the flag. If, for example, you want to unset the flags dec and oct and set the hex flag for the stream object s, you would make these two calls:
s.unsetf (std::ios::dec | std::ios::oct); s.setf (std::ios::hex);
Note that the scope of the flag must be resolved (std::ios::). Note also the use of bitwise OR to combine the dec and oct flags into a single argument.
An I/O manipulator has the following prototype pattern:
std::ios& M(std::ios& s);
where M is the name of the manipulator. Note that it takes a stream base object by reference and then returns the same object (modified), so that it makes sense to call the manipulator using the syntax
os << ... << M << ... // manipulator call syntax for an ostream os is >> ... >> M >> ... // manipulator call syntax for an istream is
This syntax is facilitated by overloads of the input and output operators something like this:
ios& operator << (ios& s, F()) { return F(); } ios& operator >> (ios& s, F()) { return F(); }
These overloads are already defined in the iostream library. So, the only thing left to do is actually write the manipulator function (the parameter F() in the operator overloads above). Here is how to write the hex manipulator function:
std::ios& hex (std::ios& s) { s.unsetf(std::ios::oct | std::ios::dec); s.setf(std::ios::hex); return s; }
Note the return of the incoming stream object (after its state is modified by changing the flag settings). The effect of this code:
is >> hex; os << hex;
is to set the hex flag (by calling hex(os)) and return the modified stream object for further processing. For input streams, this will mean that numerical input is assumed to be in hexadecimal notation. For output streams, this will mean that numbers are output in hexadecimal notation.
Create and work within a separate subdirectory cop3330/hw5. Review the COP 3330 rules found in Introduction/Work Rules.
Begin by copying the following files from the course directory: into your hw5 directory:
[LIB]/hw5/data?.in [LIB]/hw5/hw5submit.sh [LIB]/area51/bases_s.x [LIB]/area51/bases_i.x
The naming of these files uses the convention that _s are compiled for Sun/Solaris and _i are compiled for Intel/Linux. Use one of the sample client executables to experiment to get an understanding of how your program should behave.
Create the file bases.cpp that meets the specifications required below.
Turn in the file bases.cpp using the hw5submit.sh submit script.
Warning: Submit scripts do not work on the program and linprog servers. Use shell.cs.fsu.edu to submit projects. If you do not receive the second confirmation with the contents of your project, there has been a malfunction.
Do not use any "using" directives in your code.
The following constants should be declared and used in bases.cpp:
static const unsigned short cwh = 16, // max digits of unsigned long hexadecimal cwd = 20, // max digits of unsigned long decimal cwo = 26, // max digits of unsigned long octal cs1 = 4, cs2 = 2// col spacers
Do not hard code literal values for column widths and column spacers. These constants are set up to produce tables when the integers are 64-bit (eight byte) words (the size of type unsigned long). The various cw values are the max size of a 64-bit number in the various notations. The cs values are the spacing preceeding the column.
The application bases should take two file names at the command line. The first is an input file, which contains documentation, instructions, and data. The second is an output file in which a table should be created according to the input file instructions and data.
Note that there are options specifying the numerical notation for input and for the notation in two columns of output. The output file should be a table with header (giving the names of the output file and the input file) and column headers indicating the notation used in that column. The data in the table consists of one line for each number in the input file, in the notation specified by the formatting characters. See bases.x and the example input data files for clarification of this behavior.
The input file is formatted as follows:
input file format: ================= 1: file documentation lines at top of file begin with '#' 2: next string of data: (five format control characters) format for input file first character - how to interpret input numbers: 'o' or 'O': read in octal notation 'd' or 'D': read in decimal notation 'h' or 'H': read in hexadecimal notation next characters format output, read in pairs (two for col 1, two for col 2) first character of pair: numerical notation 'd' = decimal 'D' = decimal 'h' = hex/lower case 'H' = hex/upper case 'o' = octal 'O' = octal second character of pair: fill (affects hex and oct only) 'f' = fill hex and octal with leading zero, 64-bit 'n' = no fill for hex and octal 3: remainder of input file: unsigned long integers in notation designated by first format control character
The program should skip the documentation, then read the five formatting characters, and then proceed to read the file data, constructing the table in the output file as it goes. (There is no need to store more than one integer at a time, just read an integer and then write the line of the output file table corresponding to that input.)
The output file should begin with two lines of information giving the names of the file and the input data file. The third line should be blank, and the fourth line should have the headers for the table columns. The actual table entries should commence below, and allign correctly with, the column headers.
Be sure that hex and octal numbers are output with the correct number of leading zeros in case 'f'. The defined constants cwx above give the correct size needed for 64-bit numbers.
Output from your bases.x should duplicate exactly the output produced by the distributed executables. When in doubt, use the distributed executables for guidance in constructing the output file.
Keep in mind: numbers inside the machine are all binary. Decimal, octal, and hexadecimal are human lexical representations that exist only outside the machine, on screen or in files.
To get a number to print in 64-bit (16 digit) hex notation with leading zero fill, you need a column exactly 16 characters wide. If you need more visual space in the table, you will need an extra "column" of spaces for that purpose.
The best way to skip documentation is to peek() and then get() to end of line. It's a mistake to try to use "getline()" in this assignment; this function is usually too crude for intricate work, and it often erroneously discards data from the input stream. You really don't need any string variables for this assignment, although they are allowed.
Note: There might be zero lines of documentation.
See the program examples/commandLineArguments.cpp to see how to handle command line arguments in C++. Compile and run this program with some command line arguments (strings), then take a look at the source code. For example:
lacher@diablo:~/3330/examples>commandLineArguments.x aa bbbbbb cccc 4 command line arguments were entered. The data passed to function main were: 4 = argc argv[0] = commandLineArguments.x argv[1] = aa argv[2] = bbbbbb argv[3] = cccc lacher@diablo:~/3330/examples>
Note that the program and the OS cooperate via the "argument counter" argc and the "argument vector" argv. argc gives the number of input strings (starting with the name of the executable itself as "zero"), and argv is an array of strings containing all of these arguments. Note that the name of the executable will always be argv[0], for example.
Here is one sample session:
lacher@diablo:~/3330/hw5>c3330 bases lacher@diablo:~/3330/hw5>bases.x data1.in data1.out lacher@diablo:~/3330/hw5>
Here is the input file data1.in:
# data1.in # read data as decimal numbers # convert these numbers to a table of dec, hex values # ddnhf 0 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 4294967295 10000000000 100000000000 1000000000000 10000000000000 100000000000000 1000000000000000 10000000000000000 100000000000000000 1000000000000000000 10000000000000000000 18446744073709551615
Here is the outputfile data1.out:
Name of this file: data1.out Name of input data file: data1.in dec hex 0 0000000000000000 1 0000000000000001 10 000000000000000a 100 0000000000000064 1000 00000000000003e8 10000 0000000000002710 100000 00000000000186a0 1000000 00000000000f4240 10000000 0000000000989680 100000000 0000000005f5e100 1000000000 000000003b9aca00 4294967295 00000000ffffffff 10000000000 00000002540be400 100000000000 000000174876e800 1000000000000 000000e8d4a51000 10000000000000 000009184e72a000 100000000000000 00005af3107a4000 1000000000000000 00038d7ea4c68000 10000000000000000 002386f26fc10000 100000000000000000 016345785d8a0000 1000000000000000000 0de0b6b3a7640000 10000000000000000000 8ac7230489e80000 18446744073709551615 ffffffffffffffff