Fall 2006 |
Clay Shields |
Parker's Implacable Camera, Co.Assigned: November 21stProgram source code due: December 5th |
UpdateI am planning on testing your code by using a main function that tests the various methods in the Image class and Photo_set class. So it isn't a surprise (and to catch any bugs I might have in my main ahead of time) I am making this main available to you. You can download the file named grading-main.cc. You can put this in your code and it will to some more thorough test than the other mains, and print out a score out of 75.You can also copy the grading-main.cc file to your account on seva by typing: cp ~clay/grading-main.cc ~/ once it is on your account, assuming that your file is named picco-ll.cc you can insert it into your code easily by doing this: cat grading-main.cc >> picco-ll.cc That will append it to the end of the picco-ll.cc file. If you get any error messages that you think are incorrect, let me know what the message was and send me your code.
Parker's Implacable Camera, Co. - Old School, with pointersOn a recommendation from Sid, Parker of Parker's Implacable Camera Co. (Motto - "Getting all the pictures of your wedding day, even the ones you don't want. As seen on Springer!") has contacted you about coming up with a program that allows customers to look through a list of photos and select which ones they would like to order. To help you do this, an outline of a program has been provided for you. You can download this file here, or copy it to your account on seva by typing: cp ~clay/picco-ll-clean.cc ~/ You can run a working version of this program by typing: ~clay/picco-ll but you won't notice any difference from the last project. Yes, this is the same project as before, but this time with linked lists replacing where we used vectors last time. The Image class will be made into a self-referential class, and the photo_set class will use the changed Image class. I have broken this up into steps to help you, much like the last project. Step 1 First, we are going to make the Image class self referential by adding a pointer to another Image in side of it. Here is what the class definition looks like, minus what you need to add:
class Image{ friend ostream &operator<<(ostream &, Image); friend istream &operator>>(istream&, Image &); public: // Default constructor Image(); // Constructor with initial values Image(string, string); // Name observer string get_name(); // Tags observer string get_tags(); //Accesor for the tags. void set_tags(string); // Acessor for the name void set_name(string); //nextImage observer Image * get_next_image(); //nextImage accessor void set_next_image(Image *); // Image destructor ~Image(); private: string image_name; string image_tags; Image * nextImage; }; // Default constructor Image::Image(){ // MAKE THIS WORK } // Initializing Constructor // Initialize things nicely Image::Image(string initial_name, string initial_tags){ // MAKE THIS WORK } // Return the image name string Image::get_name(){ return image_name; } // Return the tags string Image::get_tags(){ return image_tags; } // Change the tags void Image::set_tags(string new_tags){ image_tags = new_tags; } // Change the name void Image::set_name(string new_name){ image_name = new_name; } //Find out what the next image is Image * Image::get_next_image(){ // MAKE THIS WORK } // Set the next image to what is passed as a parameter void Image::set_next_image(Image * new_image){ // MAKE THIS WORK } Image::~Image(){ // MAKE THIS WORK } ostream &operator<<(ostream & output, Image i){ output << i.image_name << " " << i.image_tags; }; istream &operator>>(istream& input, Image & i){ input >> i.image_name; input.ignore(); getline(input,i.image_tags); i.nextImage = NULL; };Your first task is to fill in the code above. To make sure it works, test it with the main function below. This function is commented out in the file provided with C style comments. Note that looking at these main functions is a good way to see how the objects work.
int main(){ // A small main program to test the image class // Create a new image Image test_image("DSCF0020","Bride, groom, close up"); // make sure the observors work cout << "Testing observors:" << endl; cout << "This should say DSCF0020: " << test_image.get_name() << endl; cout << "This should say 'Bride, groom, close up': " << test_image.get_tags() << endl; // make sure the accesor for the tags works: cout << "Testing accessors:" << endl; test_image.set_tags("Bride, groom, close up, pimple"); cout << "This should say 'Bride, groom, close up, pimple': " << test_image.get_tags() << endl; // make sure the friend functions work as well cout << "The next line should say 'DSCF0020 Bride, groom, close up, pimple':" << endl; cout << test_image << endl; // now test the input operator cout << "At the prompt, please type - D01 Bride, groom, family:" << endl; cin >> test_image; cout << "The next line should say 'D01 Bride, groom, family':" << endl; cout << test_image << endl; cout << test_image.get_tags() << endl; // Some new tests to make sure that the nextImage stuff works cout << "Testing pointer part" << endl << endl; Image * testPtr = new Image("DSC099.JPG","Grooms Father making a toast"); cout << " The next line should say: DSC099.JPG Grooms Father making a toast" << endl; cout << *testPtr << endl; Image * otherPtr = new Image("DSC100.JPG","Everyone toasting"); testPtr->set_next_image(otherPtr); cout << "The next line should say DSC100.JPG Everyone toasting" << endl; cout << * testPtr->get_next_image() << endl; } Step 2 Once you have that working, it is time to do the Photo_set class. I have provided an outline of the class below:
class Photo_set{ public: // Default constructor for empty photo set Photo_set(); // Method that loads the Image names and tags from a file void load_set(string source_file); // Show a numbered list of images void display_images(); // return a copy of one of the images in the set Image extract_image(int); // Add an image to the set void add_image(Image); // Return the number of images int number_of_images(); // Return the name of the set string get_name(); // Set the name of the photo set void change_set_name(string); // Save the photo set into a file void save_set(string); // Destroy the photo set ~Photo_set(); private: string set_name; Image * images; // A small method to add a dynamically created image to the list // Here because we want to separate out operations that happen // in more than one method. void add_image_to_list(Image *); // A small method to delete the list // Again, used in different public methods. void clear_list(); }; // A default constructor that makes a blank set Photo_set::Photo_set(){ // MAKE THIS WORK } // A method that is given the name of a file and reads // the information from the file. // The file has the format: // One line with the set name // Many lines, each with one image on them // Clear the old list when loading a new one. // The private method clear_list is good for this void Photo_set::load_set(string filename){ // MAKE THIS WORK } // Display a numbered list of images contained in the photo set // Start with the name, so we know which set it is // Notice that numbering starts at 1, because we don't want to // confuse grandma void Photo_set::display_images(){ // MAKE THIS WORK } // Given an integer that represents a number from the display_images // list, return a copy of that image // It does not remove the extracted image from the list // I test to make sure the image number is in range; // if it isn't, the method prints an error message and exits. // if it is out of range it will crash anyway. There are better // ways of handling this, but they are more complicated than we care about Image Photo_set::extract_image(int image_number){ // MAKE THIS WORK } // Add an image to the set // This is tricky because we need to only add dynamically created // image objects; we can't add the parameter passed directly, as it is // goes out of scope when the method ends void Photo_set::add_image(Image new_image){ // MAKE THIS WORK } // Return the number of images // This is just the size of the vector int Photo_set::number_of_images(){ // MAKE THIS WORK } // Get name simply returns the name of the set string Photo_set::get_name(){ return set_name; } // Set the name of the photo set void Photo_set::change_set_name(string new_name){ set_name = new_name; } // Save the photo set into a file of the specified name // It should save the set name and all the images void Photo_set::save_set(string filename){ // MAKE THIS WORK } // This is a private function that will add a pointer to a file to the // image list. It needs to add to the end to keep the images ordered // If you add to the front, they will be reversed void Photo_set::add_image_to_list(Image * new_image){ // MAKE THIS WORK } // This is a private function that will clear the list and // set images to NULL void Photo_set::clear_list(){ // MAKE THIS WORK } // Destroy the photo set // For this we need to delete all the items on the list // since they live outside the object. If the object goes away without // deleting them, we get a memory leak. Photo_set::~Photo_set(){ // MAKE THIS WORK }To help you with this, I have provided a main section that you can use to test the different methods in the class. This main is broken down into smaller steps. You can use it to write and test different methods a few at a time in order. Doing so will make your life easier. /////////////////////////////////////////////////////////////////////////// // A main function to test that the photo_set class works // This is done is steps to test different parts of the program. int main(){ // This section is set up so you can add methods one or two at a time // and then just change where the return 0 happens. // It should be easier to work on and test a few things at a time // The first thing we test is the add_image method and the // display_images method. I used the private add_image_to_list // method in my add_image, so that gets tested too Photo_set test_set; Image test_image ("DSC901.JPG","Cows"); cout << "Adding image"; test_set.add_image(test_image); cout << endl << "Done" << endl << "The next line should read:" << "1 DSC901.JPG Cows"<< endl; test_set.display_images(); // Remove or comment out the line below when the above portion works return 0; // Now add some more images to better test the adding method and the printing // since adding can go wrong cout << "Adding image 2"; test_image.set_name("DSC902.JPG"); test_image.set_tags("Brown cows"); test_set.add_image(test_image); cout << ".....done" << endl << "Adding image 3"; test_image.set_name("DSC903.JPG"); test_image.set_tags("White cows"); test_set.add_image(test_image); cout << ".....done" << endl << "Adding image 4"; test_image.set_name("DSC904.JPG"); test_image.set_tags("Spotted cows"); test_set.add_image(test_image); cout << ".....done" << endl; cout << endl; cout << "There should be four cow pictures below, in order by name" << endl; test_set.display_images(); cout << endl; // Uncomment the line below until the above portion works // return 0; // Test the number_of_images method cout << "There should be 4 images, and there are: " << test_set.number_of_images() << endl; cout << endl; // Uncomment the line below until the above portion works // return 0; // test the extract image method // and the display again, to make sure it isn't removed Image result = test_set.extract_image(2); cout << "The next line should read: DSC902.JPG Brown cows" << endl; cout << result << endl; cout << endl; cout << "There should be four cow pictures below, in order by name" << endl; cout << "If there are fewer, extract removed from the list instead" << endl; cout << "returning a copy of the desired image." << endl; test_set.display_images(); cout << endl; // Uncomment the line below until the above portion works // return 0; // test the save_set // You can look at the file named "test-ouput" in pico to make sure that // it is correct. It should say "Cow collection" then the same four images // we saw before test_set.change_set_name("Cow collection"); test_set.save_set("test_output"); // Uncomment the line below until the above portion works // return 0; // Test the load_set // We should be able to load the set we just saved Photo_set another_set; another_set.load_set("test_output"); cout << "The set below should show our 4 cows" << endl; another_set.display_images(); cout << endl; // Uncomment the line below until the above portion works // return 0; // Load again to make sure the list is cleared another_set.load_set("test_output"); cout << "The set below should show our 4 cows. If there are more, " << "you forgot to clear the list before loading new things in." << endl; another_set.display_images(); cout << endl; cout << "If all these worked, the main from the last project should"; cout << "work now, without change." << endl; //return 0; } Step 3 Now you need to make a main that does what the last one did. Hey, guess what, because of the object-oriented design, no changes are needed. You are done. What to turn inInclude the following header in your source code. // // Project 5 // Name: <your name> // E-mail: <your e-mail address> // COSC 071 // // In accordance with the class policies and Georgetown's // Honor Code, I certify that I have neither given nor // received any assistance on this project with the // exceptions of the lecture notes and those items noted // below. // // // Description: <Describe your program> //
You will submit your To submit your program, make sure there is a copy of the source code on your account on seva. You may name your program what you like - let's assume that it is called picco-ll.cc. To submit your program electronically, use the submit program like we did in Homework 2 and Project 1, 2, and 3, but with the command: submit -a p5 -f picco.cc
|