HW4: I/O

CS 321 Homework, Dr. Lawlor, 2006/03/29.  Due Wednesday, April 5 at 5pm.

Here's a series of problems regarding the handling of I/O.  You're expected to turn in each problem by giving it a particular name inside of netrun, which you'll need to sign up for online if you haven't already.

NetRun has online grading, so you're done once you see this response:

Grading

CS Problem 321_HW4_1 output looks OK!

Note that you MUST give the programs the correct name, or they won't get graded! Also, the LAST program you've run under that name before the deadline is the one I'll take!  

Hint: read the lecture notes.
  1. Name as "321_HW4_1".  Read each word of the input (std::cin) into v, stopping each read at any spaces and skipping whitespace.  So the input string "foo  bar" would be separated into "foo" and "bar". Be sure to break out of the loop when you hit the last word, or your program will run forever ("Killing Program: Ran too long").  (Executable NetRun link)
    std::string s;
    std::vector<std::string> v;
    while (1) {
    /* Read the next word from std::cin here.
    Stop reading when you hit white space.
    Break once there's nothing more to read. */
    ???
    v.push_back(s);
    }
    for (unsigned int i=0;i<v.size();i++)
    std::cout<<"The "<<i<<"th string read is '"<<v[i]<<"'\n";
    return v.size();
  2. Name as "321_HW4_2".  Read strings from the input, but stop only when you hit a semicolon ';' or period '.' character. So "To be; or not." would be separated into "To be" and " or not". (Executable NetRun link)
    int foo(void) {
    std::string s;
    std::vector<std::string> v;
    while (1) {
    /* Read the next word from std::cin here.
    Stop reading when you hit at semicolon or period,
    and do NOT include the semicolon or period in s.
    Break once there's nothing more to read. */
    ???
    v.push_back(s);
    }
    for (unsigned int i=0;i<v.size();i++)
    std::cout<<"The "<<i<<"th string read is '"<<v[i]<<"'\n";
    return v.size();
    }
  3. Name as "321_HW4_3".  Read big-endian 32-bit binary integers from the input.  Because web browsers have a hard time dealing with binary data in text boxes, this example uses binary data that's also valid ASCII.  So if you get a value like 2021161009 for the first integer (the four bytes that are in ASCII "xxx1"), you're actually doing the right thing. (Executable NetRun link)
    int foo(void) {
    std::vector<int> v;
    while (1) {
    int i;
    /* Read big-endian binary ints from the standard input here.
    Stop reading when no more ints are available. */
    ???
    v.push_back(i);
    }
    for (unsigned int i=0;i<v.size();i++)
    std::cout<<"The "<<i<<"th int read is '"<<v[i]<<"'\n";
    return v.size();
    }

  4. Name as "321_HW4_4".  Here's a complicated class, with lots of different stuff inside it.  Write the code to store the class to disk, and load it back from disk (writeDudes and readDudes).  You can choose any I/O method (C++ iostreams, C FILE, UNIX write) and any file format you like (e.g., ASCII, binary, or a mix).  But do beware that all the strings might contain funny characters, so getting terminator characters to work properly will probably be a nightmare.  (Executable NetRun link)
    struct dude {
    public:
    std::string name;
    std::string address;
    double karma;
    std::vector<std::string> blogs;
    };

    /* Make up a random string for testing */
    std::string makeString(int length) {
    std::string s="";
    for (int i=0;i<length;i++) {
    if (length<20) s+='A'+(rand()%24);
    else if ((rand()&0xff)<5) s+='\n';
    else s+=32+(rand()%(127-32));
    }
    return s;
    }

    /* Make up some random dude objects for testing */
    std::vector<dude> makeDudes(void) {
    std::vector<dude> dudes;
    int i,n=2+(rand()&3);
    for (i=0;i<n;i++) {
    dude f;
    f.name=makeString(6);
    f.address=makeString(150);
    f.karma=rand()&511;
    for (int j=0;j<(rand()&3);j++)
    f.blogs.push_back(makeString(18));
    dudes.push_back(f);
    }
    return dudes;
    }
    void printDude(dude &f) {
    std::cout<<"Dude:\n";
    std::cout<<" name='"<<f.name<<"'\n";
    std::cout<<" address='"<<f.address<<"'\n";
    std::cout<<" kharma="<<f.karma<<"\n";
    for (unsigned int i=0;i<f.blogs.size();i++)
    std::cout<<" blog='"<<f.blogs[i]<<"'\n";
    }
    void printDudes(std::vector<dude> &dudes) {

    for (unsigned int i=0;i<dudes.size();i++) printDude(dudes[i]);
    }

    /* Write and read all these dude objects to/from this disk file.
    You MUST write both these routines, and CANNOT change any other routine,
    (in particular, you must not change foo!)
    */
    void writeDudes(const char *toFile,std::vector<dude> dudes) {}
    void readDudes(const char *fromFile,std::vector<dude> &dudes) {}

    int foo(void) {
    srand(read_input());

    /* Make up some dudes, and write them to disk */
    writeDudes("dudes.bin",makeDudes());

    /* Read the dudes we just wrote */
    std::vector<dude> dudes;
    readDudes("dudes.bin",dudes);
    if (dudes.size()==0) std::cout<<"Woa--I didn't read any dudes?\n";
    printDudes(dudes);
    return 0;
    }


Open-Ended Problems

Half your homework grade is to complete half of the open-ended problems (miniprojects) throughout the semester.  I'll try to offer at least one open-ended problem with each week's homework.  If you complete more than half of the open-ended problems through the semester, I'll take the half with the highest grades. 

Turn in open-ended problems by naming the source code "problem.cpp" and submitting it on blackboard as HW4_O.  HW4_O is due Monday, April 10 at 5pm.
  1. Write a program that reads any existing image file format.  There exist formats like PPM that have an ASCII header, like Targa that have a simple binary header, and like JPEG or PNG that have a really complicated binary header.  All you have to do is print out the image's size, in pixels wide by pixels high--you don't even have to read the image data.