<-- back to index...

CSE 143 : 6 Jan 2000 : With solutions


Call by reference

Call by reference allows us to write functions that modify their parameters without using pointers explicitly:

void shuffle(int a, int *b, int &c) { int temp = a; a = *b; b = &temp; c = a + *b + temp; } int main() { int a = 1; int b = 2; int c = 3; shuffle(a, &b, c); cout << a << ',' << b << ',' << c << endl; }

Note: the above prints 1,2,4

File I/O

You should have covered C-style file I/O at the end of 142. Here's a refresher, plus the new and better C++ way:

/* C way */ #include <stdio.h> int main() { FILE *infile, *outfile; char c; /* Open filehandles */ infile = fopen("in.txt", "r"); outfile = fopen("out.txt", "w"); /* Test if open successful */ if (infile != NULL && outfile != NULL) { /* read until EOF */ while ( fscanf(infile, "%c", &c) != EOF ) { /* writing the character each time */ fprintf(outfile, "%c", c); } } /* Close file handles */ fclose(infile); fclose(outfile); } // C++ way: does NOT do the same thing as the above #include <iostream.h> #include <fstream.h> int main() { // Open file streams. Notice "constructor" syntax ifstream in("in.txt"); ofstream out("out.txt"); char word[200]; if (!in) { cout << "Unable to open input file." << endl; return 1; } if (!out) { cout << "Unable to open output file." << endl; return 1; } // Can you guess what the following does? while (in >> word) out << word << '\n'; }

Answer: the first program merely copies one file, character by character, to another. The second file reads in a file, one word at a time, and then prints those words to another file with newlines between them.

Review

For the first assignment, we'll be picking up right where 142 left off. You must know C pretty well by now. Here's some refresher material:

Strings

Recall the following C string functions:

Remember that C strings are zero-terminated; that is, the end of a C string is marked by the special character '\0'. Can you write a plausible implementation of strlen()? strcpy()?

There are several ways to do these. Below are the idiomatic C ways to do things, followed by clearer (better) versions:

/* Idiomatic C way */ int strlen(char *str) { int i = 0; while (*str++) i++; return i; } void strcpy(char *target, char *source) { while (*target++ = *source++); } /* Using clearer style (with an optimizing compiler, these should compile to code equivalent to the above). */ int strlen(char *str) { int i=0; while (*str != '\0') { str++; i++; } return i; } void strcpy(char *target, char *source) { while (*source != '\0') { *target = *source; target++; source++; } /* Must append null, since null char assignment does not happen */ *target = '\0'; }

Can you rewrite the following C++ program to pick the word in the file in.txt that comes first in alphabetical order, and print it to standard output?

One solution:

#include <iostream.h> #include <fstream.h> #include <stdio.h> int main() { ifstream in("in.txt"); char word[200]; char first[200]; in >> first; // Initialize first with first word while (in >> word) { // If first comes after word, set first to word if (strcmp(first, word) > 0) strcpy(first, word); } cout << first; return 0; }

Structs (old and new)

A struct allows you to define a type with named pieces, sometimes called members or fields.

typedef struct { /* C way */ int id; char name[200] } Student; struct Student { // C++ way int id; char name[200] };

Structs can be nested. Try rewriting the above struct so that the name, instead of being a single char array, is a struct with first and last name members. Then, initialize it to your personal data.

struct Name { char first[100]; char last[100]; }; struct Student { int id; Name name; }; /* Declaration; initialize this: */ Student s = {10, { "Keunwoo", "Lee" } };

How would you print out the name and ID with a comma between them?

cout << s.name.first << ' ' << s.name.last << ',' << s.id;

Optional homework: Write a program that:

All the pieces, except arrays of structs, are in the notes above. It should take you about an hour at most. I will post a solution on my web page in a couple of days.

Here's one possible solution. I recommend you paste this into a syntax-highlighting editor (e.g. Visual C++) in order to improve readability, and compile it if you don't have your own solution. Try it on this sample input.

#include <iostream.h> #include <fstream.h> #include <stdio.h> const int MAX_NAME_LENGTH = 256; const int NUM_STUDENTS = 10; const char INFILE_NAME[] = "in.txt"; struct Name { char first[MAX_NAME_LENGTH]; char last[MAX_NAME_LENGTH]; }; struct Student { int id; Name name; }; int main() { Student students[NUM_STUDENTS]; int first; // Index of first student in alphabetical order // Open input stream ifstream in(INFILE_NAME); // Flag to signal: is first time through loop? bool is_first = true; for (int i=0; i<NUM_STUDENTS; i++) { // Assign unique ID (the loop index will serve fine) students[i].id = i; // Read current student's name in >> students[i].name.first; in >> students[i].name.last; // Get first student if (is_first) { // If this is the first iteration, just blindly assign first = i; is_first = false; } else { // Otherwise, if the current student's last name is before // our stored first student, set the first student to the // current. if (strcmp(students[first].name.last, students[i].name.last) > 0) first = i; } } // Finally, print out the first student (in reality, you would probably // make this into a function for convenience). cout << students[first].name.first << ' ' << students[first].name.last << ',' << students[first].id; return 0; }
Keunwoo Lee
Last modified: Mon Jan 10 21:55:49 PST 2000