#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 8_3_date.c 8_3_file.c 8_3_float.c 8_3_int.c 8_3_mail.c 8_3_validfn.c date.h makefile nameaddress.h tstdate.c tstdate.cmp tstdate.in tstfile.c tstfile.cmp tstfile.in tstfloat.c tstfloat.cmp tstfloat.in tstint.c tstint.cmp tstint.in tstmail.c tstmail.cmp tstmail.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:40 EDT 1990 # echo x - 8_3_date.c sed 's/^X//' > 8_3_date.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.3 // Read in a date, with error checking #include #include #include #include // return the maximum # of days // in a given year and month int maxday(long year, long month) { // check for february and leap years if (month == 2) if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) return 29; else return 28; // the rest are constant static int numdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; return numdays[month-1]; } int read_date(ostream &out, istream &in, date *val) { // set up flushing of the output stream ostream *old = in.tie(&out); // loop until we get something right for ( ; ; out << "Try again\n") { // read a year number out << "Type a year: "; char buf[256], c; if (!cin.get(buf, 256)) { in.tie(old); return 0; } in.get(c); // check the integer char *p; errno = 0; long year = strtol(buf, &p, 10); if (*p || (p == buf) || errno) continue; // read a month number out << "Type a month (a number from 1 - 12): "; if (!cin.get(buf, 256)) { in.tie(old); return 0; } in.get(c); // check the integer errno = 0; long month = strtol(buf, &p, 10); if (*p || (p == buf) || errno || (month < 1) || (month > 12)) continue; // read a day of the month int maxd = maxday(year, month); out << "Type a day (a number from 1 - " << maxd << "): "; if (!cin.get(buf, 256)) { in.tie(old); return 0; } in.get(c); // check the integer errno = 0; long day = strtol(buf, &p, 10); if (*p || (p == buf) || errno || (day < 1) || (day > maxd)) continue; // return the value, restoring the old tie first in.tie(old); val->set((int)month, (int)day, (int)year); return 1; } } !EOF! ls -l 8_3_date.c echo x - 8_3_file.c sed 's/^X//' > 8_3_file.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.3 // Read in a file name, with error checking #include #include #ifndef FILENAME_MAX /* DELETE */ #define FILENAME_MAX 1024 /* DELETE */ #endif /* DELETE */ int read_filename(ostream &out, istream &in, char **val) { // set up flushing of the output stream ostream *old = in.tie(&out); // loop until we get something right for ( ; ; out << "Try again\n") { out << "Type a file name: "; // read a line, including the newline char buf[FILENAME_MAX], c; if (!cin.get(buf, FILENAME_MAX)) { in.tie(old); return 0; } in.get(c); // check the value if (!validfilename(buf)) continue; // return the value, restoring the old tie first *val = new char[strlen(buf) + 1]; strcpy(*val, buf); in.tie(old); return 1; } } !EOF! ls -l 8_3_file.c echo x - 8_3_float.c sed 's/^X//' > 8_3_float.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.3 // Read in a floating point value, with error checking #include #include #include int read_double(ostream &out, istream &in, double *val) { // set up flushing of the output stream ostream *old = in.tie(&out); // loop until we get something right for ( ; ; out << "Try again\n") { out << "Type an floating point number: "; // read a line, including the newline char buf[256], c; if (!cin.get(buf, 256)) { in.tie(old); return 0; } in.get(c); // check the value char *p; errno = 0; double ret = strtod(buf, &p); if (*p || (p == buf) || errno) continue; // return the value, restoring the old tie first in.tie(old); *val = ret; return 1; } } !EOF! ls -l 8_3_float.c echo x - 8_3_int.c sed 's/^X//' > 8_3_int.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.3 // Read in an integer, with error checking #include #include #include int read_integer(ostream &out, istream &in, long *val) { // set up flushing of the output stream ostream *old = in.tie(&out); // loop until we get something right for ( ; ; out << "Try again\n") { out << "Type an integer: "; // read a line, including the newline char buf[256], c; if (!cin.get(buf, 256)) { in.tie(old); return 0; } in.get(c); // check the integer char *p; errno = 0; long ret = strtol(buf, &p, 10); if (*p || (p == buf) || errno) continue; // return the value, restoring the old tie first in.tie(old); *val = ret; return 1; } } !EOF! ls -l 8_3_int.c echo x - 8_3_mail.c sed 's/^X//' > 8_3_mail.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Exercise 8.3 // Read in a mail and address, with error checking #include #include int read_name_and_address(ostream &out, istream &in, name_and_address *val) { // set up flushing of the output stream ostream *old = in.tie(&out); // loop until we get something right for ( ; ; out << "Try again " << "(must be longer than one line)\n") { out << "Type a mail address, " << "followed by a blank line: "; // read a line, including the newline name_and_address ret; in >> ret; // check the value if (!in) { in.tie(old); return 0; } if (!ret.name[0] || !ret.name[1]) continue; // return the value, restoring the old tie first in.tie(old); *val = ret; return 1; } } !EOF! ls -l 8_3_mail.c echo x - 8_3_validfn.c sed 's/^X//' > 8_3_validfn.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Verify that a file exists #include #include int validfilename(char *name) { struct stat statbuf; return stat(name, &statbuf) != -1; } !EOF! ls -l 8_3_validfn.c echo x - date.h sed 's/^X//' > date.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ class date { int month, day, year; public: void set(int, int, int); void get(int*, int*, int*); void next(); void print(); }; inline void date::print() { cout << month << "/" << day << "/" << year; } inline void date::set(int m, int d, int y) { month = m; day = d; year = y; } inline void date::get(int* m, int* d, int* y) { *m = month; *d = day; *y = year; } !EOF! ls -l date.h echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../../CC ERROR= ../../error.o all: tstdate tstfile tstfloat tstint tstmail tstdate: tstdate.c 8_3_date.c date.h $(CC) tstdate.c -o tstdate $(ERROR) tstfile: tstfile.c 8_3_file.c 8_3_validfn.c $(CC) tstfile.c -o tstfile $(ERROR) tstfloat: tstfloat.c 8_3_float.c $(CC) tstfloat.c -o tstfloat $(ERROR) tstint: tstint.c 8_3_int.c $(CC) tstint.c -o tstint $(ERROR) tstmail: tstmail.c 8_3_mail.c $(CC) -I../8.2dir tstmail.c -o tstmail $(ERROR) CMP= tstdate.cmp tstfile.cmp tstfloat.cmp tstint.cmp tstmail.cmp OUT= tstdate.out tstfile.out tstfloat.out tstint.out tstmail.out tstdate.out: tstdate tstdate.in ; tstdate < tstdate.in > tstdate.out tstfile.out: tstfile tstfile.in ; tstfile < tstfile.in > tstfile.out tstfloat.out: tstfloat tstfloat.in ; tstfloat < tstfloat.in > tstfloat.out tstint.out: tstint tstint.in ; tstint < tstint.in > tstint.out tstmail.out: tstmail tstmail.in ; tstmail < tstmail.in > tstmail.out test: all $(CMP) $(OUT) cmp tstdate.out tstdate.cmp cmp tstfile.out tstfile.cmp cmp tstfloat.out tstfloat.cmp cmp tstint.out tstint.cmp cmp tstmail.out tstmail.cmp @echo test done !EOF! ls -l makefile echo x - nameaddress.h sed 's/^X//' > nameaddress.h << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include "8_2a.c" #include "8_2b.c" #include "8_2c.c" !EOF! ls -l nameaddress.h echo x - tstdate.c sed 's/^X//' > tstdate.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_3_date.c" // copy a stream of dates #include main(int, char**) { for (;;) { date a; if (!read_date(cout, cin, &a)) break; a.print(); cout << "\n"; if (!cout) break; } if (!cin.eof()) error("error reading input"); if (cout.bad()) error("error writing output"); return 0; } !EOF! ls -l tstdate.c echo x - tstdate.cmp sed 's/^X//' > tstdate.cmp << '!EOF!' Type a year: Type a month (a number from 1 - 12): Type a day (a number from 1 - 31): 7/15/1987 Type a year: Type a month (a number from 1 - 12): Try again Type a year: Type a month (a number from 1 - 12): Type a day (a number from 1 - 30): 6/3/1989 !EOF! ls -l tstdate.cmp echo x - tstdate.in sed 's/^X//' > tstdate.in << '!EOF!' 1987 7 15 1988 15 1989 6 3 !EOF! ls -l tstdate.in echo x - tstfile.c sed 's/^X//' > tstfile.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include #include //#define __cplusplus #include "8_3_validfn.c" #include "8_3_file.c" // copy a stream of files #include main(int, char**) { for (;;) { char buf[1024]; char *a = buf; if (!read_filename(cout, cin, &a)) break; cout << a << "\n"; if (!cout) break; } if (!cin.eof()) error("error reading input"); if (cout.bad()) error("error writing output"); return 0; } !EOF! ls -l tstfile.c echo x - tstfile.cmp sed 's/^X//' > tstfile.cmp << '!EOF!' Type a file name: /etc/termcap Type a file name: Try again Type a file name: Try again Type a file name: /unix Type a file name: /usr !EOF! ls -l tstfile.cmp echo x - tstfile.in sed 's/^X//' > tstfile.in << '!EOF!' /etc/termcap /etc/foo abcdef /unix /usr !EOF! ls -l tstfile.in echo x - tstfloat.c sed 's/^X//' > tstfloat.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_3_float.c" // copy a stream of doubles #include main(int, char**) { for (;;) { double a; if (!read_double(cout, cin, &a)) break; cout << a << "\n"; if (!cout) break; } if (!cin.eof()) error("error reading input"); if (cout.bad()) error("error writing output"); return 0; } !EOF! ls -l tstfloat.c echo x - tstfloat.cmp sed 's/^X//' > tstfloat.cmp << '!EOF!' Type an floating point number: 3245 Type an floating point number: 2.342 Type an floating point number: Try again Type an floating point number: 813.322 Type an floating point number: -82311 Type an floating point number: Try again Type an floating point number: 9e+14 Type an floating point number: 828324 !EOF! ls -l tstfloat.cmp echo x - tstfloat.in sed 's/^X//' > tstfloat.in << '!EOF!' 3245 2.342 as8a 813.322 -82311 813zxy 900000000000000 828324 !EOF! ls -l tstfloat.in echo x - tstint.c sed 's/^X//' > tstint.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_3_int.c" // copy a stream of ints #include main(int, char**) { for (;;) { long a; if (!read_integer(cout, cin, &a)) break; cout << a << "\n"; if (!cout) break; } if (!cin.eof()) error("error reading input"); if (cout.bad()) error("error writing output"); return 0; } !EOF! ls -l tstint.c echo x - tstint.cmp sed 's/^X//' > tstint.cmp << '!EOF!' Type an integer: 3234 Type an integer: Try again Type an integer: Try again Type an integer: 813 Type an integer: -8123 Type an integer: -1806942208 Type an integer: 828324 !EOF! ls -l tstint.cmp echo x - tstint.in sed 's/^X//' > tstint.in << '!EOF!' 3234 2.342 as8a 813 -8123 900000000000000 828324 !EOF! ls -l tstint.in echo x - tstmail.c sed 's/^X//' > tstmail.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_3_mail.c" // copy a stream of ints #include main(int, char**) { for (;;) { name_and_address a; if (!read_name_and_address(cout, cin, &a)) break; cout << a << "\n"; if (!cout) break; } if (!cin.eof()) error("error reading input"); if (cout.bad()) error("error writing output"); return 0; } !EOF! ls -l tstmail.c echo x - tstmail.cmp sed 's/^X//' > tstmail.cmp << '!EOF!' Type a mail address, followed by a blank line: tony hansen broadway new york, new york Type a mail address, followed by a blank line: addison wesley redwood city california !EOF! ls -l tstmail.cmp echo x - tstmail.in sed 's/^X//' > tstmail.in << '!EOF!' tony hansen broadway new york, new york addison wesley redwood city california !EOF! ls -l tstmail.in # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0