#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 6_3a.c 6_3b.c 6_3c1.c 6_3c2.c 6_3d.c 6_3st1.h makefile substr.h tst.c tst1.c tst1.cmp tst2.cmp tst4.c # # 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:07:52 EDT 1990 # echo x - 6_3a.c sed 's/^X//' > 6_3a.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // substring operator, second version // exercise 6.3 substring string::operator()(int index, int count) { char *s1 = p->s; int s1len = strlen(s1); // convert left index, if necessary if (index < 0) index += s1len; // left index past end of string else if (index >= s1len) { substring sst(s1+s1len, 0, this); return sst; } // convert count, if necessary int numleft = s1len - index; if (count > numleft || count < 0) count = numleft; // copy the substring substring sst(s1+index, count, this); return sst; } !EOF! ls -l 6_3a.c echo x - 6_3b.c sed 's/^X//' > 6_3b.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // create a string from a substring string::string(substring& sst) { p = new class srep; p->s = new char[ sst.len + 1 ]; strncpy(p->s, sst.s, sst.len); p->s[sst.len] = '\0'; p->n = 1; } !EOF! ls -l 6_3b.c echo x - 6_3c1.c sed 's/^X//' > 6_3c1.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Assign something to a substring, version 1 // Only allow equal length assignments. #include #include // substring = char* substring& substring::operator=(char *cp) { if (len != strlen(cp)) error("lengths must match for assignment"); // disconnect string if (str->p->n > 1) { str->p->n--; struct srep *oldp = str->p; str->p = new struct srep; str->p->s = new char[strlen(oldp->s) + 1]; strcpy(str->p->s, oldp->s); str->p->n = 1; s = str->p->s + (s - oldp->s); } if (len > 0) memcpy(s, cp, len); return *this; } !EOF! ls -l 6_3c1.c echo x - 6_3c2.c sed 's/^X//' > 6_3c2.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // substring = string substring& substring::operator=(string& st) { return *this = st.p->s; } // substring = substring substring& substring::operator=(substring& sst) { string st = sst; return *this = st; } !EOF! ls -l 6_3c2.c echo x - 6_3d.c sed 's/^X//' > 6_3d.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // assign a string to a substring, version 2 // handling mismatches in lengths #include #include // assign a character string to a substring substring& substring::operator=(char *cp) { // disconnect string if (str->p->n > 1) { str->p->n--; struct srep *oldp = str->p; str->p = new struct srep; str->p->s = new char[strlen(oldp->s) + 1]; strcpy(str->p->s, oldp->s); str->p->n = 1; s = str->p->s + (s - oldp->s); } int stlen = strlen(cp); // same size, simply copy data if (len == stlen) { if (len > 0) memcpy(s, cp, len); } // expand or shrink data area else { // allocate the new data segment char *sps = str->p->s; const int s1len = s - sps; const int s3len = strlen(sps) - len - s1len; char *newdata = new char[s1len + stlen + s3len + 1]; // copy in the data if (s1len > 0) memcpy(newdata, sps, s1len); if (stlen > 0) memcpy(newdata + s1len, cp, stlen); if (s3len > 0) memcpy(newdata + s1len + stlen, s + len, s3len); newdata[s1len + stlen + s3len]= '\0'; // replace pointers delete str->p->s; str->p->s = newdata; s = newdata + s1len; len = stlen; } return *this; } !EOF! ls -l 6_3d.c echo x - 6_3st1.h sed 's/^X//' > 6_3st1.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ friend class substring; string(substring&); substring operator()(int i, int len = -1); !EOF! ls -l 6_3st1.h echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC ERROR= ../../error.o CFLAGS= all: tst1 tst2 tst4: tst4.c $(CC) +i tst4.c -o tst4 tst1: tst1.c 6_3a.c 6_3b.c 6_3c1.c 6_3c2.c substr.h ../6.1dir/strclass.h 6_3st1.h $(CC) $(CFLAGS) -D_6_3 -I../6.1dir tst1.c -o tst1 $(ERROR) tst2: tst1.c 6_3a.c 6_3b.c 6_3d.c substr.h ../6.1dir/strclass.h 6_3st1.h $(CC) $(CFLAGS) -D_6_3 -DTSTD -I../6.1dir tst1.c -o tst2 $(ERROR) CMP= tst1.cmp tst2.cmp OUT= tst1.out tst2.out tst1.out: tst1 ; tst1 > tst1.out tst2.out: tst2 ; tst2 > tst2.out test: all $(OUT) $(CMP) cmp tst1.out tst1.cmp cmp tst2.out tst2.cmp echo tests done !EOF! ls -l makefile echo x - substr.h sed 's/^X//' > substr.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // , exercise 6.3 // auxiliary substring class for class string #ifndef SUBSTR_H # define SUBSTR_H class substring { friend class string; char *s; // ptr to substring start int len; // length of substring string *str; // ptr to parent string substring(char* chptr, int stlen, string* stptr) { s = chptr; len = stlen; str = stptr; } public: // Do not define a constructor // without any initialization. // If we did, it would look like this: // substring(); // substring x; // do define the constructor // for use with initialization: substring(substring& sst) // substring x = ... { s = sst.s; len = sst.len; str = sst.str; } substring& operator=(substring &); substring& operator=(string &); substring& operator=(char *); friend ostream& operator<< (ostream& out, substring& sst) { string st = sst; return out << st; } }; // DELETE #include <6_3a.c> // DELETE #include <6_3b.c> // DELETE #ifdef TSTD // DELETE #include <6_3d.c> // DELETE #else // DELETE #include <6_3c1.c> // DELETE #endif // DELETE #include <6_3c2.c> // DELETE #endif /* SUBSTR_H */ !EOF! ls -l substr.h 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 class string { struct srep { char *s; int n; }; srep *p; public: string(char *); // string x = "abc" string(); // string x; string(string&); // string x = string ... string& operator=(char *); string& operator=(string &); ~string(); char& operator[](int i); friend class substring; string(substring&); }; class substring { friend class string; char *s; int len; string *str; substring(); // substring x; substring(substring&); // substring x = substring ... public: substring(char* chptr,int len,string* stptr); substring& operator=(substring &); substring& operator=(string &); }; string::string(substring& sst) { p = new srep; p->s = new char[ sst.len + 1 ]; strncpy(p->s, sst.s, sst.len); p->s[sst.len] = '\0'; p->n = 1; } !EOF! ls -l tst.c 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 #include main() { string w = "abcdefghijklmnop"; string x = "0123456789wxyz"; cout << "w=" << w; cout << "x=" << x; cout << "w(5)=" << w(5); string y = w(5,3); cout << "y=w(5,3)=" << y; cout << "x(-5)=" << x(-5); cout << "x(-5,3)=" << x(-5,3); cout << "x(0)=" << x(0); cout << "x(0,2)=" << x(0,2); cout << "x(11,8)=" << x(11,8); cout << "x(8,4)=" << x(8,4); cout << "\nx=" << x; x(2,2) = string("$$"); cout << "x(2,2)='$$'\n"; cout << "x=" << x << "\n"; string z = x; cout << "\nz=" << z << "x=" << x; x(8,4) = string("WXYZ"); cout << "x(8,4)='WXYZ'\n"; cout << "x=" << x << "z=" << z << "\n"; #ifdef TSTD z = x; cout << "\nz=" << z << "x=" << x; x(2,6) = string("QQQQ"); cout << "x(2,6)='QQQQ'\n"; cout << "x=" << x << "z=" << z << "\n"; z = x; cout << "\nz=" << z << "x=" << x; x(8,2) = string("!!!!"); cout << "x(8,2)='!!!!'\n"; cout << "x=" << x << "z=" << z << "\n"; #endif return 0; } !EOF! ls -l tst1.c echo x - tst1.cmp sed 's/^X//' > tst1.cmp << '!EOF!' w=abcdefghijklmnop [1] x=0123456789wxyz [1] w(5)=fghijklmnop [1] y=w(5,3)=fgh [1] x(-5)=9wxyz [1] x(-5,3)=9wx [1] x(0)=0123456789wxyz [1] x(0,2)=01 [1] x(11,8)=xyz [1] x(8,4)=89wx [1] x=0123456789wxyz [1] x(2,2)='$$' x=01$$456789wxyz [1] z=01$$456789wxyz [2] x=01$$456789wxyz [2] x(8,4)='WXYZ' x=01$$4567WXYZyz [1] z=01$$456789wxyz [1] !EOF! ls -l tst1.cmp echo x - tst2.cmp sed 's/^X//' > tst2.cmp << '!EOF!' w=abcdefghijklmnop [1] x=0123456789wxyz [1] w(5)=fghijklmnop [1] y=w(5,3)=fgh [1] x(-5)=9wxyz [1] x(-5,3)=9wx [1] x(0)=0123456789wxyz [1] x(0,2)=01 [1] x(11,8)=xyz [1] x(8,4)=89wx [1] x=0123456789wxyz [1] x(2,2)='$$' x=01$$456789wxyz [1] z=01$$456789wxyz [2] x=01$$456789wxyz [2] x(8,4)='WXYZ' x=01$$4567WXYZyz [1] z=01$$456789wxyz [1] z=01$$4567WXYZyz [2] x=01$$4567WXYZyz [2] x(2,6)='QQQQ' x=01QQQQWXYZyz [1] z=01$$4567WXYZyz [1] z=01QQQQWXYZyz [2] x=01QQQQWXYZyz [2] x(8,2)='!!!!' x=01QQQQWX!!!!yz [1] z=01QQQQWXYZyz [1] !EOF! ls -l tst2.cmp echo x - tst4.c sed 's/^X//' > tst4.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include #include class substring; class string { struct srep { char *s; int n; }; srep *p; public: string(char *); // string x = "abc" string(); // string x; string(string&); // string x = string ... string& operator=(char *); string& operator=(string &); ~string(); char& operator[](int i); friend class substring; string(substring&); friend ostream& operator<<(ostream&, string&); friend istream& operator>>(istream&, string&); friend int operator==(string &x, char *s) { return strcmp(x.p->s, s) == 0; } friend int operator==(string &x, string &y) { return strcmp(x.p->s, y.p->s) == 0; } friend int operator!=(string &x, char *s) { return strcmp(x.p->s, s) != 0; } friend int operator!=(string &x, string &y) { return strcmp(x.p->s, y.p->s) != 0; } substring operator()(int i, int len = -1); }; string::string() { p = new srep; p->s = 0; p->n = 1; } string::string(char *s) { p = new srep; p->s = new char[ strlen(s) + 1 ]; strcpy(p->s, s); p->n = 1; } string::string(string& x) { x.p->n++; p = x.p; } string::~string() { if (--p->n == 0) { delete p->s; delete p; } } string& string::operator=(char *s) { if (p->n > 1) { // disconnect self p->n--; p = new srep; } else if (p->n == 1) delete p->s; p->s = new char[ strlen(s) +1 ]; strcpy(p->s, s); p->n = 1; return *this; } string& string::operator=(string& x) { x.p->n++; if (--p->n == 0) { delete p->s; delete p; } p = x.p; return *this; } ostream& operator<<(ostream& s, string& x) { return s << x.p->s << " [" << x.p->n << "]\n"; } istream& operator>>(istream& s, string& x) { char buf[256]; s >> buf; x = buf; cout << "echo: " << x << "\n"; return s; } #include char& string::operator[] (int i) { if (i < 0 || strlen(p->s) < i) error("index out of range"); return p->s[i]; } class substring { friend class string; char *s; int len; string *str; substring(); // substring x; substring(substring&); // substring x = substring ... public: substring(char* chptr,int len,string* stptr); substring& operator=(substring &); substring& operator=(string &); friend ostream& operator<<(ostream& out, substring& sst) { string st = sst; return out << st; } }; substring::substring(char* chptr, int stlen, string* stptr) { s = chptr; len = stlen; str = stptr; } substring::substring() { s = 0; len = 0; str = 0; } substring::substring(substring& sst) { s = sst.s; len = sst.len; str = sst.str; } // substring operator // exercise 6.3 substring string::operator()(int index, int count = -1) { char *s1 = p->s; int s1len = strlen(s1); // convert left index, if necessary if (index < 0) index += s1len; else if (index >= s1len) { substring sst(s1+s1len, 0, this); return sst; } // convert count, if necessary int numleft = s1len - index; if (count > numleft || count < 0) count = numleft; // copy the substring substring sst(s1+index, count, this); return sst; } // create a string from a substring string::string(substring& sst) { p = new class srep; // p = new srep; p->s = new char[ sst.len + 1 ]; strncpy(p->s, sst.s, sst.len); p->s[sst.len] = '\0'; p->n = 1; } main() {} !EOF! ls -l tst4.c # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0