Time due: 9:00 PM Monday, June 5
This is a short homework to give you experience with C++ exceptions.
Try running the program at the end of this writeup, and notice that it occasionally fails to clean up after itself by removing the temporary file it creates.
Copy the program and modify (only) the doSomething function
to ensure that the temporary file is removed even if
displayJpeg throws. Do this by introducing a try-catch in
doSomething.
The solution in problem 1 doesn't scale very well; if the program creates
lots of temporary files in various functions, there would be a lot of
repetitive code. Once again, copy the original program and modify the
doSomething function to ensure that the temporary file is
removed even if displayJpeg throws. This time, use the
Resource Acquisition Is Initialization idiom: Define a TempFile class
to manage the temporary file; the constructor should throw the
FileException if the file can't be created. Notice how this solution
scales up very nicely for programs that create a lot of temporary files.
Once you get the basic modification done, uncomment the lines in doSomething
that actually do something with the temporary file. Do what is necessary
to the TempFile class and to those lines so that clients can use
operator<< and can call member functions like
put, write, and flush on the
underlying file. Do this in such a way that you, the designer of the TempFile
class, don't have to know everything that can done to an ofstream.
Turn in the two .cpp files at the CS 188 submission site.
#include <iostream>
#include <string>
#include <fstream> // defines std::ofstream and std::ifstream
#include <cstdio> // defines std::remove
#include <cstdlib> // defines std::srand and std::rand
#include <ctime> // defines std::time
#include <stdexcept> // defines std::runtime_error
using namespace std;
const char* TEMPFILENAME = "mytempfile";
// To test for failure to create the temporary file in doSomething, change
// this to, for example, "someNonexistentDirectory/mytempfile"
class FileException : public runtime_error
{
public:
FileException(const string& msg) : runtime_error(msg) {}
};
class InvalidJpegException : public runtime_error
{
public:
InvalidJpegException(const string& msg) : runtime_error(msg) {}
};
void doSomething();
void displayJpeg(const string& filename);
int main()
{
srand(time(0));
try
{
doSomething();
cout << "doSomething succeeded." << endl;
}
catch (const FileException& ex)
{
cout << "doSomething aborted with a file error: " << ex.what() << endl;
}
catch (const runtime_error& ex)
{
cout << "doSomething aborted with some runtime error: " << ex.what() << endl;
}
// See if the temp file still exists. Both UNIX and Windows have
// better ways of doing this than by trying to open the file for
// reading, but they aren't part of Standard C++.
ifstream tf(TEMPFILENAME);
if (tf)
cout << TEMPFILENAME << " still exists, which is bad." << endl;
else
cout << TEMPFILENAME << " doesn't exist, which is good." << endl;
}
void doSomething()
{
// Create a temporary file
ofstream tempf(TEMPFILENAME);
if (!tempf)
throw FileException(TEMPFILENAME);
// Do things with the temporary file
// tempf << "Hello!" << endl;
// tempf << 123;
// tempf.put('=');
// tempf.write("123", 3);
// tempf.put('\n');
// tempf.flush();
// Show a pretty picture
displayJpeg("aPrettyPicture.jpg");
// Do more things with the temporary file
// tempf << "Goodbye!" << endl;
// Delete temporary file
tempf.close();
remove(TEMPFILENAME);
}
void displayJpeg(const string& filename)
{
// A real implementation would open the JPEG file
// and display it if it was properly formed, or
// throw an InvalidJpegException if it wasn't.
// For this assignment, we'll just simulate
// occasional failures.
bool isValidJpeg = (rand() % 3 != 0);
if (!isValidJpeg)
throw InvalidJpegException(filename);
cout << "There's a nice picture in " << filename << endl;
}