#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 6_5.h 6_5srep.h makefile tst.in tst1.c tst1.cmp # # 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:08:08 EDT 1990 # echo x - 6_5.h sed 's/^X//' > 6_5.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 6.5 // String class with value semantics // and delayed copying on assignment. #ifndef STR_H # define STR_H # include # include #include "6_5srep.h" /* EXPAND */ // a helper typedef for the cast // back into a character pointer typedef const char *charptr; class string { srep *p; char *str() { return p->s; } int len() { return p->size; } public: // string s; string() { p = new srep; } // string s(5); string(int sz) { p = new srep(sz); } // string s("xyz"); string(char *s) { p = new srep(s); } // string s = string ... string(string &s) { s.p->refcnt++; p = s.p; } ~string() { if (--p->refcnt == 0) delete p; } // s = string string& operator=(string &s) { s.p->refcnt++; if (--p->refcnt == 0) delete p; p = s.p; return *this; } // s = "xyz"; string& operator=(char *s) { if (p->refcnt > 1) { p->refcnt--; p = new srep(s); } else *p = s; return *this; } // char *c = s; const char *operator charptr() { return str(); } // x = s[3]; // s[3] = 'x'; char &operator[](int i) { if (i < 0 || i >= len()) return str()[0]; else return str()[i]; } friend ostream& operator<<(ostream&, string&); friend istream& operator>>(istream&, string&); friend int operator==(string &x, char *s) { return strcmp(x.str(), s) == 0; } friend int operator==(string &x, string &y) { return strcmp(x.str(), y.str()) == 0; } friend int operator!=(string &x, char *s) { return strcmp(x.str(), s) != 0; } friend int operator!=(string &x, string &y) { return strcmp(x.str(), y.str()) != 0; } }; inline ostream& operator<<(ostream &s, string &x) { return s << x.str(); } inline istream& operator>>(istream &s, string &x) { char buf[1024]; s >> buf; x = buf; return s; } #endif /* STR_H */ !EOF! ls -l 6_5.h echo x - 6_5srep.h sed 's/^X//' > 6_5srep.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // define the class to manage the // actual character string class srep { friend class string; char *s; int size; int refcnt; srep() { refcnt = 1; s = new char[size = 1]; s[0] = 0; } srep(int sz) { refcnt = 1; s = new char[size = sz]; s[0] = 0; } srep(char *x) { refcnt = 1; s = new char[size = strlen(x) + 1]; strcpy(s, x); } srep& operator=(char *x) { delete s; refcnt = 1; s = new char[size = strlen(x) + 1]; strcpy(s, x); return *this; } ~srep() { delete s; } }; !EOF! ls -l 6_5srep.h echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC CFLAGS= ERROR= ../../error.o all: tst1 tst1: tst1.c 6_5.h 6_5srep.h makefile $(CC) $(CFLAGS) tst1.c -o tst1 $(ERROR) CMP= tst1.cmp OUT= tst1.out tst1.out: tst1 tst.in ; tst1 < tst.in > tst1.out test: all $(OUT) $(CMP) cmp tst1.out tst1.cmp echo tests done !EOF! ls -l makefile echo x - tst.in sed 's/^X//' > tst.in << '!EOF!' hello there again done !EOF! ls -l tst.in echo x - tst1.c sed 's/^X//' > tst1.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include <6_5.h> #include main() { string x[100]; cout << "here we go\n"; for (int n = 0; cin>>x[n]; n++) { string y; if (n == 100) error("too many strings"); cout << (y = x[n]) << "\n"; if (y == "done") break; } cout << "here we go back again\n"; for (int i = n-1; 0 <= i; i--) cout << x[i] << "\n"; return 0; } !EOF! ls -l tst1.c echo x - tst1.cmp sed 's/^X//' > tst1.cmp << '!EOF!' here we go hello there again done here we go back again again there hello !EOF! ls -l tst1.cmp # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0