$29
Educational Objectives: After completing this assignment the = student=20 should have the following knowledge, ability, and skills:
• Open and read text files with filenames determined at runtime=20
• Read numerical data from text files in various formats (octal, = decimal,=20 and hexadecimal)=20
• Open and write text files with filenames determined at runtime=20
• Format text file output using std:: I/O manipulators=20
• Write numerical data in various formats (octal, decimal, and = hexadecimal)=20
• Create and use an I/O manipulator with zero parameters=20
• Explain how manipulators are created, including the background = assumptions=20
• Explain how manipulators function by detailing the actions = triggered by a=20 manipulator call
Operational Objectives: Create a file formatting = program=20 bases.cpp as described in the code requirements and = specifications=20 below.
Deliverables: One file bases.cpp.
I/O Manipulators
The goal for this assignment is learn about and use I/O manipulators. = We will=20 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=20 function. (The manipulators that take parameters are somewhat more = complex,=20 requiring function objects.) Here's how it works:
Various properties of I/O are controlled by "flags", which are public = member=20 variables of the base class std::ios and hence inherited by = other=20 classes such as std::istream, std::ostream,=20 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=20 implementations they are single bits, although this is not specified by = the=20 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=20 example, you want to unset the flags dec and oct and = set the=20 hex flag for the stream object s, you would make these = two=20 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=20 also the use of bitwise OR to combine the dec and oct = flags=20 into a single argument.
An I/O manipulator has the following prototype pattern:
std::ios& M(std::ios& s); =20
where M is the name of the manipulator. Note that it takes a = stream=20 base object by reference and then returns the same object (modified), so = that it=20 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=20 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=20 only thing left to do is actually write the manipulator function (the = parameter=20 F() in the operator overloads above). Here is how to write the=20 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=20 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=20 stream object for further processing. For input streams, this will mean = that=20 numerical input is assumed to be in hexadecimal notation. For output = streams,=20 this will mean that numbers are output in hexadecimal notation.
Procedural Requirements
1. Create and work within a separate subdirectory = cop3330/hw5. Review=20 the COP 3330 rules found in Introduction/Work Rules.
2. Begin by copying the following files from the course directory: = into your=20 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=20 for Sun/Solaris and _i are compiled for Intel/Linux. Use one = of the=20 sample client executables to experiment to get an understanding of how = your=20 program should behave.
3. Create the file bases.cpp that meets the specifications = required=20 below.
4. Turn in the file bases.cpp using the hw5submit.sh = submit=20 script.
Warning: Submit scripts do not work on the = program and=20 linprog servers. Use shell.cs.fsu.edu to submit = projects. If=20 you do not receive the second confirmation with the contents of your = project,=20 there has been a malfunction.
Code Requirements and Specifications
1. Do not use any "using" directives in your code.
2. The following constants should be declared and used in = bases.cpp:=20
static const unsigned short
cwh =3D 16, // max digits of unsigned long hexadecimal
cwd =3D 20, // max digits of unsigned long decimal
cwo =3D 26, // max digits of unsigned long octal
cs1 =3D 4, cs2 =3D 2// col spacers
Do not hard code literal values for column widths and column = spacers. These=20 constants are set up to produce tables when the integers are 64-bit = (eight=20 byte) words (the size of type unsigned long). The various = cw=20 values are the max size of a 64-bit number in the various notations. = The=20 cs values are the spacing preceeding the column.
3. The application bases should take two file names at the = command=20 line. The first is an input file, which contains documentation, = instructions,=20 and data. The second is an output file in which a table should be = created=20 according to the input file instructions and data.
Note that there are options specifying the numerical notation for = input and=20 for the notation in two columns of output. The output file should be a = table=20 with header (giving the names of the output file and the input file) = and=20 column headers indicating the notation used in that column. The data = in the=20 table consists of one line for each number in the input file, in the = notation=20 specified by the formatting characters. See bases.x and the = example=20 input data files for clarification of this behavior.
4. The input file is formatted as follows:
input file format:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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' =3D decimal
'D' =3D decimal
'h' =3D hex/lower case
'H' =3D hex/upper case
'o' =3D octal
'O' =3D octal
second character of pair: fill (affects hex and oct only)
'f' =3D fill hex and octal with leading zero, 64-bit
'n' =3D 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=20 characters, and then proceed to read the file data, constructing the = table in=20 the output file as it goes. (There is no need to store more than one = integer=20 at a time, just read an integer and then write the line of the output = file=20 table corresponding to that input.)
5. The output file should begin with two lines of information giving = the names=20 of the file and the input data file. The third line should be blank, = and the=20 fourth line should have the headers for the table columns. The actual = table=20 entries should commence below, and allign correctly with, the column = headers.=20
6. Be sure that hex and octal numbers are output with the correct = number of=20 leading zeros in case 'f'. The defined constants cwx = above=20 give the correct size needed for 64-bit numbers.
7. When in doubt, use the distributed executables for guidance in = constructing=20 the output file.
Hints
• Keep in mind: numbers inside the machine are all binary. Decimal, = octal,=20 and hexadecimal are human lexical representations that exist only = outside the=20 machine, on screen or in files.
• To get a number to print in 64-bit (16 digit) hex notation with = leading=20 zero fill, you need a column exactly 16 characters wide. If you need = more=20 visual space in the table, you will need an extra "column" of spaces = for that=20 purpose.
• The best way to skip documentation is to peek() and then=20 get() to end of line. It's a mistake to try to use=20 "getline()" in this assignment; this function is usually too = crude=20 for intricate work, and it often erroneously discards data from the = input=20 stream. You really don't need any string variables for this = assignment,=20 although they are allowed.
• Note: There may be no lines of documentation.
• See the program examples/commandLineArguments.cpp to see = how to=20 handle command line arguments in C++. Compile and run this program = with some=20 command line arguments (strings), then take a look at the source code. = For=20 example:
=
lacher@diablo:~/3330/examples>commandLineArguments.x =
aa bbbbbb cccc
4 command line arguments were entered.
The data passed to function main were:
4 =3D argc
argv[0] =3D commandLineArguments.x
argv[1] =3D aa
argv[2] =3D bbbbbb
argv[3] =3D cccc
lacher@diablo:~/3330/examples>
Note that the program and the OS cooperate via the "argument = counter"=20 argc and the "argument vector" argv. argc = gives the=20 number of input strings (starting with the name of the executable = itself as=20 "zero"), and argv is an array of strings containing all of = these=20 arguments. Note that the name of the executable will always be=20 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