Streaming and I/0: Chapter 14 D&D
Streaming and I/0: Chapter 14 D&D
Chapter 14 D&D
Menu
Reading/writing text file streams Reading/writing string streams Command line arguments
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); int n; instr >> n; return n; }
// constructor
#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;
the latter is called invoking the program from the command line.
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??
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);
Main
if argc < 3 or argc > 5 usage(string(argv[0])); exit; for all command line arguments if -d option, then set decrypt if -kn option, set key=n, otherwise key=3 if 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