#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 8_2a.c 8_2b.c 8_2c.c 8_2d.c makefile tst.c tst.cmp tst.in # # To extract the files from this shell archive file simply # create a directory for this file, move the archive file # to it and enter the command # # sh filename # # The files will be extracted automatically. # Note: Do not use csh. # # Archive created: Mon Jul 30 23:12:33 EDT 1990 # echo x - 8_2a.c sed 's/^X//' > 8_2a.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.2 struct name_and_address { char **name; int len; name_and_address() { name = new char*[1]; name[0] = 0; len = 1; } // construct an address using // another as its initializer name_and_address(name_and_address &na) { // init name and pass the buck to op= name = 0; *this = na; } // A helper function to remove the strings. // This is used by assignment and input. void deallocate_name(); // assign one address to another name_and_address& operator=(name_and_address &na) { // delete any strings already there deallocate_name(); // allocate and copy the strings name = new char*[na.len]; for (char **tmpname = name, **tmpnaname = na.name; *tmpnaname; tmpname++, tmpnaname++) { *tmpname = new char[strlen(*tmpnaname) + 1]; strcpy(*tmpname, *tmpnaname); } *tmpname = 0; len = na.len; return *this; } // remove the parts of an address ~name_and_address() { deallocate_name(); } // input and output friend istream& operator>> (istream&, name_and_address&); friend ostream& operator<< (ostream&, name_and_address&); }; void name_and_address::deallocate_name() { if (name) { for (char **svname = name; *svname; ) delete *svname++; delete name; name = 0; } } !EOF! ls -l 8_2a.c echo x - 8_2b.c sed 's/^X//' > 8_2b.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // output the name and address as a series of lines ostream& operator<<(ostream &out, name_and_address &x) { if (x.name) for (char **n = x.name; *n; n++) out << *n << "\n"; out << "\n"; return out; } !EOF! ls -l 8_2b.c echo x - 8_2c.c sed 's/^X//' > 8_2c.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // check a line to make sure it is made // up entirely of spaces and tabs #include static int isblankline(char *buf) { for ( ; *buf; buf++) if (!isspace(*buf)) return 0; return 1; } // Input a series of lines into a name and address. istream& operator>>(istream &in, name_and_address &x) { x.deallocate_name(); x.name = new char*[x.len = 6]; char **n = x.name; for (int curlen = 0; ; curlen++, n++) { // read in a line char buf[256], c; in.get(buf, sizeof(buf)); in.get(c); // zap the newline if (!in) break; // did we reach a blank line? if (isblankline(buf)) break; // reallocate if necessary if (curlen >= x.len) { const int inc = 4; char **svname = x.name; x.name = new char*[x.len + inc]; memcpy((char*)x.name, (char*)svname, x.len * sizeof(char*)); x.len += inc; } // save the line *n = new char[strlen(buf) + 1]; strcpy(*n, buf); } *n = 0; return in; } !EOF! ls -l 8_2c.c echo x - 8_2d.c sed 's/^X//' > 8_2d.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // copy a stream of name_and_address objects #include main(int, char**) { for (;;) { name_and_address a; if (!(cin >> a)) break; if (!(cout << a)) break; name_and_address b = a; if (!(cout << b)) break; } if (!cin.eof()) error("error reading input"); if (cout.bad()) error("error writing output"); return 0; } !EOF! ls -l 8_2d.c echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC ERROR= ../../error.o all: tst tst: tst.c 8_2a.c 8_2b.c 8_2c.c 8_2d.c $(CC) tst.c -o tst $(ERROR) CMP= tst.cmp OUT= tst.out tst.out: tst tst.in ; tst < tst.in > tst.out test: all $(CMP) $(OUT) cmp tst.out tst.cmp @echo test done !EOF! ls -l makefile echo x - tst.c sed 's/^X//' > tst.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include #include #include "8_2a.c" /* struct name_and_address */ #include "8_2b.c" /* operator<<(name_and_address) */ #include "8_2c.c" /* operator>>(name_and_address) */ #include "8_2d.c" /* main() */ !EOF! ls -l tst.c echo x - tst.cmp sed 's/^X//' > tst.cmp << '!EOF!' this is a test of this is a test of how's this? and this? how's this? and this? !EOF! ls -l tst.cmp echo x - tst.in sed 's/^X//' > tst.in << '!EOF!' this is a test of how's this? and this? !EOF! ls -l tst.in # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0