370 likes | 445 Views
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.
E N D
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 Algorithm Also 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);
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