0% found this document useful (0 votes)
182 views93 pages

Chapter Eight: Streams: Big C++ by Cay Horstmann

C++
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
182 views93 pages

Chapter Eight: Streams: Big C++ by Cay Horstmann

C++
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 93

Chapter Eight: Streams

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Chapter Goals

• To be able to read and write files


• To convert between strings and numbers using string
streams
• To process command line arguments
• To understand the concepts of sequential and
random access

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Topic 1

1. Reading and writing text files


2. Reading text input
3. Writing text output
4. Parsing and formatting strings
5. Command line arguments
6. Random access and binary files

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading and Writing Files

• The C++ input/output library is based on the concept of


streams.
• An input stream is a source of data.
• An output stream is a destination for data.
• The most common sources and destinations for data are
the files on your hard disk.
– You need to know how to read/write disk files to work with large
amounts of data that are common in business, administrative,
graphics, audio, and science/math programs

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Streams: An Example
This is a stream of characters. It could be from
the keyboard or from a file. Each of these is
just a character - even these: 3 -23.73 which,
when input, can be converted to: ints or doubles
or whatever type you like.
(that was a '\n' at the end of the last line)
&*@&^#!%#$ (No, that was –not- a curse!!!!!!!!!!
¥1,0000,0000 (price of a cup of coffee in Tokyo)
Notice that all of this text is very plain - No
bold or green of italics – just characters – and
whitespace (TABs, NEWLINES and, of course... the
other one you can’t see: the space character:
(another '\n')
(&& another) (more whitespace)

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading and Writing Streams

The stream you just saw is a plain text file.


No formatting, no colors, no video or music
(or sound effects).

A program can read these sorts of plain text streams of


characters from the keyboard, as has been done so far
with cin.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading and Writing Disk Files

You can also read and write files stored on your hard disk:

• plain text files


• binary information (a binary file)
– Such as images or audio recording

To read/write files, you use variables of the stream types:


ifstream for input from plain text files.
ofstream for output to plain text files.
fstream for input and output from binary files.
You must #include <fstream>
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Opening a Stream

To read anything from a file stream,


you need to open the stream.

(The same for writing.)


Opening associates the variable name with the file name.

After the file is open, you refer to it ONLY by the stream


variable name.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Code for Opening Streams
ifstream in_file;
in_file.open("input.txt"); //filename is input.dat

An alternative shorthand syntax combines the 2 statements:

ifstream in_file(“input.txt”);

As your program runs and tries to find this file, it WILL ONLY LOOK IN
THE DIRECTORY (FOLDER) IT IS LOCATED IN!

That is a common source of errors. If the desired file is not in the


executing program’s folder, the full file path must be specified.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
File Path Names
File names can contain directory path information, such as:
UNIX
in_file.open("~/nicework/input.dat");
Windows
in_file.open("c:\\nicework\\input.dat");

When you specify the file name as a string literal, and the name
contains backslash characters (as in Windows),
you must supply each backslash twice
to avoid having unintended escape characters in the string.

\\ becomes a single \ when processed by the compiler.

Big C++ by Cay Horstmann


Copyright © 2018
2008 by John Wiley & Sons. All rights reserved
When the File Name is in a C++ string variable

If the filename comes from the user, you will store it in a


string. If you use a C-string (char array), the open()
function works fine.

If you use a C++ string, some older library versions require


you to convert it to a C-string using c_str() as the
argument to open():

cout << "Please enter the file name:";


string filename;
cin >> filename;
ifstream in_file;
in_file.open(filename.c_str());

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Opening a Stream, Filename is a char[] array

cout << "Please enter the file name:";


char filename[80];
cin >> filename;
ifstream in_file;
in_file.open(filename);

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Closing a Stream

When the program ends,


all streams that you have opened
will be automatically closed.

You can manually close a stream with the


close member function:

in_file.close();

Manually closing a stream is only necessary


if you want to re-use the same stream variable for a different
file, or want to switch from input to output on the same file.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading from a Stream: Use >>

You already know how to read and write using files – it is the
same syntax as with cin, which is an istream also.

string name;
double value;
in_file >> name >> value;

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading from a Stream, Testing for Failure
The >> operator returns a “not failed” condition,
allowing you to combine an input statement and a test.
A “failed” read yields a false
and a “not failed” read yields a true.

if (in_file >> name >> value)


{
// Process input
}

To read the entire file, use a loop:

while (in_file >> name >> value)


{
// Process input
} Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Failing to Open

The open method also sets a “not failed” condition.


It is a good idea to test for failure immediately:

in_file.open(filename.c_str());
// Check for failure after opening
if (in_file.fail())
{
cout << “Error opening file: “ <<
filename << endl;
return -1;
}
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Writing to a Stream: Just Like cout <<

To write to a file: declare an ofstream variable, open the


file, check for failure, and then stream the data to the
ofstream with <<

ofstream out_file;
out_file.open("output.txt");
if (in_file.fail()) { return -1; }
out_file << name << " " << value << endl;

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
A Programming Example: Popular Names

The Social Security Administration publishes


lists of the most popular baby names @
http://www.ssa.gov/OACT/babynames/.

A query of the 1000 most popular names for


the 1990s yields the screen shown here:

We saved the data as text, and pasted it into


the book companion code babynames.txt
file.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
File Structure

Each line in the file contains seven entries:


• The rank (from 1 to 1,000)
• The name, frequency, and percentage of the male name of that rank
• The name, frequency, and percentage of the female name of that rank

An example line from the file:


10 Joseph 260365 1.2681 Megan 160312 0.8

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Baby Names Program Planning

Sample line: 10 Joseph 260365 1.2681 Megan 160312 0.8

We will display the top 50% of the names stored in the file.

To process each line, we first read the rank:


int rank;
in_file >> rank;

Next we read three values for that boy’s name:


string name;
int count;
double percent;
in_file >> name >> count >> percent;

Then we read the 3 values for the girl data.

Let's make a helper function (process_name) to do the 3 reads.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Loop Control, and Reference Parameters for Functions
To stop processing after reaching 50%, we could add up the
frequencies and stop when they reach 50%.

However, it is simpler to have “total” variables for boys and


girls, initialized with 50.

Then we’ll subtract the frequencies as we read them and


stop when the total reaches 0.

Reading or writing a file modifies the stream variable, as it


counts the number of characters read or written so far.

For that reason, you must always make stream parameter


variables reference parameters.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Baby Names: Code Part 1
// sec01/babynames.cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
/**
Reads name information, prints the name if total >= 0, and
adjusts the total.
@param in_file the input stream
@param total the total percentage that should still be processed
*/
void process_name(ifstream& in_file, double& total)
{
string name;
int count;
double percent;
in_file >> name >> count >> percent;
// Check for failure after each input
if (in_file.fail()) { return; }
if (total > 0) { cout << name << " "; }
total = total - percent;
} Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Baby Names: Code Part 2
int main()
{
ifstream in_file;
in_file.open("babynames.txt");
// Check for failure after opening
if (in_file.fail()) { return 0; }
double boy_total = 50;
double girl_total = 50;
while (boy_total > 0 || girl_total > 0)
{
int rank;
in_file >> rank;
if (in_file.fail()) { return 0; }
cout << rank << " ";
process_name(in_file, boy_total);
process_name(in_file, girl_total);
cout << endl;
}
return 0; Big C++ by Cay Horstmann
} Copyright © 2018 by John Wiley & Sons. All rights reserved
Practice It: File I/O Basics

• Write code statements for the following.


– Answers are shown in tiny font which you may enlarge.

Define an input ifstream in; An ifstream object is an input file stream variable.

file stream variable named in.
Associate the input
file stream with a file in.open("in.txt");
The open function associates the input stream with the
disk file in.txt and opens it for reading.

named in.txt.
Define a variable word;
Use word to read the first word string word; in >> word;
Simply use the same input operations with which you are
already familiar. The >> operator reads the next word.

from the file.


Declare an output ofstream out; The output file stream is an ofstream.

file stream variable named out.
Use the output stream variable
to create a new file out.open("out.txt"); Use the open function to create the desired text file.

named out.txt.
Write a line consisting of the out << "Hello" << endl;
To write to a file, use the << operator and
the endlmanipulator that you have already used with cout.

word Hello to out.txt.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Practice It: File I/O and a Function

What is the effect of the following statements? (answers shown in tiny font
below)
ifstream in_file;
in_file.open("");
string word = "\n";
in_file >> word;
The statements have no effect.
Because there cannot be a file whose name is the empty string, in_file is set to the “failed” state, and no operations have any effect.

What is wrong with this function?


double sum(ifstream in)
{
double total = 0;
double input;
while (cin >> input)
{
total = total + input;
}
return total;
1.
}
in should have been declared as a reference parameter.
2. The input statement should have been in >> input.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Topic 2

1. Reading and writing text files


2. Reading text input
3. Writing text output
4. Parsing and formatting strings
5. Command line arguments
6. Random access and binary files

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading Words and Characters
What really happens when reading a string?
string word;
in_file >> word;

1. Any whitespace is skipped


(whitespace is: '\t' '\n' ' ').
2. The first character that is not white space is added to the string word.
More characters are added until either another white space character
occurs, or the end of the file has been reached.

You can read a single character, including whitespace, using get():


char ch;
in_file.get(ch);
The get method returns the “not failed” condition so:
while (in_file.get(ch)) //reads entire file, char by char
{
// Process the character ch
}
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Lookahead: Reading a Number Only If It Is a Number
You can look at a character after reading it and then put it back.
This is called one-character lookahead. A typical usage: check for
numbers before reading them so that a failed read won’t happen:

char ch;
int n=0; //for reading an entire int
in_file.get(ch);

if (isdigit(ch)) // Is this a number?


{
// Put the digit back so that it will
// be part of the number we read
in_file.unget();

data >> n; // Read integer starting with ch

}
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Functions in <cctype> (Handy for Lookahead): Table 1

Function Accepted Characters


isdigit 0 ... 9
isalpha a ... z, A ... Z
islower a ... z
isupper A ... Z
isalnum a ... z, A ... Z, 0 ... 9

isspace White space (space, tab, newline, and the rarely used carriage
return, form feed, and vertical tab)

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading A Whole Line: getline
The function
getline()
reads a whole line up to the next '\n', into a C++ string. The '\n' is then
deleted, and NOT saved into the string.

string line;
ifstream in_file("myfile.txt");

getline(in_file, line);

NOTE: to read a line into a C-string, the syntax is different.


getline becomes a member function of the stream object:

char cline[100];
in_file.getline(cline, 99); //the int argument
// is the max number of chars to read

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Reading A Whole Line in a Loop: getline

The getline function, like the others we’ve


seen, returns the “not failed” condition.

To process a whole file line by line:

string line;
while( getline(in_file, line)) //reads whole file
{
// Process line
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing a File Line by Line

Here is a CIA file from


http://www.cia.gov/library/publications/the-world-factbook/

Each line has: country name, its population, a newline character.


(And there is some whitespace in there too.)
China 1330044605
India 1147995898
United States 303824646
...
We'll read the file line by line with getline.
To extract the data from a line string, we need to
find out where the name ends and the number starts.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Parsing a File Line using <cctype> Functions

// Locate the first digit of population


int i = 0;
while (!isdigit(line[i])) { i++; }

// Go backwards to find end of country name


int j = i - 1;
while (isspace(line[j])) { j--; }

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Capturing the Line characters into separate strings

Finally, extract the country name and population:


string country_name = line.substr(0, j + 1);
string population = line.substr(i);
There is just one problem: population is stored in a
string, not a number.

You will see in Section 8.4 how to extract the


population number as an int
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Common Error: Mixing >> and getline Input

A problem occurs when a call to getline follows a  >>


• >> does not remove any trailing '\n' from the input stream buffer,
though it does skip a leading '\n' until it finds non-whitespace
• The getline reads only the newline left by the preceding >>,
considering it as the end of an empty line.

• This would happen if the following code were used on a file


that had lines of strings interleaved with lines of numbers:
while(!in.fail())
{
getline(in, country_name); //gets empty strings
in >> population;
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
The Fix for Mixing >> and getline Input

To solve the problem, any trailing newline in the input buffer must be
removed before calling getline

We do this by adding a dummy getline after the >> statement:


string dummy;
while(!in.fail())
{
getline(in, country_name); //gets empty strings
in >> population;
getline(in, dummy); //delete the dangling '\n'
}

There are other alternative remedies for deleting the dangling newline,
including calling in.get() or in.ignore(), but we will leave those
as research exercises for the reader.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Practice It: Line and Character Input
ifstream in;
string str;
char ch;
Write statements to carry out the following tasks (answers shown in tiny font):

Set str to the next line in the input. getline(in, str); The getline function reads the next line from the stream and places it in the string str. The newline is not part of the result.

Set str to the next word in the input. in >> str; The >> operator reads the next word from the stream, removing any whitespace that precedes it.

Set ch to the next character in the in >> ch; Use the >> to get the next character from the stream, skipping any whitespace.

input, skipping any whitespace.

Set ch to the next character in the in.get(ch); Use the get function to get the next character from the stream, even if it is whitespace.

input, but do not skip whitespace.


Fill in the condition to check
whether ch is a digit: isdigit(ch) The cctype header has functions for testing whether a character is a digit, letter, or whitespace.

if (...) { num = ch - '0'; }


Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Topic 3

1. Reading and writing text files


2. Reading text input
3. Writing text output
4. Parsing and formatting strings
5. Command line arguments
6. Random access and binary files

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Writing Text Output

You use the operator >> to send strings and numbers to


an output stream, and the put function for a single char:

string name = "Hello";


int value = 2;
char ch = '!';

ofstream out_file;
out_file.open("output.txt");
if (out_file.fail())
{ return -1; }

out_file << name << " " << value << endl;

out_file.put(ch); Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Formatting Output – Manipulators

To control how the output is formatted,


you use stream manipulators.

A manipulator is an object that:


– is sent to a stream using the >> operator.
– affects the behavior of the stream.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Manipulators to Display a Time such as 09:01

Use setfill when you need to pad numbers with


leading zeroes.
To set the width in which to display, use setw:

strm << setfill('0') << setw(2) << hours << ":“


<< setw(2) << minutes << setfill(' ');

That last setfill(' ') re-sets the fill back to the default
space character.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Stream Manipulators: Table 2
Manipulator Purpose Example Output
out_file << setw(6) << 123 123
setw Sets the field width of the next << endl << 123 << endl << 123
item only. setw(6) << 12345678; 12345678

Sets the fill character for


out_file << setfill('0') <<
setfill padding a field. (default is a setw(6) << 123;
000123
space.)
out_file << left << setw(6)
left Selects left alignment. << 123;
123

right Selects right alignment out_file << right <<


123
(default). setw(6) << 123;
double x = 123.4567;
Selects fixed format for 123.457
fixed out_file << x << endl <<
floating-point numbers. fixed << x; 123.456700

Sets the number of significant


double x = 123.4567;
digits for the default floating- 123.456700
out_file << fixed << x <<
setprecision point format, the number of
endl << setprecision(2) << 123.46
digits after the decimal point x;
for fixed format.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Practice It: Formatting Output
Produce this output to the ofstream strm (answers shown in tiny font):

12.345679 123456789.000000
strm << setprecision(6) << fixed << 12.3456789 << " " << 123456789.0;

(column width is 10):


123
4567
strm << setw(10) << 123 << endl << setw(10) << 4567;

----------|----------
Count: 177
----------|----------
strm << "----------|----------\n"
<< left << setw(10) << "Count:"
<< right << setw(11) << 177
<< "----------|----------\n";

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Floating Point Formats: fixed, scientific, defaultfloat

For money values, choose fixed format with two digits after the decimal point.
out_file << fixed << setprecision(2);

To get the scientific format: a number with one digit before the decimal point
and an exponent. As with the fixed format, the setprecision denotes the
number of digits after the decimal point. :
out_file << scientific << setprecision(3) << 123.456;
produces
1.235e+02

To switch back to the default floating-point format, use the defaultfloat


manipulator introduced in C++ 11:

out_file << defaultfloat;

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Unicode, UTF-8, and C++ Strings
• The Unicode standard encodes alphabets from many languages, and some icons.
• Each Unicode character is 21-bits, written in hexadecimal for humans viewing the code
• For example,
– é (Latin small letter e with acute accent) has the code U+OOE9
– And (high speed train) has the code U+1F684.
• For efficiency, characters in files or transmitted over the Internet are saved at less than
21 bits.
– each Unicode character saved as a sequence of one or more bytes.
• In your programs, you can use the \U prefix followed by 8 hex digits for such
characters:
string e_acute = u8"\U000000e9";
string high_speed_train = u8"\U0001f684";
• Use the find member function to look for a Unicode character:
string message = . . .;
size_t pos = message.find(e_acute);
if (pos != string::npos)
{
// Message has e_acute starting at position pos
}
The size_t type indicates a non-negative position, and string::npos is a special value that
denotes no position.
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Topic 4

1. Reading and writing text files


2. Reading text input
3. Writing text output
4. Parsing and formatting strings
5. Command line arguments
6. Random access and binary files

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Stream Adapters

In order to “extract” numeric information held in a string,


we can adapt the string to have the same interface as
stream types

– then we could use >> and << on strings.

istringstream and ostringstream


are adapters that do just that!

The <sstream> header is required.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
istringstream Reads from a string into other Variables

Declare an istringstream variable named strm allows


parsing data from a string such as
"January 24, 1973"
into numeric variables & other strings resembles cin>>:

istringstream strm;
//read string into the istringstream buffer
strm.str("January 24, 1973");

string month;
int day;
string comma;
int year;
strm >> month >> day >> comma >> year;
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Converting a string to a single int or double

In C++11 and later, to convert a single string to its int or


double value, use the functions stoi and stod:
string year = "1973";
int y = stoi(year);
string mass = “9.85”;
double dmass = stod(mass);

Pre-C++11, write your own function using an istringstream:


int string_to_int(string s)
{
istringstream strm;
strm.str(s);
int n = 0;
strm >> n;
return n;
} Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
The ostringstream Type for Building Strings

An ostringstream can copy text and numbers in a string.


The numbers can be formatted as with files/cout, and
the output operator << works the same.
string month = "January";
int day = 24, year = 1973;
ostringstream strm;
strm << month << " " << day << "," << year;
<< " - "
<< fixed << setprecision(5) << 10.0 / 3;

// .str() “extracts” the stream into a string.


string output = strm.str();

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Converting Numbers to strings without Formatting

If you don’t need formatting, use the C++11 to_string


function to convert numbers to strings:

string output = month + " " + to_string(day) + ", " +


to_string(year);

Here is a function you can use with older versions:

string int_to_string(int n)
{
ostringstream strm;
strm << n;
return strm.str();
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Practice It: istringstream code

Complete the following function:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

/**
Decomposes an address into city, state, and zip.
@param address an address such as "Ann Arbor, Michigan 48109"
@return a vector<string> with city, state, and zip, such as
{ "Ann Arbor", "Michigan", "48109" }
*/
vector<string> decompose(string address)
{
istringstream strm;
strm.str(address);

. . .
}
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Topic 5

1. Reading and writing text files


2. Reading text input
3. Writing text output
4. Parsing and formatting strings
5. Command line arguments
6. Random access and binary files

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line

Depending on the operating system and C++ development


system used, there are different methods of starting a
program:

• Select “Run” in the compilation environment.


• Click on an icon.
• Type the program name at a prompt in a command shell
window (called “invoking the program from the
command line”)
– To open this command shell in Windows, type “cmd” in the Search
box, then click on cmd.exe
– The name of the program you type on the command line will
depend on the IDE you used, but it might be your project name.
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Arguments

In each of these methods, you can pass some information in


via “command line arguments”

These arguments are passed to the main function!

Yes, the cmd shell program calls the main function of your
program.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Arguments Example

The user might type into a command shell window for starting
the program named prog:

prog -v input.dat

prog is the program name (your C++ program).


-v and input.dat are command line arguments

The - in -v typically indicates an option.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
main is set up differently for Command Line Arguments

If your program intends to process command line arguments,


main must be set up differently:

int main(int argc, char* argv[])


{
...
}

argc for argument count: argc =1 if the user typed nothing


after your program name
argv for argument vector (not a “real” vector, but an array of
char pointers, IE, C-strings)
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Arguments: Example Values

Given that the user typed:


argv
prog -v input.dat
0 1 2
int main(int argc, char* argv[])
{
...
}

argc is 3
argv contains these three C strings:
argv[0]: "prog"
argv[1]: "-v"
argv[2]: "input.dat" Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Example Program: Encrypting A File

• Let’s write a program that encrypts a file


• scrambles it so that it is unreadable except to those
who know the decryption method.
• Ignoring 2,000 years of progress in encryption, use a
method familiar to Julius Caesar
• replacing an A with a D, a B with an E, and so on.
• each character c is replaced with c + 3

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Programming: Encrypting A File

We will use the name caesar for our exe, with 3 command line
arguments:
1. An optional -d flag to indicate decrypt instead of encrypt
2. The input file name
3. The output file name

THUS OUR CODE WILL NOT PROMPT THE USER FOR FILE
NAMES!! It will get them as the C-strings in argv[].

For example,
caesar input.txt encrypt.txt
encrypts the file input.txt with the result in encrypt.txt.
caesar -d encrypt.txt output.txt
decrypts the file encrypt.txt and places the result into output.txt.
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Program: Encrypting A File, Part 1
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

/**
Encrypts a stream using the Ceasar cipher.
@param in the stream to read from
@param out the stream to write to
@param k the encryption key
*/
void encrypt_file(ifstream& in, ofstream& out, int k)
{
char ch;
while (in.get(ch))
{
out.put(ch + k);
}
} Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Program: Encrypting A File, Part 2
int main(int argc, char* argv[])
{
int key = 3;
int file_count = 0; // The number of files specified
ifstream in_file;
ofstream out_file;

// Process all command-line arguments


for (int i = 1; i < argc; i++)
{
// The currently processed argument
string arg = argv[i];
if (arg == "-d") // The decryption option
{
key = -3; }

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Program: Encrypting A File, Part 3

else // It is a file name


{
file_count++;
if (file_count == 1) // The first file name
{
in_file.open(arg.c_str());
// Exit the program if opening failed
if (in_file.fail())
{
cout << "Error opening input file “
<< arg << endl;
return 1;
}
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Program: Encrypting A File, Part 4
else if (file_count == 2) // The second file name
{
out_file.open(arg.c_str());
if (out_file.fail())
{
cout << "Error opening output file “
<< arg << endl;
return 1;
}
}
}
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Command Line Program: Encrypting A File, Part 5

// Exit if the user didn't specify two files


if (file_count != 2)
{
cout << "Usage: "
<< argv[0] << " [-d] infile outfile" << endl;
return 1;
}

encrypt_file(in_file, out_file, key);


return 0;
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
How To: Process Text Files, Example Program

Consider this task: Read two country data files, worldpop.txt and
worldarea.txt (supplied with the book’s companion code).

Both files contain the same countries in the same order.

Write a file world_pop_density.txt that contains country names and


population densities (people per square km), with the country names
aligned left and the numbers aligned right:

Afghanistan 50.56
Akrotiri 127.64
Albania 125.91
Algeria 14.18
American Samoa 288.92
. . .
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
How To: Process Text Files, Step by Step, Part 1

• Programs to process files can be complex. Here are the steps,


adapted to the two-file task above:
1. Understand the processing task. The following pseudocode
describes it:
While there are more lines to be read
Read a line from each file.
Extract the country name.
population = number following the country name in the first line
area = number following the country name in the second line
If area != 0
density = population / area
Print country name and density.
2. Determine which files you need to read and write:
– worldpop.txt and worldarea.txt, assumed to be in the same folder as the exe.
3. Choose a method for obtaining the file names. Options:
1. Hard-coding the file names (such as "worldpop.txt")
2. Asking the user
3. Using command-line arguments for the file names
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
How To: Process Text Files, Step by Step, Part 2

4. Choose between line, word, and character-based input.


– We’ll use line input
5. With line-oriented input, extract the required data.
6. Place repeatedly occurring tasks into functions.
• a helper function: extracting the country name and the
value that follows.
– void read_line(string line, string& country, double& value)
• also a function string_to_double to convert population and area
values to floating-point numbers
7. If required, use manipulators to format the output:
out << setw(40) << left << country << setw(15) << right <<
density << endl;

To view the complete program, see the textbook companion code


sec05/popdensity.cpp. It is too long to repeat here.
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Topic 6

1. Reading and writing text files


2. Reading text input
3. Writing text output
4. Parsing and formatting strings
5. Command line arguments
6. Random access and binary files

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Sequential Access and Random Access

Sequential Access: as we’ve been doing


– one input at a time starting at the beginning

Random Access: you can go immediately to any


point in the file, by specifying the location. File
streams support this, but cin/cout do not.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Random Access: put and get positions

The screen has a cursor to show the user where (s)he is typing.
Binary read/write files have two “cursor” positions:
1. the put position – where the next write will go.
2. the get position – where the next read will be.

//Functions: move the get and put positions to a


// given value, counted from the beginning of stream:

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Binary Files

Many files, in particular those containing


images and sounds, do not store information
as text but as binary numbers.

The meanings and positions of these binary


numbers must be known to process a binary file.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Binary Files vs. Text Files

Data is stored in files as sequences of bytes,


just as they are in the memory of the computer.

(Each byte has a value between 0 and 255.)

To store the word “CAB” as ASCII text takes four bytes:


67 65 66 00

The binary data in an image has a special


representation as a sequence of bytes
– but it’s still just a bunch of numbers.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Binary Files: Opening and Reading

To open a binary file for reading and writing, declare an fstream


and use this version of the open method:

fstream strm;
strm.open("img.gif", ios::in | ios::out | ios::binary);

ios::in and ios::out allow us to


read from and write into the same file.

You cannot use the >> operator to read a binary file. Instead,
read a byte by calling get()

int input = strm.get();


//returns a value between 0 and 255.
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Binary File Data

A “real” int, like 1822327,


takes four bytes to store on most systems.

To read a “real” int, you will have to do four reads

– and some arithmetic.

(Or write a function to do this! – see the get_int() function


in the following example…)

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files

The BMP image file format is pretty simple. Other formats such
as PNG, GIF, JPG are far more complex, as they compress
the image to save space.

So we will use BMP file format in the following program. You


can convert any of the above formats to BMP with most
imaging programs.

In fact, we’ll the use the most simple of the


several versions of the BMP format:

the 24-bit true color format

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files: The BMP File Format

The BMP file format for 24-bit true color format:

Each pixel’s (picture element) color is represented


in RGB form – Red, Green, and Blue amounts.

In the file, each pixel is represented as


a sequence of three bytes:

• a byte for the blue value (B)


• a byte for the green amount (G)
• a byte for the red amount (R)

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files: Color Examples

Here are some RGB values stored in a BMP file


(you’ll notice that it’s really stored as BGR):

Cyan (a mixture of blue and green) is the bytes: 255 255 0

Pure red is the values: 0 0 255 (no blue, no green, all red)

Medium gray is 128 128 128 (half of 255 for all three)

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files: The BMP Header

Most binary files start with some information about


the contents called the header.

A BMP file header:


Position Item
2 The size of this file in bytes
10 The start of the image data
18 The width of the image in pixels
22 The height of the image in pixels

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files: Pixel Rows

The image itself is represented as a sequence


of pixel rows (a scan line),
starting with the bottom row in the image.

Each pixel row contains a sequence of BGR bytes.

The end of the row is padded with additional bytes so


that the number of bytes in the row is divisible by 4.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files: Scan Line Example

For example,
if a row consisted of merely three pixels,
one cyan, one red, one medium gray,
there would three padding bytes.
The numbers would be:
255 255 0 0 0 255 128 128 128 x y z

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Processing Image Files: the Negative Task

Now that you know all there is to know about BMP files
for 24-bit true color images, we’ll write code to create the
negative of an input image file.

We create the negative of each pixel by subtracting the R,


G, and B values from 255.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Program to Produce the Negative, Part 1

// sec06/imagemod.cpp
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
/**
Processes a pixel by forming the negative.
@param blue the blue value of the pixel
@param green the green value of the pixel
@param red the red value of the pixel
*/
void process(int& blue, int& green, int& red)
{
blue = 255 - blue;
green = 255 - green;
red = 255 - red;
}
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Program to Produce the Negative, Part 2

/**
Gets an integer from a binary stream.
@param stream the stream
@param offset the offset at which to read the integer
@return the integer starting at the given offset
*/
int get_int(fstream& stream, int offset)
{
stream.seekg(offset);
int result = 0;
int base = 1;
for (int i = 0; i < 4; i++)
{
result = result + stream.get() * base;
base = base * 256;
}
return result;
} Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Program to Produce the Negative, Part 3

int main()
{
cout << "Please enter the file name: ";
string filename;
cin >> filename;
fstream stream;

// Open as a binary file


stream.open(filename.c_str(),
ios::in|ios::out|ios::binary);

// Get the image dimensions


int file_size = get_int(stream, 2);
int start = get_int(stream, 10);
int width = get_int(stream, 18);
int height = get_int(stream, 22);

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Program to Produce the Negative, Part 4

// Scan lines must occupy multiples of four bytes


int scanline_size = width * 3;
int padding = 0;
if (scanline_size % 4 != 0)
{
padding = 4 - scanline_size % 4;
}
if (file_size != start +
(scanline_size + padding) * height)
{
cout << "Not a 24-bit true color image file.“
<< endl;
return 1;
}

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Program to Produce the Negative, Part 5

// Go to the start of the pixels


stream.seekg(start);

// For each scan line


for (int i = 0; i < height; i++)
{
// For each pixel
for (int j = 0; j < width; j++)
{
// Go to the start of the pixel
int pos = stream.tellg();

// Read the pixel


int blue = stream.get();
int green = stream.get();
int red = stream.get();

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Program to Produce the Negative, Part 6

// Process the pixel


process(blue, green, red);

// Go back to the start of the pixel


stream.seekp(pos);

// Write the pixel


stream.put(blue);
stream.put(green);
stream.put(red);
}

// Skip the padding


stream.seekg(padding, ios::cur);
}
return 0;
}
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Practice It: Negative Image Code

1. Modify the imagemod.cpp program to turn the green


values of each pixel to red, the blue values to green, and
the red values to blue for a psychedelic effect.

• Hint: you only need to change one function!

2. If a BMP file stores a 100 × 100 pixel image, with the


image data starting at offset 64, what is the total file size?
• 10,000 bytes
• 30,000 bytes
• 30,064 bytes
• 40,000 bytes
Answer: 30,064 bytes. We need 3 × 100 bytes for each scan line. There is no padding because this number is divisible by 4. The total size = 3 × 100 × 100 + 64 = 30,064 bytes.

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Chapter Summary, Part 1
Develop programs that read and write files.
• To read or write files, use variables of type fstream, ifstream, or
ofstream.
• When opening a file stream, supply the name of the file stored on disk.
ifstream infile;
infile.open(“filename.txt”);
• Read from a file stream with the same operations that you use with cin.
int num;
infile >> num;
• Write to a file stream with the same operations that you use with cout.
ofstream out(“filename.txt”);
out << num;
• Always use a reference parameter for a stream function argument,
because streams are modified as they are read or written
void process_name(ifstream& in_file, double& total)

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Chapter Summary, Part 2

Be able to process text in files.


• When reading a string with the >> operator, the white space between
words is consumed.
• You can get individual characters from a stream and unget the last one.
in_file.get(ch);
if (isdigit(ch))
{
in_file.unget(); // Put the digit back
data >> n; // Read integer starting with ch
}
• You can read a line of input with getline() and then process it further.
There are 2 flavors of the function:
string line;
ifstream in_file("myfile.txt");
getline(in_file, line);

char cstring[100];
in_file.getline(cstring, 99);

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved
Chapter Summary, Part 3

Write programs that neatly format their output.


• #include <iomanip>
• Use the setw manipulator to set the width of the next output.
out << setw(40) << left << country << setw(15) << right <<
density << endl;
• Use the fixed and setprecision manipulators to format floating-
point numbers with a fixed number of digits after the decimal point.
out_file << fixed << x << endl << setprecision(2) << x;

Convert between strings and numbers.


• Use an istringstream to convert the numbers inside a string to
integers or floating-point numbers.
istringstream strm;
strm.str("January 24, 1973");
string month, comma;
int day, year;
strm >> month >> day >> comma >> year;
• Use an ostringstream to convert numeric values to strings.
Big C++ by Cay Horstmann
Copyright © 2018 by John Wiley & Sons. All rights reserved
Chapter Summary, Part 4

Process the command line arguments of a C++ program.


• Programs that start from the command line can receive the name of the
program and the command line arguments in the main function.
int main(int argc, char* argv[])

Develop programs that read and write binary files.


• Open the file with:
fstream strm;
strm.open("img.gif", ios::in | ios::out | ios::binary);
• You can access any position in a random access file by moving the file
pointer prior to a read or write operation.
strm.seekg(position); //read = get
char c = strm.get();
strm.seekp(position); // write = put
position = strm.tellg();
position = strm.tellp();

Big C++ by Cay Horstmann


Copyright © 2018 by John Wiley & Sons. All rights reserved

You might also like