Upload
ralf-porter
View
227
Download
0
Tags:
Embed Size (px)
Citation preview
Streaming and I/0
Chapter 14 D&D
Menu
• Reading/writing text file streams
• Reading/writing string streams
• Command line arguments
Reading/writing text streams
All programs we’ve written so far have read input from standard input, and written output to standard output.
cin, cout, and cerr are C++ streams.
We will now extend this concept to disk files.
To access a disk file, we can open a file stream variable.
#include <iostream>
ifstream infile(“filename”); // input
ofstream outfile(“filename”); // output
fstream inoutfile(“filename”); // in/output
Example (code fragment):
#include <iostream>
...
ifstream input_data;
input_data.open(“myfile”);
int n;
double x;
input_data >> n >> x;
...
Reading strings from streams (code fragment):
#include <iostream>
...
ifstream input_data;
input_data.open(“myfile”);
string s;
input_data >> s; // read word
getline(input_data,s);
...
Reading characters from streams (code fragment):
#include <iostream>
...
ifstream input_data;
input_data.open(“myfile”);
char ch;
input_data.get(ch); // get one character
...
Some other member functions of input streams:
input_stream.peek(ch); // look ahead one char
input_stream.unget(); // put the last char back
Some member functions common to both input and output streams:
input_stream.fail(); // stream op failed
input_stream.eof(); // end of stream reached
input_stream.close();
input_stream.open(“filename”);
Code fragment:
char ch;
ifstream input_stream;
input_stream.open(“mydata”);
input_stream.get(ch); // get one character
if(‘0’<= ch and ch <= ‘9’)
{
input_stream.unget();
int n;
input_stream >> n;
}
input_stream.close();
Output file streams (code fragment):
#include <iostream>
...
ofstream output_data(“myfile”);
output_data << n << “_” << x << “\n”;
output_data.put(ch); // write a single character
output_data.close();
...
Many compilers do not support string parameters to the open/close file function.
...
string s = “myfile”;
ofstream output_data;
output_data.open(s); // sometimes supported
...
output_data.open(s.c_str());
...
member function s.c_str() yields standard C character array
Example paths as strings in Unix:
...
string s = “/home/ugrad/hacker/myfile.dat”;
s = “~hacker/myfile.dat”; // file in home directory
s = “myfile.dat” // file in current directory
On PC:
string s = “C:\\hacker\\myfile.dat”;
// corresponds with file C:\hacker\myfile.dat
File paths
User could be prompted for a file name
cout << “Type filename”;
cin >> s;
File name could be computed or concatenated:
string homedir = “~”;
s = homedir + “myfile” + “dat”;
String Streams
• #include <sstream>
• istringstream: reads from a string
• ostringstream: writes to a string
• Has same interfaces as other stream classes, but allows read/write to a string object.
Code fragment:
...
string input = “January 23, 1955”;
istringstream instr(input); // constructor
string month,comma;
int day,year;
instr >> month >> day >> comma >> year;
...
C++ does the conversion from string to the other types.
#include <sstream>
int string_to_int(string s)
{
istringstream instr(s); // constructor
int n;
instr >> n;
return n;
}
#include <sstream>
string double_to_string(double a)
{
ostringstream outstr; // constructor
outstr << a;
return outstr.str(); // return string equiv.
}
#include <sstream>
string double_to_string(double a)
{
ostringstream outstr; // constructor
outstr << setprecision(5); // 5 places after decimal
outstr << a;
return outstr.str(); // return string equiv.
}
// double_to_string(sqrt(2)) returns “1.41421”;
Command Line Arguments
• There are different ways to start a program:– click on icon– type name of program and return
• the latter is called invoking the program from the command line.
Command Line Arguments• You can include additional arguments on the
command line; e.g., in Unix:
ls -l
make main
g++ -Wall -ansi main.cpp -o main
Usually, we interpret symbols preceded by - as options.
Arguments to C++ main function
int main(int argc, char *argv[])
{
...
}
Example command line:
myprog -v input.dat
In this case
argc == 3
string(argv[0]) == “myprog”
string(argv[1]) == “-v”
string(argv[2]) == “input.dat”
argv[0] always gives the name of the program
argc always >= 1
Number of command line arguments can vary:
myprog -v input.dat
myprog
myprog -i -v input.dat -o output.dat
argv[0] always gives the name of the program
argc always >= 1
What is the value of argc in each of the cases above??
Caesar’s Encryption AlgorithmAlso known as Caesar’s Cipher.
Scrample message via algorithm:– specify integer key k between 0 and 25– to encrypt, shift each input character by k
Example:
k = 3, input = “ABCDEFG”
output = “DEFGHIJ”
To decrypt message, use key = -k
Program arguments
• optional -d flag indicates decryption rather than encryption
• optional encryption key -k<int>
• input file name
• output file name
• Examples:crypt -k11 input.txt encrypt.txt
crypt -d -k11 encrypt.txt output.txt
functions used
usage(string program_name);
open_file_error(string filename);
remainder(int a, int n);
encrypt(char ch, int k);
encrypt_file(ifstream& in, ofstream& out, int k)
string_to_int(string s);
main(int argc, char *argv);
Mainif argc < 3 or argc > 5
usage(string(argv[0]));exit;
for all command line argumentsif -d option, then set decryptif -kn option, set key=n, otherwise key=3if not option, input filename or output filename
openfile (either infile or outfile)if(nfile != 2)
usage(string(argv[0]));exit;
if(decrypt) key = -key;encrypt_file(infile,outfile,key);infile.close();outfile.close();
done;
void usage(string program_name)/* PURPOSE: Prints usage instructions RECEIVES: program_name - the name of this program*/{ cout << "Usage: " << program_name << " [-d] [-kn] infile outfile\n"; exit(1);}
void open_file_error(string filename)/* PURPOSE: Prints file opening error message RECEIVES: filename - the name of the file that could not be opened*/{ cout << "Error opening file " << filename << "\n"; exit(1);}
void encrypt_file(ifstream& in, ofstream& out, int k)/* PURPOSE: Encrypt a file using the Caesar cipher RECEIVES: in - the file to read from out- the file to write to k - the encryption key*/{ char ch; while (in.get(ch)) out.put(encrypt(ch, k));}
char encrypt(char ch, int k)/* PURPOSE: Encrypt a character using the Caesar cipher RECEIVES: ch - the character to encrypt k - the encryption key RETURNS: the encrypted character*/{ const int NLETTER = 26; if ('A' <= ch && ch <= 'Z') return static_cast<char>('A' + remainder(ch - 'A' + k, NLETTER)); if ('a' <= ch && ch <= 'z') return static_cast<char>('a' + remainder(ch - 'a' + k, NLETTER)); return ch;}
int remainder(int a, int n)/* PURPOSE: Compute correct remainder for negative dividend RECEIVES: a - an integer n - an integer > 0 RETURNS: the mathematically correct remainder r such that a - r is divisible by n and 0 <= r and r < n*/{ if (a >= 0) return a % n; else return n - 1 - (-a - 1) % n;}
int string_to_int(string s)/* PURPOSE: Convert a string to an integer, e.g. "3" -> 3 RECEIVES: s - a string representing an integer RETURNS: the equivalent integer*/ { istringstream instr(s); int n; instr >> n; return n;}
int main(int argc, char* argv[]){ bool decrypt = false; int key = 3; int nfile = 0; /* the number of files specified */ ifstream infile; ofstream outfile; if (argc < 3 or argc > 5) usage(string(argv[0]));
for (int i = 1; i < argc; i++) { string arg = string(argv[i]); if (arg.length() >= 2 and arg[0] == '-') /* it is a command line option */ { char option = arg[1]; if (option == 'd') decrypt = true; else if (option == 'k') key = string_to_int(arg.substr(2, arg.length() - 2)); }
else { nfile++; if (nfile == 1) { infile.open(arg.c_str()); if (infile.fail()) open_file_error(arg); } else if (nfile == 2) { outfile.open(arg.c_str()); if (outfile.fail()) open_file_error(arg); } } }
if(nfile != 2) usage(string(argv[0]));
if (decrypt) key = -key;
encrypt_file(infile, outfile, key); infile.close(); outfile.close(); return 0;} // end of main