/* ECP: FILEname=fig1_1.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ printf( "Is there anybody out there?\n" ); /* 5*/ return 0; /* 6*/ } /* ECP: FILEname=fig1_2.c */ /* 1*/ #include /* 2*/ /* Read Items, Compute Their Average */ /* 3*/ main( void ) /* 4*/ { /* 5*/ int ItemsRead = 0; /* 6*/ double ThisItem, Sum = 0.0; /* 7*/ printf( "Enter as many items as you want\n" ); /* 8*/ printf( "Terminate with non-double or EOF marker\n" ); /* 9*/ while( scanf( "%lf", &ThisItem ) == 1 ) /*10*/ { /*11*/ ItemsRead++; /*12*/ Sum += ThisItem; /*13*/ } /*14*/ printf( "The average of %d items was %f\n", /*15*/ ItemsRead, Sum / ItemsRead ); /*16*/ return 0; /*17*/ } /* ECP: FILEname=fig1_3.c */ /* 1*/ #include /* 2*/ unsigned long int /* 3*/ Factorial( unsigned long int N ) /* 4*/ { /* 5*/ int i; /* 6*/ unsigned long int Answer = 1; /* 7*/ for( i = 1; i <= N; i++ ) /* 8*/ Answer *= i; /* 9*/ return Answer; /*10*/ } /*11*/ main( void ) /*12*/ { /*13*/ int i; /*14*/ const int MaxNum = 12; /*15*/ printf( " N N!\n" ); /*16*/ for( i = 0; i <= MaxNum; i++ ) /*17*/ printf( "%2d %10lu\n", i, Factorial( i ) ); /*18*/ return 0; /*19*/ } /* ECP: FILEname=fig1_5.c */ /* 1*/ #include /* 2*/ /* Compute Frequency Of Lottery Numbers */ /* 3*/ #define MaxNum 49 /* Numbers Range From 1 To 49 */ /* 4*/ main( void ) /* 5*/ { /* 6*/ int Count[ MaxNum + 1 ]; /* Frequency Of Each Number */ /* 7*/ int Number; /* 8*/ int i; /* 9*/ for( i = 0; i <= MaxNum; i++ ) /*10*/ Count[ i ] = 0; /*11*/ /* Note: No Prompting For Input */ /*12*/ while( scanf( "%d", &Number ) == 1 ) /*13*/ if( Number < 1 || Number > MaxNum ) /*14*/ printf( "Out of range number ignored\n" ); /*15*/ else /*16*/ Count[ Number ]++; /*17*/ /* Output The Data, Seven Numbers Per Line */ /*18*/ for( i = 1; i <= MaxNum; i++ ) /*19*/ { /*20*/ printf( "%3d:%4d", i, Count[ i ] ); /*21*/ if( i % 7 == 0 ) /*22*/ printf( "\n" ); /*23*/ else /*24*/ printf( " " ); /*25*/ } /*26*/ return 0; /*27*/ } /* ECP: FILEname=fig1_6.c */ /* 1*/ /* Return 1 if Str1 And Str2 Are Equal */ /* 2*/ int /* 3*/ IsEqual( char Str1[ ], char Str2[ ] ) /* 4*/ { /* 5*/ int i; /* 6*/ for( i = 0; Str1[ i ] == Str2[ i ]; i++ ) /* 7*/ if( Str1[ i ] == '\0' ) /* 8*/ return 1; /* Equal Strings */ /* 9*/ return 0; /* Not Equal */ /*10*/ } /* ECP: FILEname=fig1_8.c */ /* 1*/ #include /* 2*/ /* Read And Write Strings */ /* 3*/ #define MaxLen 512 /* 4*/ main( void ) /* 5*/ { /* 6*/ char Str[ MaxLen + 1 ]; /* 7*/ while( scanf( "%s", Str ) == 1 ) /* 8*/ printf( "I read %s\n", Str ); /* 9*/ return 0; /*10*/ } /* ECP: FILEname=fig1_9.c */ /* 1*/ struct Complex /* 2*/ AddComplex( struct Complex X, struct Complex Y ) /* 3*/ { /* 4*/ struct Complex Sum; /* 5*/ Sum.Real = X.Real + Y.Real; /* 6*/ Sum.Imag = X.Imag + Y.Imag; /* 7*/ return Sum; /* 8*/ } /* ECP: FILEname=fig1_10.c */ /* 1*/ #include /* 1*/ void /* 2*/ Swap( int * const X, int * const Y ) /* 3*/ { /* 4*/ int Tmp; /* 5*/ Tmp = *X; /* 6*/ *X = *Y; /* 7*/ *Y = Tmp; /* 8*/ } /* 1*/ main( void ) /* 2*/ { /* 3*/ int A = 5, B = 7; /* 4*/ Swap( &A, &B ); /* Must Pass The Address */ /* 5*/ printf( "%d %d\n", A, B ); /* 6*/ return 0; /* 7*/ } /* ECP: FILEname=fig1_11.c */ /* 1*/ typedef struct Complex Complex; /* 2*/ void AddComplex( const Complex *X, const Complex *Y, Complex *Sum ) /* 3*/ { /* 4*/ Sum->Real = X->Real + Y->Real; /* 5*/ Sum->Imag = X->Imag + Y->Imag; /* 6*/ } /* ECP: FILEname=fig1_12.c */ /* 1*/ #include /* 2*/ /* Read Items, Compute Their Average */ /* 3*/ main( void ) /* 4*/ { /* 5*/ FILE *Fp; /* File Pointer */ /* 6*/ char FileName[ 256 ]; /* File Name */ /* 7*/ int ItemsRead = 0; /* 8*/ double ThisItem, Sum = 0.0; /* 9*/ printf( "Enter input file: " ); /*10*/ if( scanf( "%s", FileName ) != 1 || /*11*/ ( Fp = fopen( FileName, "r" ) ) == NULL ) /*12*/ { /*13*/ fprintf( stderr, "Cannot open input file\n" ); /*14*/ return 1; /*15*/ } /*16*/ while( fscanf( Fp, "%lf", &ThisItem ) == 1 ) /*17*/ { /*18*/ ItemsRead++; /*19*/ Sum += ThisItem; /*20*/ } /*21*/ printf( "The average of %d items was %f\n", /*22*/ ItemsRead, Sum / ItemsRead ); /*23*/ return 0; /*24*/ } /* ECP: FILEname=fig2_1.c */ /* * A Simple First Program. * MW, 10/13/95 */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ printf( "Testing 123\n" ); /* 5*/ } /* ECP: FILEname=fig2_2.c */ #include main(void){printf("Testing 123\n");} /* ECP: FILEname=fig2_3.c */ /* 1*/ /* This comment ends early on the next line. /* 2*/ * This is not in the comment! /* 3*/ * Neither is this; the next line is also an error. /* 4*/ */ /* 5*/ #include /* 6*/ main( void ) /* 7*/ { /* 8*/ printf( "Testing 123\n" ); /* 9*/ } /* ECP: FILEname=fig2_4.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ int First = 12, Second, Third = 6; /* 5*/ Second = 8; /* 6*/ printf( "The ints: %d %d %d\n", First, Second, Third ); /* 7*/ First = Third; /* 8*/ printf( "The ints: %d %d %d\n", First, Second, Third ); /* 9*/ Third += Second; /*10*/ printf( "The ints: %d %d %d\n", First, Second, Third ); /*11*/ First = Second + Third; /*12*/ printf( "The ints: %d %d %d\n", First, Second, Third ); /*13*/ First++; /*14*/ ++Second; /*15*/ printf( "The ints: %d %d %d\n", First, Second, Third ); /*16*/ Third = First++ + ++Second; /*17*/ printf( "The ints: %d %d %d\n", First, Second, Third ); /*18*/ } /* ECP: FILEname=fig2_5.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ double A = 373737.0; /* 5*/ double B; /* 6*/ B = A*A*A + 0.37/A - A*A*A - 0.37/A; /* 7*/ printf( "The value of B is %f.\n", B ); /* 8*/ } /* ECP: FILEname=fig2_13.c */ /* 1*/ /* Faculty Profile Fields */ /* 2*/ #define Sex 0x0001 /* On If Female */ /* 3*/ #define Minority 0x0002 /* On If In A Minority Group */ /* 4*/ #define Veteran 0x0004 /* On If Veteran */ /* 5*/ #define Disabled 0x0008 /* On If Disabled */ /* 6*/ #define UScitizen 0x0010 /* On If Citizen */ /* 7*/ #define Doctorate 0x0020 /* On If Holds A Doctorate */ /* 8*/ #define Tenured 0x0040 /* On If Tenured */ /* 9*/ #define TwelveMonth 0x0080 /* On If On 12 Month Contract */ /*10*/ #define Visitor 0x0100 /* On If Not Permanent Faculty */ /*11*/ #define Campus 0x0200 /* On If Work Is At Main Campus */ /*12*/ #define Rank 0x0c00 /* Two Bits To Represent Rank */ /*13*/ #define Assistant 0x0400 /* Assistant Professor */ /*14*/ #define Associate 0x0800 /* Associate Professor */ /*15*/ #define Full 0x0c00 /* Full Professor */ /*16*/ #define College 0xf000 /* Represents 16 Colleges */ /*17*/ ... /*18*/ #define ArtsScience 0x3000 /* Arts And Science = College #3 */ /*19*/ ... /*20*/ /* Initialize Appropriate Fields */ /*21*/ Tim = ArtsScience | Associate | Campus | Tenured | /*22*/ Doctorate | UScitizen; /*23*/ /* Promote Tim To Full Professor */ /*24*/ Tim &= ~Rank; /* Turn All Rank Fields Off */ /*25*/ Tim |= Full; /* Turn Rank Fields On */ /*26*/ /* Find Bob's Tenure And College */ /*27*/ BobsTenured = Bob & Tenured; /* Zero If Untenured */ /*28*/ BobsCollege = ( Bob >> 12 ) & 0x000f; /* ECP: FILEname=fig2_14.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ int X; /* 5*/ double Y; /* 6*/ printf( "Enter an integer and a real: " ); /* 7*/ scanf( "%d %lf", &X, &Y ); /* 8*/ printf( "You entered %d and %f\n", X, Y ); /* 9*/ } /* ECP: FILEname=fig3_18.c */ /* 1*/ /* Print Prime Factorization Of A Number */ /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ unsigned long NumberToFactor, PossibleFactor, UnfactoredPart; /* 6*/ printf( "Enter a number to factor: " ); /* 7*/ scanf( "%lu", &NumberToFactor ); /* 8*/ PossibleFactor = 2; /* 9*/ UnfactoredPart = NumberToFactor; /*10*/ while( PossibleFactor * PossibleFactor <= UnfactoredPart ) /*11*/ { /*12*/ if( UnfactoredPart % PossibleFactor == 0 ) /*13*/ { /* Found A Factor */ /*14*/ printf( "%lu ", PossibleFactor ); /*15*/ UnfactoredPart /= PossibleFactor; /*16*/ } /*17*/ else /*18*/ { /* No Factor; try Next Factor */ /*19*/ if( PossibleFactor == 2 ) /*20*/ PossibleFactor = 3; /*21*/ else /*22*/ PossibleFactor += 2; /*23*/ } /*24*/ } /*25*/ /* Print Last Factor */ /*26*/ printf( "%lu\n", UnfactoredPart ); /*27*/ } /* ECP: FILEname=fig3_20.c */ /* 1*/ /* Find Numbers Equal To Sum Of The Cubes Of Their Digits */ /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ int Hund, Tens, Ones; /* 6*/ for( Hund = 1; Hund <= 9; Hund++ ) /* 7*/ for( Tens = 0; Tens <= 9; Tens++ ) /* 8*/ for( Ones = 0; Ones <= 9; Ones++ ) /* 9*/ if( Hund * Hund * Hund + Tens * Tens * Tens /*10*/ + Ones * Ones * Ones /*11*/ == 100 * Hund + 10 * Tens + Ones ) /*12*/ printf( "%d%d%d\n", Hund, Tens, Ones ); /*13*/ } /* ECP: FILEname=fig3_24.c */ /* 1*/ /* Find Next Prime After Some Starting Number */ /* 2*/ #include /* 3*/ #define TRUE 1 /* 4*/ main( void ) /* 5*/ { /* 6*/ unsigned long int Divisor, PossiblePrime; /* 7*/ int FoundPrime; /* 8*/ printf( "Enter the starting number: " ); /* 9*/ scanf( "%lu", &PossiblePrime ); /*10*/ if( PossiblePrime <= 2 ) /*11*/ PossiblePrime = 2; /*12*/ else /*13*/ if( PossiblePrime != 3 ) /*14*/ { /*15*/ if( PossiblePrime % 2 == 0 ) /*16*/ PossiblePrime++; /* Need An Odd Number */ /*17*/ for( ; ; PossiblePrime += 2 ) /*18*/ { /*19*/ FoundPrime = !TRUE; /*20*/ for( Divisor = 3; PossiblePrime % Divisor; Divisor += 2 ) /*21*/ if( Divisor * Divisor > PossiblePrime ) /*22*/ { /*23*/ FoundPrime = TRUE; /*24*/ break; /*25*/ } /*26*/ /*27*/ if( FoundPrime ) /*28*/ break; /*29*/ } /*30*/ } /*31*/ printf( "Next largest prime is %lu\n", PossiblePrime ); /*32*/ } /* ECP: FILEname=fig3_25.c */ /* 1*/ /* Print Prime Factorization Of A Number */ /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ unsigned long NumberToFactor, PossibleFactor, UnfactoredPart; /* 6*/ printf( "Enter a number to factor: " ); /* 7*/ scanf( "%lu", &NumberToFactor ); /* 8*/ PossibleFactor = 2; /* 9*/ UnfactoredPart = NumberToFactor; /*10*/ while( PossibleFactor * PossibleFactor <= UnfactoredPart ) /*11*/ { /*12*/ if( UnfactoredPart % PossibleFactor == 0 ) /*13*/ { /* Found A Factor */ /*14*/ printf( "%lu ", PossibleFactor ); /*15*/ UnfactoredPart /= PossibleFactor; /*16*/ continue; /*17*/ } /*18*/ /* No Factor; try Next Factor */ /*19*/ if( PossibleFactor == 2 ) /*20*/ PossibleFactor = 3; /*21*/ else /*22*/ PossibleFactor += 2; /*23*/ } /*24*/ /* Print Last Factor */ /*25*/ printf( "%lu\n", UnfactoredPart ); /*26*/ } /* ECP: FILEname=fig3_26.c */ /* 1*/ /* Print Distribution Of Last Digit Of Random Numbers */ /* 2*/ #include /* 3*/ #include /* For rand( ) */ /* 4*/ main( void ) /* 5*/ { /* 6*/ int i; /* 7*/ int Zeros = 0, Odds = 0, Others = 0; /* 8*/ for( i = 0; i < 10000; i++ ) /* 9*/ switch( rand( ) % 10 ) /*10*/ { /*11*/ case 0: /*12*/ Zeros++; /*13*/ break; /*14*/ case 2: /*15*/ case 4: /*16*/ case 6: /*17*/ case 8: /*18*/ Others++; /*19*/ break; /*20*/ default: /*21*/ Odds++; /*22*/ break; /*23*/ } /*24*/ printf( "Zeros: %d, odds: %d, others: %d\n", /*25*/ Zeros, Odds, Others ); /*26*/ } /* ECP: FILEname=fig3_28.c */ /* 1*/ /* Find Next Prime After StartingNumber */ /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ unsigned long int Divisor, PossiblePrime; /* 6*/ printf( "Enter the starting number: " ); /* 7*/ scanf( "%lu", &PossiblePrime ); /* 8*/ if( PossiblePrime <= 2 ) /* 9*/ PossiblePrime = 2; /*10*/ else /*11*/ if( PossiblePrime != 3 ) /*12*/ { /*13*/ if( PossiblePrime % 2 == 0 ) /*14*/ PossiblePrime++; /* Need An Odd Number */ /*15*/ /*16*/ for( ; ; PossiblePrime += 2 ) /*17*/ for( Divisor = 3; PossiblePrime % Divisor; Divisor += 2 ) /*18*/ if( Divisor * Divisor > PossiblePrime ) /*19*/ goto FoundPrime; /*20*/ } /*21*/ FoundPrime: /*22*/ printf( "Next largest prime is %lu\n", PossiblePrime ); /*23*/ } /* ECP: FILEname=fig3_29.c */ /* 1*/ #include /* 2*/ #define Pi 3.1416 /* 3*/ #define Circle 1 /* 4*/ #define Rectangle 2 /* 5*/ #define Square 3 /* 6*/ main( void ) /* 7*/ { /* 8*/ int Choice; /* 9*/ double Dim1, Dim2; /*10*/ while( 1 ) /*11*/ { /*12*/ printf( "Enter %d for circle, ", Circle ); /*13*/ printf( "Enter %d for rectangle, ", Rectangle ); /*14*/ printf( "Enter %d for square: ", Square ); /*15*/ if( scanf( "%d", &Choice ) != 1 ) /*16*/ break; /*17*/ if( Choice == Circle ) /*18*/ { /*19*/ printf( "Enter radius: " ); /*20*/ if( scanf( "%lf", &Dim1 ) != 1 ) /*21*/ break; /*22*/ printf( "Shape is circle radius %.2f; ", Dim1 ); /*23*/ printf( "the area is %.2f\n", Dim1 * Dim1 * Pi ); /*24*/ } /*25*/ else if( Choice == Square ) /*26*/ { /*27*/ printf( "Enter side: " ); /*28*/ if( scanf( "%lf", &Dim1 ) != 1 ) /*29*/ break; /*30*/ printf( "Shape is square side %.2f; ", Dim1 ); /*31*/ printf( "the area is %.2f\n", Dim1 * Dim1 ); /*32*/ } /*33*/ else if( Choice == Rectangle ) /*34*/ { /*35*/ printf( "Enter length and width: " ); /*36*/ if( scanf( "%lf %lf", &Dim1, &Dim2 ) != 2 ) /*37*/ break; /*38*/ printf( "Shape is rectangle " ); /*39*/ printf( "length %.2f width %.2f; ", Dim1, Dim2 ); /*40*/ printf( "the area is %.2f\n", Dim1 * Dim2 ); /*41*/ } /*42*/ else /* Illegal Choice */ /*43*/ break; /*44*/ } /*45*/ } /* ECP: FILEname=fig4_1.c */ /* 1*/ #include /* 2*/ /* Return True Iff N Is Prime */ /* 3*/ int /* 4*/ IsPrime( unsigned long int N ) /* 5*/ { /* 6*/ unsigned long int Divisor; /* 7*/ if( N % 2 ) /* 8*/ for( Divisor = 3; N % Divisor; Divisor += 2 ) /* 9*/ if( Divisor * Divisor > N ) /*10*/ return 1; /*11*/ return N == 2 || N == 3; /*12*/ } /*13*/ /* Return An Odd Starting Number */ /*14*/ unsigned long int /*15*/ FirstTrial( void ) /*16*/ { /*17*/ unsigned long int StartingNum; /*18*/ printf( "Enter a starting number: " ); /*19*/ if( scanf( "%lu", &StartingNum ) == 1 ) /*20*/ return StartingNum % 2 ? StartingNum : ++StartingNum; /*21*/ printf( "Bad number entered\n" ); /*22*/ return 0; /*23*/ } /*24*/ /* Find Next Prime After Some Starting Point */ /*25*/ main( void ) /*26*/ { /*27*/ unsigned long int PossiblePrime = FirstTrial( ); /*28*/ for( ; !IsPrime( PossiblePrime ); PossiblePrime += 2 ) /*29*/ ; /*30*/ printf( "Next largest prime is %lu\n", PossiblePrime ); /*31*/ } /* ECP: FILEname=fig4_6.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ /* Prints 5 0.000000 */ /* 5*/ printf( "%d %f\n", 5, sqrt( 5 ) ); /* 6*/ } /* ECP: FILEname=fig4_7.c */ /* 1*/ #include /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ /* Prints 5 2.236068 */ /* 6*/ printf( "%d %f\n", 5, sqrt( 5 ) ); /* 7*/ } /* ECP: FILEname=fig4_8.c */ /* 1*/ #include "prime.h" /* 2*/ /* Return True Iff N Is Prime */ /* 3*/ int /* 4*/ IsPrime( unsigned long int N ) /* 5*/ { /* 6*/ unsigned long int Divisor; /* 7*/ if( N % 2 ) /* 8*/ for( Divisor = 3; N % Divisor; Divisor += 2 ) /* 9*/ if( Divisor * Divisor > N ) /*10*/ return 1; /*11*/ return N == 2 || N == 3; /*12*/ } /*13*/ /* Return Smallest Prime >= N */ /*14*/ unsigned long int /*15*/ FindPrime( unsigned long int N ) /*16*/ { /*17*/ unsigned long int TestPrime; /*18*/ TestPrime = N % 2 ? N : N + 1; /*19*/ for( ; ! IsPrime( TestPrime ); TestPrime += 2 ) /*20*/ ; /*21*/ return TestPrime; /*22*/ } /* ECP: FILEname=fig4_10.c */ /* 1*/ #include /* 2*/ #include "prime.h" /* 3*/ /* Return An Odd Starting Number */ /* 4*/ unsigned long int /* 5*/ FirstTrial( void ) /* 6*/ { /* 7*/ unsigned long int StartingNum; /* 8*/ printf( "Enter a starting number: " ); /* 9*/ if( scanf( "%lu", &StartingNum ) == 1 ) /*10*/ return StartingNum % 2 ? StartingNum : ++StartingNum; /*11*/ printf( "Bad number entered\n" ); /*12*/ return 0; /*13*/ } /*14*/ /* Find Next Prime After Some Starting Point */ /*15*/ main( void ) /*16*/ { /*17*/ printf( "Next largest prime is %lu\n", /*18*/ FindPrime( FirstTrial( ) ) ); /*19*/ } /* ECP: FILEname=fig4_9.c */ /* 1*/ int IsPrime( unsigned long int N ); /* 2*/ unsigned long int FindPrime( unsigned long int N ); /* ECP: FILEname=fig4_13.c */ /* 1*/ #include "root.h" /* 2*/ int /* 3*/ DifferentSign( double F( double ), double Pt1, double Pt2 ) /* 4*/ { /* 5*/ return ( F( Pt1 ) < 0 ) != ( F( Pt2 ) < 0 ); /* 6*/ } /* 7*/ double /* 8*/ Solve( double F( double ), double Low, double High ) /* 9*/ { /*10*/ double Mid = ( Low + High ) / 2.0; /*11*/ double SmallInterval = ( High - Low ) * Epsilon; /*12*/ if( ! F( Low ) ) /*13*/ return Low; /*14*/ else /*15*/ if( ! F( High ) ) /*16*/ return High; /*17*/ else /*18*/ if( ! DifferentSign( F, Low, High ) ) /*19*/ { /*20*/ printf( "Suggested points have same sign!\n" ); /*21*/ return SolveError; /*22*/ } /*23*/ while( F( Mid ) && ( High - Low ) > SmallInterval ) /*24*/ { /*25*/ if( DifferentSign( F, Low, Mid ) ) /*26*/ High = Mid; /*27*/ else /*28*/ Low = Mid; /*29*/ Mid = ( Low + High ) / 2.0; /*30*/ } /*31*/ return Mid; /*32*/ } /* ECP: FILEname=fig4_15.c */ /* 1*/ static double Radicand; /* 2*/ static /* 3*/ double /* 4*/ CubeRootEqn( double X ) /* 5*/ { /* 6*/ return X * X * X - Radicand; /* 7*/ } /* 8*/ double /* 9*/ Cbrt( double N ) /*10*/ { /*11*/ Radicand = N; /*12*/ if( N > 0 ) /*13*/ if( N > 1.0 ) /*14*/ return Solve( CubeRootEqn, 1, N ); /*15*/ else /*16*/ return Solve( CubeRootEqn, N, 1 ); /*17*/ else /*18*/ if( N > -1.0 ) /*19*/ return Solve( CubeRootEqn, -1, N ); /*20*/ else /*21*/ return Solve( CubeRootEqn, N, -1 ); /*22*/ } /* ECP: FILEname=fig4_16.c */ /* 2*/ #define Epsilon 1E-10 /* 3*/ #define SolveError DBL_MAX /* 4*/ double Solve( double F( double ), double Low, double High ); /* 5*/ double Cbrt( double N ); /* ECP: FILEname=fig4_18.c */ /* 1*/ void /* 2*/ PrintBinary( unsigned int N ) /* 3*/ { /* 4*/ if( N >= 2 ) /* 5*/ PrintBinary( N >> 1 ); /* All The Other Bits */ /* 6*/ printf( "%d", N & 01 ); /* Least Significant Bit */ /* 7*/ } /* ECP: FILEname=fig4_19.c */ /* 1*/ #include /* 2*/ #define Pi 3.1416 /* 3*/ #define Circle 1 /* 4*/ #define Rectangle 2 /* 5*/ #define Square 3 /* 6*/ #define NoArea ( -1.0 ) /* 7*/ double /* 8*/ ProcessCircle( void ) /* 9*/ { /*10*/ double Dim1; /*11*/ printf( "Enter radius: " ); /*12*/ if( scanf( "%lf", &Dim1 ) != 1 ) /*13*/ return NoArea; /*14*/ printf( "Shape is circle radius %.2f; ", Dim1 ); /*15*/ return Dim1 * Dim1 * Pi; /*16*/ } /* ECP: FILEname=fig4_20.c */ /* 1*/ main( void ) /* 2*/ { /* 3*/ int Choice; /* 4*/ double Area; /* 5*/ while( 1 ) /* 6*/ { /* 7*/ printf( "Enter %d for circle, ", Circle ); /* 8*/ printf( "Enter %d for rectangle, ", Rectangle ); /* 9*/ printf( "Enter %d for square: ", Square ); /*10*/ if( scanf( "%d", &Choice ) != 1 ) /*11*/ break; /*12*/ if( Choice == Circle ) /*13*/ Area = ProcessCircle( ); /*14*/ else if( Choice == Square ) /*15*/ Area = ProcessSquare( ); /*16*/ else if( Choice == Rectangle ) /*17*/ Area = ProcessRectangle( ); /*18*/ else /* Illegal Choice */ /*19*/ break; /*20*/ if( Area < 0 ) /*21*/ break; /*22*/ printf( "the area is %.2f\n", Area ); /*23*/ } /*24*/ } /* ECP: FILEname=fig5_4.c */ /* 1*/ #define PrintIntDebug( Expr ) \ /* 2*/ printf( "(" #Expr "): %d\n", ( Expr ) ) /* 3*/ int /* 4*/ main( void ) /* 5*/ { /* 6*/ int X = 5, Y = 7; /* 7*/ PrintIntDebug( X + Y ); /* 8*/ return 0; /* 9*/ } /* ECP: FILEname=fig5_5.c */ /* 1*/ #define PrintDebug( Expr, Type ) \ /* 2*/ printf( "(" #Expr "): %" Type##Conv "\n", ( Expr ) ) /* 3*/ #define intConv "d" /* 4*/ #define doubleConv "f" /* 5*/ main( void ) /* 6*/ { /* 7*/ int X = 5, Y = 7; /* 8*/ double A = 5.0, B = 7.0; /* 9*/ PrintDebug( X + Y, int ); /*10*/ PrintDebug( A + B, double ); /*11*/ return 0; /*12*/ } /* ECP: FILEname=fig5_7.c */ /* 1*/ #define PrintDebug( Expr, Type ) \ /* 2*/ printf( __FILE__ "[%d](" #Expr "): %" Type##Conv "\n", \ /* 3*/ __LINE__, ( Expr ) ) /* 4*/ #define intConv "d" /* 5*/ #define doubleConv "f" /* 6*/ main( void ) /* 7*/ { /* 8*/ int X = 5, Y = 7; /* 9*/ double A = 5.0, B = 7.0; /*10*/ PrintDebug( X + Y, int ); /* Really Line 12 */ /*11*/ PrintDebug( A + B, double ); /* Really Line 13 */ /*12*/ return 0; /*13*/ } /* ECP: FILEname=fig5_8.c */ /* 1*/ #define Square( X ) ( ( X ) * ( X ) ) /* 2*/ double /* 3*/ ( Square )( double X ) /* Parentheses Are Required */ /* 4*/ { /* 5*/ return X * X; /* 6*/ } /* 7*/ main( void ) /* 8*/ { /* 9*/ double A = 5.0; /*10*/ printf( "%f\n", Square( A ) ); /* Macro Call */ /*11*/ printf( "%f\n", ( Square )( A++ ) ); /* Function Call */ /*12*/ return 0; /*13*/ } /* ECP: FILEname=fig6_1.c */ /* 1*/ /* A Very Flawed Program */ /* 2*/ #include /* 3*/ int Global; /* 4*/ main( void ) /* 5*/ { /* 6*/ static int X, Y, Z = 1; /* 7*/ int Local; /* 8*/ /* First, We Will Be Nosey */ /* 9*/ printf( "X, Y, and Z are at %x, %x, %x\n", &X, &Y, &Z ); /*10*/ printf( "Global is at: %x\n", &Global ); /*11*/ printf( "Local is at: %x\n\n", &Local ); /*12*/ printf( "X, Y, and Z are at %u, %u, %u\n", &X, &Y, &Z ); /*13*/ printf( "Values of X, Y, and Z: %d %d %d\n", X, Y, Z ); /*14*/ /* Now Show Some Typical scanf Errors */ /*15*/ printf( "Enter 1 to read into Y, 2 for Z\n" ); /*16*/ scanf( "%d", &X ); /*17*/ if( X == 1 ) /*18*/ { /*19*/ printf( "Enter Y: " ); /*20*/ scanf( "%d", Y ); /* Wrong! */ /*21*/ printf( "Y = %d\n", Y ); /*22*/ } /*23*/ else /*24*/ if( X == 2 ) /*25*/ { /*26*/ printf( "Enter Z: " ); /*27*/ scanf( "%d", Z ); /* Wrong! */ /*28*/ printf( "Z = %d\n", Z ); /*29*/ } /*30*/ return 0; /*31*/ } /* ECP: FILEname=fig6_11.c */ /* 1*/ #include /* 1*/ void /* 2*/ Swap( int * const X, int * const Y ) /* 3*/ { /* 4*/ int Tmp; /* 5*/ Tmp = *X; /* 6*/ *X = *Y; /* 7*/ *Y = Tmp; /* 8*/ } /* 1*/ main( void ) /* 2*/ { /* 3*/ int A = 5, B = 7; /* 4*/ Swap( &A, &B ); /* Must Pass The Address */ /* 5*/ printf( "%d %d\n", A, B ); /* 6*/ return 0; /* 7*/ } /* ECP: FILEname=fig6_10.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ const int X = 5; /* X Should Not Change */ /* 5*/ const int *PtrC = &X; /* A Constant Pointer To It */ /* 6*/ int *PtrNC = ( int * ) PtrC; /* PtrNC Is Not Constant */ /* 7*/ *PtrNC = 10; /* So This Changes X! */ /* 8*/ printf( "%d\n", X ); /* 9*/ return 0; /*10*/ } /* ECP: FILEname=fig6_13.c */ /* 1*/ void * Swaps Where X And Y Point, Not Their Value */ /* 2*/ WrongSwap1( const int *X, const int *Y ) /* 3*/ { /* 4*/ const int *Tmp; /* 5*/ Tmp = X; /* 6*/ X = Y; /* Would Be Caught By Compiler If The */ /* 7*/ Y = Tmp; /* const Directive Was Used Correctly */ /* 8*/ } /* 1*/ void /* Can Lead To A Difficult To Track Down Bug */ /* 2*/ WrongSwap2( int * const X, int * const Y ) /* 3*/ { /* 4*/ int *Tmp; /* Pointer Not Needed To Store The int */ /* 5*/ *Tmp = *X; /* Major Error: Tmp Is Uninitialized */ /* 6*/ *X = *Y; /* 7*/ *Y = *Tmp; /* 8*/ } /* ECP: FILEname=fig6_17.c */ /* 1*/ #include "root.h" /* 2*/ int /* 3*/ DifferentSign( double ( *F )( double ), double Pt1, double Pt2 ) /* 4*/ { /* 5*/ return ( ( *F )( Pt1 ) < 0 ) != ( ( *F )( Pt2 ) < 0 ); /* 6*/ } /* 7*/ double /* 8*/ Solve( double ( *F )( double ), double Low, double High ) /* 9*/ { /*10*/ double Mid = ( Low + High ) / 2.0; /*11*/ double SmallInterval = ( High - Low ) * Epsilon; /*12*/ if( ! ( *F )( Low ) ) /*13*/ return Low; /*14*/ else /*15*/ if( ! ( *F )( High ) ) /*16*/ return High; /*17*/ else /*18*/ if( ! DifferentSign( F, Low, High ) ) /*19*/ { /*20*/ printf( "Suggested points have same sign!\n" ); /*21*/ return SolveError; /*22*/ } /*23*/ while( ( *F )( Mid ) && ( High - Low ) > SmallInterval ) /*24*/ { /*25*/ if( DifferentSign( F, Low, Mid ) ) /*26*/ High = Mid; /*27*/ else /*28*/ Low = Mid; /*29*/ Mid = ( Low + High ) / 2.0; /*30*/ } /*31*/ return Mid; /*32*/ } /* ECP: FILEname=fig7_1.c */ /* 1*/ #include /* 2*/ /* Print Three Integers, But Avoid Duplicates */ /* 3*/ main( void ) /* 4*/ { /* 5*/ int Num1, Num2, Num3; /* 6*/ printf( "Enter three integers: " ); /* 7*/ if( scanf( "%d %d %d", &Num1, &Num2, &Num3 ) != 3 ) /* 8*/ { /* 9*/ printf( "Expected three integers -- exiting...\n" ); /*10*/ return 1; /*11*/ } /*12*/ if( Num1 == Num2 ) /*13*/ if( Num2 == Num3 ) /*14*/ printf( "%d\n", Num1 ); /*15*/ else /*16*/ printf( "%d %d\n", Num1, Num3 ); /*17*/ else /* Num1 != Num2 */ /*18*/ if( Num1 == Num3 || Num2 == Num3 ) /*19*/ printf( "%d %d\n", Num1, Num2 ); /*20*/ else /*21*/ printf( "%d %d %d\n", Num1, Num2, Num3 ); /*22*/ return 0; /* Normal Exit */ /*23*/ } /* ECP: FILEname=fig7_2.c */ /* 1*/ #include /* 2*/ #define CompExch( X, Y ) \ /* 3*/ if( X > Y ){ int _Tmp; _Tmp = X; X = Y; Y = _Tmp; } /* 4*/ /* Print Four Integers, But Avoid Duplicates */ /* 5*/ main( void ) /* 6*/ { /* 7*/ int Num1, Num2, Num3, Num4; /* 8*/ printf( "Enter four integers: " ); /* 9*/ if( scanf( "%d %d %d %d", /*10*/ &Num1, &Num2, &Num3, &Num4 ) != 4 ) /*11*/ { /*12*/ printf( "Expected four integers -- exiting...\n" ); /*13*/ return 1; /*14*/ } /*15*/ CompExch( Num1, Num2 ); /*16*/ CompExch( Num3, Num4 ); /*17*/ CompExch( Num1, Num3 ); /*18*/ CompExch( Num2, Num4 ); /*19*/ CompExch( Num2, Num3 ); /*20*/ printf( "%d", Num1 ); /*21*/ if( Num2 != Num1 ) /*22*/ printf( " %d", Num2 ); /*23*/ if( Num3 != Num2 ) /*24*/ printf( " %d", Num3 ); /*25*/ if( Num4 != Num3 ) /*26*/ printf( " %d", Num4 ); /*27*/ printf( "\n" ); /*28*/ return 0; /* Normal Exit */ /*29*/ } /* ECP: FILEname=fig7_3.c */ /* 1*/ #include /* 2*/ /* Print Four Integers, But Avoid Duplicates */ /* 3*/ #define CompExch( X, Y ) \ /* 4*/ if( X > Y ) { int _Tmp; _Tmp = X; X = Y; Y = _Tmp; } /* 5*/ main( void ) /* 6*/ { /* 7*/ int Num[ 4 ]; /* Num[ 0 ] Num[ 1 ] Num[ 2 ] Num[ 3 ] */ /* 8*/ printf( "Enter four integers: " ); /* 9*/ if( scanf( "%d %d %d %d", /*10*/ &Num[ 0 ], &Num[ 1 ], &Num[ 2 ], &Num[ 3 ] ) != 4 ) /*11*/ { /*12*/ printf( "Expected four integers -- exiting...\n" ); /*13*/ return 1; /*14*/ } /*15*/ CompExch( Num[ 0 ], Num[ 1 ] ); /*16*/ CompExch( Num[ 2 ], Num[ 3 ] ); /*17*/ CompExch( Num[ 0 ], Num[ 2 ] ); /*18*/ CompExch( Num[ 1 ], Num[ 3 ] ); /*19*/ CompExch( Num[ 1 ], Num[ 2 ] ); /*20*/ printf( "%d", Num[ 0 ] ); /*21*/ if( Num[ 1 ] != Num[ 0 ] ) /*22*/ printf( " %d", Num[ 1 ] ); /*23*/ if( Num[ 2 ] != Num[ 1 ] ) /*24*/ printf( " %d", Num[ 2 ] ); /*25*/ if( Num[ 3 ] != Num[ 2 ] ) /*26*/ printf( " %d", Num[ 3 ] ); /*27*/ printf( "\n" ); /*28*/ return 0; /* Normal Exit */ /*29*/ } /* ECP: FILEname=fig7_5.c */ /* 1*/ #include /* 2*/ /* Print Up To MaxN Integers, But Avoid Duplicates */ /* 3*/ #define MaxN 10 /* 4*/ main( void ) /* 5*/ { /* 6*/ int Num[ MaxN ], Tmp; /* 7*/ int j, Counter, ItemsRead = 0; /* 8*/ /* Read Input */ /* 9*/ printf( "Enter up to %d integers: ", MaxN ); /*10*/ while( ItemsRead < MaxN && scanf( "%d", &Num[ ItemsRead ] ) > 0 ) /*11*/ ItemsRead++; /*12*/ /* Sort Input, Using Insertion Sort */ /*13*/ for( Counter = 1; Counter < ItemsRead; Counter++ ) /*14*/ { /*15*/ Tmp = Num[ Counter ]; /*16*/ for( j = Counter; j > 0 && Tmp < Num[ j - 1 ]; j-- ) /*17*/ Num[ j ] = Num[ j - 1 ]; /*18*/ Num[ j ] = Tmp; /*19*/ } /*20*/ /* Output Non-Duplicates */ /*21*/ printf( "%d", Num[ 0 ] ); /*22*/ for( Counter = 1; Counter < ItemsRead; Counter++ ) /*23*/ if( Num[ Counter ] != Num[ Counter - 1 ] ) /*24*/ printf( " %d", Num[ Counter ] ); /*25*/ printf( "\n" ); /*26*/ return 0; /* Normal Exit */ /*27*/ } /* ECP: FILEname=fig7_8.c */ /* 1*/ #include /* 2*/ #define Len 3 /* 3*/ main( void ) /* 4*/ { /* 5*/ int First, Second; /* 6*/ int Num[ Len ]; /* 7*/ int Third, Fourth; /* 8*/ int i; /* 9*/ /* Initialize Array To Zero, Other Variables To Five */ /*10*/ First = Second = Third = Fourth = 5; /*11*/ for( i = 0; i < Len; i++ ) /*12*/ Num[ i ] = 0; /*13*/ printf( "Addresses are:\n" ); /*14*/ printf( "&First = %x, &Second = %x\n", &First, &Second ); /*15*/ printf( "&Third = %x, &Fourth = %x\n", &Third, &Fourth ); /*16*/ for( i = 0; i < Len + 2; i++ ) /*17*/ printf( "&Num[%d] = %x\n", i, &Num[ i ] ); /*18*/ printf( "\n" ); /* Print Array Starting Point */ /*19*/ printf( "Num = %x\n", Num ); /*20*/ /* This Will Usually Print One Of Other Variables */ /*21*/ printf( "Num[%d] = %d\n", Len + 1, Num[ Len + 1 ] ); /*22*/ /* This Will Usually Overwrite One Of Other Variables */ /*23*/ Num[ Len + 1 ] = 0; /*24*/ printf( "First = %d, Second = %d\n", First, Second ); /*25*/ printf( "Third = %d, Fourth = %d\n", Third, Fourth ); /*26*/ } /* ECP: FILEname=fig7_11.c */ /* 1*/ #include /* 2*/ #define MaxN 10 /* 3*/ /* Read Up To MaxItems Ints, With No Attempts At Error Recovery */ /* 4*/ int /* 5*/ GetInts( int Array[ ], int MaxItems ) /* 6*/ { /* 7*/ int i = 0; /* 8*/ printf( "Enter up to %d integers: ", MaxItems ); /* 9*/ while( i < MaxItems && scanf( "%d", &Array[ i ] ) == 1 ) /*10*/ i++; /*11*/ return i; /*12*/ } /*13*/ /* Print Non-Duplicates: Sorted Array Array With N Items */ /*14*/ void /*15*/ PrintNondup( const int Array[ ], unsigned int N ) /*16*/ { /*17*/ int i; /*18*/ printf( "%d", Array[ 0 ] ); /*19*/ for( i = 1; i < N; i++ ) /*20*/ if( Array[ i ] != Array[ i - 1 ] ) /*21*/ printf( " %d", Array[ i ] ); /*22*/ printf( "\n" ); /*23*/ } /*24*/ main( void ) /*25*/ { /*26*/ int Num[ MaxN ]; /*27*/ int ItemsRead; /*28*/ ItemsRead = GetInts( Num, MaxN ); /*29*/ printf( "Processing %d items\n", ItemsRead ); /*30*/ if( ItemsRead > 0 ) /*31*/ { /*32*/ InsertSort( Num, ItemsRead ); /*33*/ PrintNondup( Num, ItemsRead ); /*34*/ } /*35*/ return !ItemsRead; /*36*/ } /* ECP: FILEname=fig7_12.c */ /* 1*/ /* Insertion Sort: Array A With N Items */ /* 2*/ typedef int ElementType; /* 3*/ void /* 4*/ InsertSort( ElementType A[ ], unsigned int N ) /* 5*/ { /* 6*/ ElementType Tmp; /* 7*/ int i, j; /* 8*/ for( i = 1; i < N; i++ ) /* 9*/ { /*10*/ Tmp = A[ i ]; /*11*/ for( j = i; j > 0 && Tmp < A[ j - 1 ]; j-- ) /*12*/ A[ j ] = A[ j - 1 ]; /*13*/ A[ j ] = Tmp; /*14*/ } /*15*/ } /* ECP: FILEname=fig7_13.c */ /* 1*/ #include /* 2*/ #define MaxN 10 /* 3*/ typedef int IntArray[ MaxN ]; /* 4*/ /* Print Non-Duplicates: Array Array With N Items */ /* 5*/ /* Do Not Alter The Array */ /* 6*/ void /* 7*/ PrintNondup( const IntArray Array, unsigned int N ) /* 8*/ { /* 9*/ IntArray Tmp; /* A Temporary Array */ /*10*/ int i; /*11*/ for( i = 0; i < N; i++ ) /* Copy Into Tmp */ /*12*/ Tmp[ i ] = Array[ i ]; /*13*/ InsertSort( Tmp, N ); /* Sort Tmp */ /*14*/ printf( "%d", Tmp[ 0 ] ); /*15*/ for( i = 1; i < N; i++ ) /*16*/ if( Tmp[ i ] != Tmp[ i - 1 ] ) /*17*/ printf( " %d", Tmp[ i ] ); /*18*/ printf( "\n" ); /*19*/ } /*20*/ main( void ) /*21*/ { /*22*/ IntArray Num; /*23*/ int ItemsRead; /*24*/ ItemsRead = GetInts( Num, MaxN ); /*25*/ printf( "Processing %d items\n", ItemsRead ); /*26*/ if( ItemsRead > 0 ) /*27*/ PrintNondup( Num, ItemsRead ); /*28*/ return !ItemsRead; /*29*/ } /* ECP: FILEname=fig7_15.c */ /* 1*/ void /* 2*/ Shellsort( ElementType A[ ], const unsigned int N ) /* 3*/ { /* 4*/ unsigned int Gap; /* 5*/ ElementType Tmp; /* 6*/ unsigned int i, j; /* Loop Counters */ /* 7*/ for( Gap = N/2; Gap > 0; Gap /= 2 ) /* 8*/ for( i = Gap; i < N; i++ ) /* 9*/ { /*10*/ Tmp = A[ i ]; /*11*/ for( j = i; j >= Gap && Tmp < A[ j - Gap ]; j -= Gap ) /*12*/ A[ j ] = A[ j - Gap ]; /*13*/ A[ j ] = Tmp; /*14*/ } /*15*/ } /* ECP: FILEname=fig7_16.c */ /* 1*/ void /* 2*/ Shellsort( ElementType A[ ], const unsigned int N ) /* 3*/ { /* 4*/ unsigned int Gap; /* 5*/ ElementType Tmp; /* 6*/ unsigned int i, j; /* Loop Counters */ /* 7*/ for( Gap = N/2; Gap > 0; Gap = Gap == 2 ? 1 : Gap / 2.2 ) /* 8*/ for( i = Gap; i < N; i++ ) /* 9*/ { /*10*/ Tmp = A[ i ]; /*11*/ for( j = i; j >= Gap && Tmp < A[ j - Gap ]; j -= Gap ) /*12*/ A[ j ] = A[ j - Gap ]; /*13*/ A[ j ] = Tmp; /*14*/ } /*15*/ } /* ECP: FILEname=fig7_18.c */ /* 1*/ enum Piece { Human, Computer, Empty }; /* 2*/ enum Side { You, Me }; /* 3*/ enum Color { X, O }; /* 4*/ enum Score { HumanWin, Draw, ComputerWin, Unclear }; /* 5*/ typedef enum Piece Piece; /* 6*/ typedef enum Side Side; /* 7*/ typedef enum Score Score; /* 8*/ typedef enum Color Color; /* 9*/ #define Bsize 3 /* 3 By 3 Tic Tac Toe */ /*10*/ typedef Piece BoardType[ Bsize ][ Bsize ]; /*11*/ /* Prototypes For Two Unwritten Routines */ /*12*/ void GetMove( BoardType B, Side S ); /*13*/ int IsWon( BoardType B, Side S ); /*14*/ /* Place Piece P ( Possibly Empty ) */ /*15*/ void /*16*/ Place( BoardType Board, int Row, int Column, Piece P ) /*17*/ { /*18*/ Board[ Row ][ Column ] = P; /*19*/ } /*20*/ int /*21*/ IsFull( BoardType Board ) /*22*/ { /*23*/ int Row, Column; /*24*/ for( Row = 0; Row < Bsize; Row++ ) /*25*/ for( Column = 0; Column < Bsize; Column++ ) /*26*/ if( Board[ Row ][ Column ] == Empty ) /*27*/ return 0; /*28*/ return 1; /*29*/ } /* ECP: FILEname=fig7_19.c */ /* 1*/ int /* 2*/ IsEmpty( BoardType Board, int Row, int Column ) /* 3*/ { /* 4*/ return Board[ Row ][ Column ] == Empty; /* 5*/ } /* 6*/ void /* 7*/ MakeEmpty( BoardType Board ) /* 8*/ { /* 9*/ int Row, Column; /*10*/ for( Row = 0; Row < Bsize; Row++ ) /*11*/ for( Column = 0; Column < Bsize; Column++ ) /*12*/ Board[ Row ][ Column ] = Empty; /*13*/ } /*14*/ void /*15*/ PrintBoard( BoardType Board ) /*16*/ { /*17*/ int Row, Column; /*18*/ printf( "---\n" ); /*19*/ for( Row = 0; Row < Bsize; Row++ ) /*20*/ { /*21*/ for( Column = 0; Column < Bsize; Column++ ) /*22*/ if( Board[ Row ][ Column ] == Empty ) /*23*/ printf( " " ); /*24*/ else if( Board[ Row ][ Column ] == Computer ) /*25*/ printf( CompColor == X ? "X" : "O" ); /*26*/ else /*27*/ printf( CompColor != X ? "X" : "O" ); /*28*/ printf( "\n" ); /*29*/ } /*30*/ printf( "---\n" ); /*31*/ } /* ECP: FILEname=fig7_21.c */ /* 1*/ #include /* 2*/ void /* 3*/ PrintSize( int A[ ] ) /* 4*/ { /* 5*/ printf( "Size of formal A[] is %u\n", sizeof( A ) ); /* 6*/ } /* 7*/ main( void ) /* 8*/ { /* 9*/ int A[ ] = { 1, 2, 3, 4, 5 }; /*10*/ printf( "Size of actual A[] is %u\n", sizeof( A ) ); /*11*/ printf( "A has %u elements\n", sizeof( A )/sizeof( A[ 0 ] ) ); /*12*/ printf( "Ints are %u bytes\n\n", sizeof( int ) ); /*13*/ PrintSize( A ); /*14*/ return 0; /*15*/ } /* ECP: FILEname=fig7_23.c */ /* 1*/ #include /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ int *NumArray; /* A Dynamically Allocated Array */ /* 6*/ int ItemsRead = 0; /* 7*/ printf( "How many items? " ); /* 8*/ scanf( "%d", &ItemsRead ); /* 9*/ if( ItemsRead <= 0 || ItemsRead > MaxN ) /*10*/ Error( "ItemsRead is out of range" ); /*11*/ NumArray = malloc( sizeof( int ) * ItemsRead ); /*12*/ if( NumArray == NULL ) /*13*/ Error( "Out of memory" ); /*14*/ if( GetInts( NumArray, ItemsRead ) != ItemsRead ) /*15*/ Error( "Not enough input" ); /*16*/ PrintNondup( NumArray, ItemsRead ); /*17*/ return !ItemsRead; /*18*/ } /* ECP: FILEname=fig7_25.c */ /* 1*/ #include /* 2*/ #include /* 3*/ /* Print Non-Duplicates: Array Has N Items */ /* 4*/ /* Since We Do Not Know N, TmpArray Is Dynamically Allocated */ /* 5*/ /* However, We Must Now Remember To free The Memory! */ /* 6*/ /* Array Is Left Untouched */ /* 7*/ void /* 8*/ PrintNondup( const int Array[ ], const unsigned int N ) /* 9*/ { /*10*/ int *TmpArray; /* A Temporary Array */ /*11*/ int i; /*12*/ TmpArray = malloc( sizeof( int ) * N ); /*13*/ if( TmpArray == NULL ) /*14*/ Error( "No memory for temporary array" ); /*15*/ for( i = 0; i < N; i++ ) /* Copy Into TmpArray */ /*16*/ TmpArray[ i ] = Array[ i ]; /*17*/ Shellsort( TmpArray, N ); /* Sort TmpArray */ /*18*/ printf( "%d", TmpArray[ 0 ] ); /*19*/ for( i = 1; i < N; i++ ) /*20*/ if( TmpArray[ i ] != TmpArray[ i - 1 ] ) /*21*/ printf( " %d", TmpArray[ i ] ); /*22*/ printf( "\n" ); /*23*/ free( TmpArray ); /* Must free The Array Now */ /*24*/ } /* ECP: FILEname=fig7_26.c */ /* 1*/ /* Read An Unlimited Number Of Ints */ /* 2*/ /* With No Attempts At Error Recovery */ /* 3*/ /* Correct Implementation */ /* 4*/ /* Returns A Pointer To The Data */ /* 5*/ /* ItemsRead Is Set By Reference To #Items Read */ /* 6*/ int * /* 7*/ GetInts( int * const ItemsRead ) /* 8*/ { /* 9*/ int NumRead = 0; /*10*/ int ArraySize = 5; /*11*/ int InputVal, *Array; /*12*/ /*13*/ Array = malloc( sizeof( int ) * ArraySize ); /*14*/ if( Array == NULL ) /*15*/ Error( "Out of memory" ); /*16*/ printf( "Enter any number of integers: " ); /*17*/ while( scanf( "%d", &InputVal ) == 1 ) /*18*/ { /*19*/ if( NumRead == ArraySize ) /*20*/ { /* Array Doubling Code */ /*21*/ ArraySize *= 2; /*22*/ Array = realloc( Array, sizeof( int ) * ArraySize ); /*23*/ if( Array == NULL ) /*24*/ Error( "Out of memory" ); /*25*/ } /*26*/ Array[ NumRead++ ] = InputVal; /*27*/ } /*28*/ *ItemsRead = NumRead; /*29*/ return realloc( Array, sizeof( int ) * NumRead ); /*30*/ } /* 1*/ main( void ) /* 2*/ { /* 3*/ int *NumArray; /* 4*/ int ItemsRead; /* 5*/ NumArray = GetInts( &ItemsRead ); /* 6*/ PrintNondup( NumArray, ItemsRead ); /* 7*/ return !ItemsRead; /* 8*/ } /* ECP: FILEname=fig7_27.c */ /* 1*/ /* Read An Umlimited Number Of Ints */ /* 2*/ /* With No Attempts At Error Recovery */ /* 3*/ /* Returns #Items Read */ /* 4*/ /* Will Fail Because Array Is A Copy Of NumArray And So */ /* 5*/ /* Changes In Where It Points Are Not Seen in NumArray */ /* 6*/ int /* 7*/ GetIntsWrong( int *Array ) /* 8*/ { /* 9*/ int NumRead = 0; /*10*/ int ArraySize = 5; /*11*/ int InputVal; /*12*/ /*13*/ Array = malloc( sizeof( int ) * ArraySize ); /*14*/ if( Array == NULL ) /*15*/ Error( "Out of memory" ); /*16*/ printf( "Enter any number of integers: " ); /*17*/ while( scanf( "%d", &InputVal ) == 1 ) /*18*/ { /*19*/ if( NumRead == ArraySize ) /*20*/ { /* Array Doubling Code */ /*21*/ ArraySize *= 2; /*22*/ Array = realloc( Array, sizeof( int ) * ArraySize ); /*23*/ if( Array == NULL ) /*24*/ Error( "Out of memory" ); /*25*/ } /*26*/ Array[ NumRead++ ] = InputVal; /*27*/ } /*28*/ return NumRead; /*29*/ } /* ECP: FILEname=fig7_31.c */ /* 1*/ #include /* 2*/ #define MaxN 10 /* 3*/ /* Read Up To MaxItems Ints; No Attempts At Error Recovery */ /* 4*/ int /* 5*/ GetInts( int *Array, int MaxItems ) /* 6*/ { /* 7*/ int i = 0; /* 8*/ printf( "Enter up to %d integers: ", MaxItems ); /* 9*/ while( i < MaxItems && scanf( "%d", Array++ ) == 1 ) /*10*/ i++; /*11*/ return i; /*12*/ } /* ECP: FILEname=fig7_32.c */ /* 1*/ void /* 2*/ PrintShapeName( int i ) /* 3*/ { /* 4*/ if( i == Circle ) /* 5*/ printf( "circle" ); /* 6*/ else if( i == Rectangle ) /* 7*/ printf( "rectangle" ); /* 8*/ else if( i == Square ) /* 9*/ printf( "square" ); /*10*/ else /*11*/ printf( "unrecognized shape" ); /*12*/ } /* ECP: FILEname=fig7_33.c */ /* 1*/ #define MaxShapes 1000 /* 2*/ void /* 3*/ OutputShapes( const double ShapeType[ ], /* 4*/ const double Areas[ ], double HowMany ) /* 5*/ { /* 6*/ int i, j; /* 7*/ printf( "\n" ); /* 8*/ for( i = Circle; i <= Square; i++ ) /* 9*/ { /*10*/ for( j = 0; j < HowMany; j++ ) /*11*/ if( ShapeType[ j ] == i ) /*12*/ { /*13*/ PrintShapeName( i ); /*14*/ printf( " area %.2f\n", Areas[ j ] ); /*15*/ } /*16*/ } /*17*/ } /* ECP: FILEname=fig7_34.c */ /* 1*/ main( void ) /* 2*/ { /* 3*/ int i, j, ShapesRead, Choice; /* 4*/ double Areas[ MaxShapes ]; /* 5*/ double ShapeType[ MaxShapes ]; /* 6*/ for( i = 0; i < MaxShapes; i++ ) /* 7*/ { /* 8*/ printf( "Enter %d for circle, ", Circle ); /* 9*/ printf( "Enter %d for rectangle, ", Rectangle ); /*10*/ printf( "Enter %d for square: ", Square ); /*11*/ if( scanf( "%d", &Choice ) != 1 ) /*12*/ break; /*13*/ if( Choice == Circle ) /*14*/ Areas[ i ] = ReadCircle( ); /*15*/ else if( Choice == Square ) /*16*/ Areas[ i ] = ReadSquare( ); /*17*/ else if( Choice == Rectangle ) /*18*/ Areas[ i ] = ReadRectangle( ); /*19*/ else /* Illegal Choice */ /*20*/ break; /*21*/ ShapeType[ i ] = Choice; /*22*/ } /*23*/ OutputShapes( ShapeType, Areas, i ); /*24*/ return 0; /*25*/ } /* ECP: FILEname=fig8_1.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ char Ch; /* 5*/ while( scanf( "%c", &Ch ) != EOF ) /* 6*/ printf( "Read a *%c*, internal number %d\n", Ch, Ch ); /* 7*/ return 0; /* 8*/ } /* ECP: FILEname=fig8_6.c */ /* 1*/ #include /* 2*/ #include /* 3*/ void /* 4*/ PrintBool( int Val ) /* 5*/ { /* 6*/ printf( "%6c", Val ? 'T' : 'F' ); /* 7*/ } /* 8*/ main( void ) /* 9*/ { /*10*/ unsigned char Ch = 0; /*11*/ printf( "DEC OCT HEX CHAR ALPHA UPPER LOWER " ); /*12*/ printf( "DIGIT ALNUM HEX SPACE PUNCT\n" ); /*13*/ do /*14*/ { /*15*/ printf( "%3d %3o %3x ", Ch, Ch, Ch ); /*16*/ if( isgraph( Ch ) ) /*17*/ printf( "%4c", Ch ); /*18*/ else if( isprint( Ch ) ) /*19*/ printf( " sp" ); /*20*/ else switch( Ch ) /*21*/ { /*22*/ case '\a': printf( "bell" ); break; /*23*/ case '\n': printf( " nl" ); break; /*24*/ case '\0': printf( "null" ); break; /*25*/ case '\t': printf( " tab" ); break; /*26*/ default : printf( "\\%03o", Ch ); break; /*27*/ } /*28*/ PrintBool( isalpha( Ch ) ); /*29*/ PrintBool( isupper( Ch ) ); /*30*/ PrintBool( islower( Ch ) ); /*31*/ PrintBool( isdigit( Ch ) ); /*32*/ PrintBool( isalnum( Ch ) ); /*33*/ PrintBool( isxdigit( Ch ) ); /*34*/ PrintBool( isspace( Ch ) ); /*35*/ PrintBool( ispunct( Ch ) ); /*36*/ printf( "\n" ); /*37*/ } while( Ch++ != 127 ); /*38*/ return 0; /*39*/ } /* ECP: FILEname=fig8_7.c */ /* 1*/ int /* 2*/ ToUpper( char Ch ) /* 3*/ { /* 4*/ switch( Ch ) /* 5*/ { /* 6*/ case 'a': return 'A'; /* 7*/ case 'b': return 'B'; /* 8*/ case 'c': return 'C'; /* 9*/ case 'd': return 'D'; /*10*/ case 'e': return 'E'; /*11*/ case 'f': return 'F'; /*12*/ case 'g': return 'G'; /*13*/ case 'h': return 'H'; /*14*/ case 'i': return 'I'; /*15*/ case 'j': return 'J'; /*16*/ case 'k': return 'K'; /*17*/ case 'l': return 'L'; /*18*/ case 'm': return 'M'; /*19*/ case 'n': return 'N'; /*20*/ case 'o': return 'O'; /*21*/ case 'p': return 'P'; /*22*/ case 'q': return 'Q'; /*23*/ case 'r': return 'R'; /*24*/ case 's': return 'S'; /*25*/ case 't': return 'T'; /*26*/ case 'u': return 'U'; /*27*/ case 'v': return 'V'; /*28*/ case 'w': return 'W'; /*29*/ case 'x': return 'X'; /*30*/ case 'y': return 'Y'; /*31*/ case 'z': return 'Z'; /*32*/ default : return Ch; /*33*/ } /*34*/ } /* ECP: FILEname=fig8_8.c */ /* 1*/ /* Generate Routine in Previous Figure */ /* 2*/ /* This Program Works Only An ASCII Machine, */ /* 3*/ /* But Code That Is Generated Is Portable To Any Machine */ /* 4*/ #include /* 5*/ main( void ) /* 6*/ { /* 7*/ char C; /* 8*/ printf( "int\nToUpper( char ch )\n{\n" ); /* ToUpper */ /* 9*/ printf( "\tswitch( ch )\n\t{\n" ); /* Start switch */ /*10*/ for( C = 'a'; C <= 'z'; C++ ) /* Print Cases */ /*11*/ printf( "\t\tcase '%C': return '%C';\n", C, C + 'A'-'a' ); /*12*/ printf( "\t\tdefault : return ch;\n" ); /*13*/ printf( "\t}\n}\n" ); /* Closing Braces */ /*14*/ return 0; /*15*/ } /* ECP: FILEname=fig8_9.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ int Ch; /* Must Be An int!! */ /* 5*/ while( ( Ch = getchar( ) ) != EOF ) /* ( ) Are Needed!! */ /* 6*/ { /* 7*/ putchar( Ch ); /* 8*/ if( Ch == '\n' ) /* 9*/ putchar( '\n' ); /*10*/ } /*11*/ return 0; /*12*/ } /* ECP: FILEname=fig8_11.c */ /* 1*/ int /* 2*/ ToUpper( char Ch ) /* 3*/ { /* 4*/ static const char Lower[ ] = "abcdefghijklmnopqrstuvwxyz"; /* 5*/ static const char Upper[ ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /* 6*/ int i; /* 7*/ for( i = 0; Lower[ i ] != '\0'; i++ ) /* 8*/ if( Lower[ i ] == Ch ) /* 9*/ return Upper[ i ]; /*10*/ return Ch; /*11*/ } /* ECP: FILEname=fig8_13.c */ /* 1*/ ??=include /* 2*/ main( void ) /* 3*/ ??< /* 4*/ printf( "Hello world??/n" ); /* 5*/ ??> /* ECP: FILEname=fig8_14.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ printf( "What??!!\n" ); /* What|! */ /* 5*/ printf( "What??" "!!\n" ); /* What??!! */ /* 6*/ printf( "What?\?!!\n" ); /* What??!! */ /* 7*/ } /* ECP: FILEname=fig8_15.c */ /* 1*/ unsigned int /* 2*/ Strlen( const char Str[ ] ) /* 3*/ { /* 4*/ int i; /* 5*/ for( i = 0; Str[ i ] != '\0'; i++ ) /* 6*/ ; /* 7*/ return i; /* 8*/ } /* ECP: FILEname=fig8_16.c */ /* 1*/ unsigned int /* 2*/ Strlen( const char Str[ ] ) /* 3*/ { /* 4*/ int i = -1; /* 5*/ while( Str[ ++i ] ) /* 6*/ ; /* 7*/ return i; /* 8*/ } /* ECP: FILEname=fig8_17.c */ /* 1*/ char * /* 2*/ Strcpy( char Lhs[ ], const char Rhs[ ] ) /* 3*/ { /* 4*/ int i; /* 5*/ if( Lhs != Rhs ) /* 6*/ for( i = 0; Lhs[ i ] = Rhs[ i ]; i++ ) /* 7*/ ; /* 8*/ return Lhs; /* 9*/ } /* ECP: FILEname=fig8_18.c */ /* 1*/ int /* 2*/ Strcmp( const char Lhs[ ], const char Rhs[ ] ) /* 3*/ { /* 4*/ int i; /* 5*/ for( i = 0; Lhs[ i ] == Rhs[ i ]; i++ ) /* 6*/ if( Lhs[ i ] == '\0' ) /* 7*/ return 0; /* 8*/ return Lhs[ i ] - Rhs[ i ]; /* 9*/ } /* ECP: FILEname=fig8_19.c */ /* 1*/ int /* 2*/ IsPrefix( const char Little[ ], const char Big[ ] ) /* 3*/ { /* 4*/ return !strncmp( Little, Big, strlen( Little ) ); /* 5*/ } /* ECP: FILEname=fig8_20.c */ /* 1*/ unsigned int /* 2*/ Strlen( const char * const Str ) /* 3*/ { /* 4*/ const char *Sp = Str; /* 5*/ while( *Sp++ ) /* 6*/ ; /* 7*/ return Sp - Str - 1; /* 8*/ } /* ECP: FILEname=fig8_21.c */ /* 1*/ /* Incorrect Routine That Will Work On Almost All Machines */ /* 2*/ unsigned int /* 3*/ WrongStrlen( const char * const Str ) /* 4*/ { /* 5*/ const char *Sp = Str - 1; /* Illegal Pointer */ /* 6*/ while( *++Sp ) /* 7*/ ; /* 8*/ return Sp - Str; /* 9*/ } /* ECP: FILEname=fig8_22.c */ /* 1*/ char * /* 2*/ Strcpy( char * const Lhs, const char *Rhs ) /* 3*/ { /* 4*/ char *Lhp = Lhs; /* 5*/ if( Lhs != Rhs ) /* 6*/ while( ( *Lhp++ = *Rhs++ ) != '\0' ) /* 7*/ ; /* 8*/ return Lhs; /* 9*/ } /* ECP: FILEname=fig8_24.c */ /* 1*/ int /* 2*/ Strcmp( const char *Lhs, const char *Rhs ) /* 3*/ { /* 4*/ for( ; *Lhs == *Rhs && *Lhs != '\0'; Lhs++, Rhs++ ) /* 5*/ ; /* 6*/ return *Lhs - *Rhs; /* 7*/ } /* ECP: FILEname=fig8_25.c */ /* 1*/ int /* 2*/ CountChars( const char *Str, char SearchChar ) /* 3*/ { /* 4*/ unsigned int Matches = 0; /* 5*/ if( Str != NULL ) /* 6*/ while( ( Str = Strchr( Str, SearchChar ) ) != NULL ) /* 7*/ { /* 8*/ Str++; /* 9*/ Matches++; /*10*/ } /*11*/ return Matches; /*12*/ } /* ECP: FILEname=fig8_26.c */ /* 1*/ int /* 2*/ Itoa( char Str[ ], int N ) /* 3*/ { /* 4*/ return sprintf( Str, "%d", N ); /* 5*/ } /* ECP: FILEname=fig8_27.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #define LineLen 72 /* 4*/ #define IndentLen 5 /* 5*/ #define FLUSH "" /* ECP: FILEname=fig8_28.c */ /* 1*/ main ( void ) /* 2*/ { /* 3*/ char Str[ 1000 ]; /* 4*/ for( ; ; ) /* 5*/ { /* 6*/ if( scanf( "%[^ \t\n]", Str ) == 1 ) /* 7*/ { /* 8*/ Justify( Str ); /* Get A Word And Justify */ /* 9*/ continue; /*10*/ } /*11*/ else /* Get White Space */ /*12*/ if( scanf( "%[ \t]", Str ) == 1 ) /*13*/ continue; /*14*/ else /* Must Be A Newline Or EOF */ /*15*/ { /*16*/ if( getchar( ) == EOF ) /* Should Be A Newline */ /*17*/ break; /*18*/ /* If There's another newline, then new paragraph */ /*19*/ if( scanf( "%[\n]", Str ) == 1 ) /*20*/ Justify( FLUSH ); /*21*/ } /*22*/ } /*23*/ Justify( FLUSH ); /* Finish Off Last Line */ /*24*/ return 0; /*25*/ } /* ECP: FILEname=fig8_29.c */ /* 1*/ /* If Word Is FLUSH, Then Output The Current Line. */ /* 2*/ /* Otherwise, Add Word To End Of Line; if It Doesn't Fit */ /* 3*/ /* Then Output The Current Line ( Padded ) */ /* 4*/ void /* 5*/ Justify( const char Word[ ] ) /* 6*/ { /* 7*/ static char CurrentLine[ LineLen + 1 ] = ""; /* 8*/ static int CharsHeld = 0; /* 9*/ static int Indent = IndentLen; /* Current Amount To Indent */ /*10*/ static int LineLimit = LineLen - IndentLen; /*11*/ int WordLen = strlen( Word ); /*12*/ if( strcmp( Word, FLUSH ) == 0 ) /*13*/ { /*14*/ /* Print The Pending Line. */ /*15*/ PrintSpaces( Indent ); /*16*/ puts( CurrentLine ); /* No Padding */ /*17*/ Indent = IndentLen; /* For Next Line */ /*18*/ } /*19*/ else /*20*/ if( CharsHeld + WordLen < LineLimit ) /*21*/ { /*22*/ /* Word Fits On The Line */ /*23*/ if( CharsHeld ) /* Toss in Blank if Not First Word */ /*24*/ { /*25*/ strcat( CurrentLine, " " ); /*26*/ CharsHeld++; /*27*/ } /*28*/ strcat( CurrentLine, Word ); /*29*/ CharsHeld += WordLen; /*30*/ return; /*31*/ } /*32*/ else /*33*/ { /* Print The Pending Line With Padding*/ /*34*/ PrintSpaces( Indent ); /*35*/ PutOut( CurrentLine, LineLimit ); /*36*/ Indent = 0; /* Next Line Is Not Indented */ /*37*/ } /*38*/ /* Start Up The Next Line */ /*39*/ strcpy( CurrentLine, Word ); /*40*/ CharsHeld = WordLen; /*41*/ LineLimit = LineLen - Indent; /*42*/ } /* ECP: FILEname=fig8_30.c */ /* 1*/ void /* 2*/ PrintSpaces( int HowMany ) /* 3*/ { /* 4*/ while( HowMany-- > 0 ) /* 5*/ putchar( ' ' ); /* 6*/ } /* 7*/ void /* 8*/ PutOut( const char Line[ ], int Length ) /* 9*/ { /*10*/ int SmallGapLen; /*11*/ int NumGaps = 0; /*12*/ int NumSmallGaps; /*13*/ int LineLen = strlen( Line ); /*14*/ int TotalSpaces; /*15*/ int i; /*16*/ for( i = 0; Line[ i ]; i++ ) /*17*/ if( Line[ i ] == ' ' ) /*18*/ NumGaps++; /*19*/ if( !NumGaps ) /*20*/ { /*21*/ puts( Line ); /*22*/ return; /*23*/ } /*24*/ TotalSpaces = Length - LineLen + NumGaps; /*25*/ SmallGapLen = TotalSpaces / NumGaps; /*26*/ NumSmallGaps = NumGaps - TotalSpaces % NumGaps; /*27*/ for( i = 0; Line[ i ]; i++ ) /*28*/ if( Line[ i ] == ' ' ) /*29*/ PrintSpaces( SmallGapLen + ( NumSmallGaps-- <= 0 ) ); /*30*/ else /*31*/ putchar( Line[ i ] ); /*32*/ putchar( '\n' ); /*33*/ } /* ECP: FILEname=fig8_31.c */ /* 1*/ /* Print out Starting And Ending time. */ /* 2*/ /* Incorrect: ctime Returns A Pointer To static Data */ /* 3*/ #include /* 4*/ #include /* 5*/ main( void ) /* 6*/ { /* 7*/ time_t Before, After; /* 8*/ char *Bct, *Act; /* 9*/ time( &Before ); /*10*/ Bct = ctime( &Before ); /*11*/ sleep( 5 ); /*12*/ time( &After ); /*13*/ Act = ctime( &After ); /*14*/ printf( "Before: %s", Bct ); /*15*/ printf( "After: %s", Act ); /*16*/ return 0; /*17*/ } /* ECP: FILEname=fig8_33.c */ /* 1*/ #include /* 2*/ /* The Error Codes. */ /* 3*/ /* Automatically Assigned Starting From 0 */ /* 4*/ enum /* 5*/ { /* 6*/ ErNoMem, /* 7*/ ErOutOfRange, /* 8*/ ErFormat, /* 9*/ ErEOF, /*10*/ ErError /*11*/ }; /*12*/ /* The Corresponding Error Messages */ /*13*/ const char *ErrorMessages[ ] = /*14*/ { /*15*/ "Out of memory", /*16*/ "Input value out of range", /*17*/ "Format error", /*18*/ "Premature end of input", /*19*/ "Bad argument to PrintError" /*20*/ }; /*21*/ static const NumErr = /*22*/ sizeof( ErrorMessages ) / sizeof( char * ); /* 1*/ void /* 2*/ PrintError( int ErrorNum ) /* 3*/ { /* 4*/ if( ErrorNum < 0 || ErrorNum >= NumErr ) /* 5*/ ErrorNum = ErError; /* 6*/ printf( "Error: %s.\n", ErrorMessages[ ErrorNum ] ); /* 7*/ } /* ECP: FILEname=fig8_34.c */ /* 1*/ /* Shellsort An Array Of Strings */ /* 2*/ /* Do Not Move Strings, But Just Pointers */ /* 3*/ void /* 4*/ Shellsort( const char *A[ ], const unsigned int N ) /* 5*/ { /* 6*/ unsigned int Gap; /* 7*/ const char *Tmp; /* 8*/ unsigned int i, j; /* Loop Counters */ /* 9*/ for( Gap = N/2; Gap > 0; Gap = Gap == 2 ? 1 : Gap / 2.2 ) /*10*/ for( i = Gap; i < N; i++ ) /*11*/ { /*12*/ Tmp = A[ i ]; /*13*/ for( j = i; j >= Gap && /*14*/ strcmp( Tmp, A[ j - Gap ] ) < 0; j -= Gap ) /*15*/ A[ j ] = A[ j - Gap ]; /*16*/ A[ j ] = Tmp; /*17*/ } /*18*/ } /* ECP: FILEname=fig8_36.c */ /* 1*/ const char *States[ ] = /* 2*/ { /* 3*/ "alabama", "alaska", "arizona", "arkansas", "california", /* 4*/ "colorado", "connecticut", "delaware", "florida", "georgia", /* 5*/ "hawaii", "idaho", "illinois", "indiana", "iowa", /* 6*/ "kansas", "kentucky", "louisiana", "maine", "maryland", /* 7*/ "massachusetts", "michigan", "minnesota", "mississippi", /* 8*/ "missouri", "montana", "nebraska", "nevada", "newhampshire", /* 9*/ "newjersey", "newmexico", "newyork", "northcarolina", /*10*/ "northdakota", "ohio", "oklahoma", "oregon", "pennsylvania", /*11*/ "rhodeisland", "southcarolina", "southdakota", "tennessee", /*12*/ "texas", "utah", "vermont", "virginia", "washington", /*13*/ "westvirginia", "wisconsin", "wyoming" /*14*/ }; /*15*/ static const NumStates = sizeof States / sizeof( char * ); /* 1*/ /* Return Position Of A String In An Array Of Strings. */ /* 2*/ /* Array Must Be Sorted; return -1 if Not Found. */ /* 3*/ int /* 4*/ BinarySearch( const char *Str, const char *StrArray[ ], /* 5*/ const unsigned int ArrayLen ) /* 6*/ { /* 7*/ int Low = 0, High = ArrayLen - 1; /* 8*/ int Mid; /* 9*/ int Cmp; /*10*/ while( Low <= High ) /*11*/ { /*12*/ Mid = ( Low + High ) / 2; /*13*/ Cmp = strcmp( Str, StrArray[ Mid ] ); /*14*/ if( Cmp < 0 ) /*15*/ High = Mid - 1; /*16*/ else if( Cmp > 0 ) /*17*/ Low = Mid + 1; /*18*/ else /*19*/ return Mid; /*20*/ } /*21*/ return -1; /* Item Not Found */ /*22*/ } /* ECP: FILEname=fig8_38.c */ /* 1*/ #include /* 2*/ #define Pi 3.1416 /* 3*/ #define NoArea ( -1.0 ) /* 4*/ enum { Circle, Rectangle, Square }; /* 5*/ /* Names Must Be in The Same Order As enum List */ /* 6*/ static char *ShapeNames[ ] = /* 7*/ { /* 8*/ "circle", /* 9*/ "rectangle", /*10*/ "square", /*11*/ }; /*12*/ #define DiffShapes ( sizeof ( ShapeNames ) / sizeof( char * ) ) /* ECP: FILEname=fig8_39.c */ /* 1*/ void /* 2*/ PrintShapeName( int i ) /* 3*/ { /* 4*/ if( i < 0 || i >= DiffShapes ) /* 5*/ printf( "unrecognized shape" ); /* 6*/ else /* 7*/ printf( "%s", ShapeNames[ i ] ); /* 8*/ } /* ECP: FILEname=fig8_40.c */ /* 1*/ #define MaxStringLen 80 /* 2*/ #define StrConv1( Len ) ( "%" #Len "s" ) /* 3*/ #define StrConv( Len ) ( StrConv1( Len ) ) /* 4*/ int /* 5*/ GetChoice( void ) /* 6*/ { /* 7*/ int i; /* 8*/ char Str[ MaxStringLen + 1 ]; /* 9*/ if( scanf( StrConv( MaxStringLen ), Str ) == 1 ) /*10*/ for( i = 0; i < DiffShapes; i++ ) /*11*/ if( strcmp( Str, ShapeNames[ i ] ) == 0 ) /*12*/ return i; /*13*/ return -1; /*14*/ } /* ECP: FILEname=fig9_5.c */ /* 1*/ /* Find All Friday The 13th Birthdays */ /* 2*/ /* For Person Born On Nov. 13, 1973 */ /* 3*/ #include /* 4*/ #include /* 5*/ main( void ) /* 6*/ { /* 7*/ const Friday = 6 - 1; /* Sunday Is 0, Etc... */ /* 8*/ struct tm TheTime = { 0 }; /* Set All Fields To 0 */ /* 9*/ int Year; /*10*/ TheTime.tm_mon = 11 - 1; /* January Is 0, Etc... */ /*11*/ TheTime.tm_mday = 13; /* 13th Day Of The Month */ /*12*/ for( Year = 1973; Year < 2073; Year++ ) /*13*/ { /*14*/ TheTime.tm_year = Year - 1900; /* 1900 Is 0, Etc... */ /*15*/ if( mktime( &TheTime ) == -1 ) /*16*/ { /*17*/ printf( "mktime failed in %d\n", Year ); /*18*/ break; /*19*/ } /*20*/ if( TheTime.tm_wday == Friday ) /*21*/ printf( "%s", asctime( &TheTime ) ); /*22*/ } /*23*/ return 0; /*24*/ } /* ECP: FILEname=fig9_6.c */ /* 1*/ typedef enum { Heart, Diamond, Club, Space } SuitType; /* 2*/ typedef struct Card /* 3*/ { /* 4*/ unsigned int FaceVal; /* 5*/ SuitType Suit; /* 6*/ } Card; /* 7*/ /* Constants To Allow Multiple Decks */ /* 8*/ #define Decks 1 /* 9*/ #define CardsPerDeck 52 /*10*/ #define TotalCards ( Decks * CardsPerDeck ) /*11*/ #define MinCards 1 /* Minimum Before New Decks Needed */ /*12*/ #include /* 1*/ /* Discard Old Stack Of Cards And get New Cards */ /* 2*/ void /* 3*/ NewDeck( Card SomeCards[ ], const int NumDecks ) /* 4*/ { /* 5*/ int i, j, k; /* 6*/ /* Load Up All The Cards */ /* 7*/ for( i = 0; i < NumDecks; i++ ) /* 8*/ for( j = 0; j < 13; j++ ) /* 9*/ for( k = 0; k < 4; k++ ) /*10*/ { /*11*/ SomeCards[ 52*i + 4*j + k ].Suit = k; /*12*/ SomeCards[ 52*i + 4*j + k ].FaceVal = j + 1; /*13*/ } /*14*/ /* Shuffle */ /*15*/ for( i = 1; i < TotalCards; i++ ) /*16*/ { /*17*/ int RandCard = rand( ) % ( i + 1 ); /* Choose Random */ /*18*/ Card TmpCard = SomeCards[ i ]; /* Card And Swap */ /*19*/ SomeCards[ i ] = SomeCards[ RandCard ]; /*20*/ SomeCards[ RandCard ] = TmpCard; /*21*/ } /*22*/ } /* ECP: FILEname=fig9_7.c */ /* 1*/ /* Return The Next Card */ /* 2*/ void /* 3*/ Deal( Card *OneCard ) /* 4*/ { /* 5*/ static Card TheCards[ TotalCards ]; /* 6*/ static int CardsUndealt = 0; /* 7*/ if( CardsUndealt < MinCards ) /* 8*/ { /* 9*/ NewDeck( TheCards, Decks ); /*10*/ CardsUndealt = TotalCards; /*11*/ } /*12*/ *OneCard = TheCards[ --CardsUndealt ]; /*13*/ } /* 1*/ /* Get Five Cards */ /* 2*/ void /* 3*/ DealHand( Card Hand[ ] ) /* 4*/ { /* 5*/ int i; /* 6*/ for( i = 0; i < 5; i++ ) /* 7*/ Deal( &Hand[ i ] ); /* 8*/ } /* 1*/ /* Returns Non Zero If All Cards Have Same Suit */ /* 2*/ int /* 3*/ IsFlush( const Card Hand[ ] ) /* 4*/ { /* 5*/ int i; /* 6*/ for( i = 1; i < 5; i++ ) /* 7*/ if( Hand[ i ].Suit != Hand[ 0 ].Suit ) /* 8*/ return 0; /* 9*/ return 1; /*10*/ } /* ECP: FILEname=fig9_8.c */ /* 1*/ int /* 2*/ IsLeap( int Year ) /* 3*/ { /* 4*/ if( Year % 4 ) /* Not Divisible By 4 */ /* 5*/ return 0; /* 6*/ if( Year % 100 ) /* Divisible By 4, But Not 100 */ /* 7*/ return 1; /* 8*/ if( Year % 400 ) /* Divisible By 100, But Not 400 */ /* 9*/ return 0; /*10*/ return 1; /* Divisible By 400 */ /*11*/ } /* ECP: FILEname=fig9_9.c */ /* 1*/ /*Fill In The tm_yday Field, As In mktime */ /* 2*/ int /* 3*/ MkYear( struct tm *TmStruct ) /* 4*/ { /* 5*/ static const int MonthDays[ ] = /* 6*/ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* 7*/ static const int LeapMonthDays[ ] = /* 8*/ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* 9*/ const int *MyMonthDays; /*10*/ int i; /*11*/ if( TmStruct != NULL ) /*12*/ { /*13*/ int Days = ( *TmStruct ).tm_mday; /*14*/ const int Month = ( *TmStruct ).tm_mon; /*15*/ const int Year = ( *TmStruct ).tm_year + 1900; /*16*/ MyMonthDays = IsLeap( Year ) ? LeapMonthDays : MonthDays; /*17*/ if( Month < 0 || Month > 11 || Days < 0 || /*18*/ Days > MyMonthDays[ Month ] ) /*19*/ return -1; /*20*/ for( i = 0; i < Month; i++ ) /*21*/ Days += MyMonthDays[ i ]; /*22*/ ( *TmStruct ).tm_yday = Days; /*23*/ return 0; /*24*/ } /*25*/ return -1; /*26*/ } /* ECP: FILEname=fig9_11.c */ /* 1*/ /*Fill In The tm_yday Field, As In mktime */ /* 2*/ int /* 3*/ MkYear( struct tm *TmStruct ) /* 4*/ { /* 5*/ static const int MonthDays[ ] = /* 6*/ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* 7*/ static const int LeapMonthDays[ ] = /* 8*/ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* 9*/ const int *MyMonthDays; /*10*/ int i; /*11*/ if( TmStruct != NULL ) /*12*/ { /*13*/ int Days = TmStruct->tm_mday; /*14*/ const int Month = TmStruct->tm_mon; /*15*/ const int year = TmStruct->tm_year + 1900; /*16*/ MyMonthDays = IsLeap( year ) ? LeapMonthDays : MonthDays; /*17*/ if( Month < 0 || Month > 11 || Days < 0 || /*18*/ Days > MyMonthDays[ Month ] ) /*19*/ return -1; /*20*/ for( i = 0; i < Month; i++ ) /*21*/ Days += MyMonthDays[ i ]; /*22*/ TmStruct->tm_yday = Days; /*23*/ return 0; /*24*/ } /*25*/ return -1; /*26*/ } /* ECP: FILEname=fig9_12.c */ /* 1*/ typedef struct Block /* 2*/ { /* 3*/ char Junk[ 508 ]; /* 4*/ int Key; /* 5*/ } Block; /* 6*/ struct Block P[ 2000 ]; /* ECP: FILEname=fig9_13.c */ /* 1*/ /* Shellsort An Array Of Blocks. */ /* 2*/ /* Very Slow Because Of Block Copies. */ /* 3*/ void /* 4*/ Shellsort( Block A[ ], const unsigned int N ) /* 5*/ { /* 6*/ unsigned int Gap; /* 7*/ Block Tmp; /* 8*/ unsigned int i, j; /* Loop Counters */ /* 9*/ for( Gap = N/2; Gap > 0; Gap = Gap == 2 ? 1 : Gap / 2.2 ) /*10*/ for( i = Gap; i < N; i++ ) /*11*/ { /*12*/ Tmp = A[ i ]; /*13*/ for( j = i; j >= Gap && /*14*/ Tmp.Key < A[ j - Gap ].Key; j -= Gap ) /*15*/ A[ j ] = A[ j - Gap ]; /*16*/ A[ j ] = Tmp; /*17*/ } /*18*/ } /* ECP: FILEname=fig9_15.c */ /* 1*/ /* Shellsort An Array Of Blocks. */ /* 2*/ /* Uses Only 2N Block Copies. */ /* 3*/ void /* 4*/ Shellsort( Block A[ ], const unsigned int N ) /* 5*/ { /* 6*/ unsigned int Gap; /* 7*/ Block *Tmp; /* 8*/ unsigned int i, j; /* Loop Counters */ /* 9*/ Block **Ptr; /* Array Of Pointers To Block */ /*10*/ Block *ACopy; /* Sorted Array */ /*11*/ /* Allocate And Initialize Pointers for Indirect Sort */ /*12*/ if( ! ( Ptr = malloc( N * sizeof( struct Block * ) ) ) ) /*13*/ Error( "Out of memory" ); /*14*/ if( ! ( ACopy = malloc( N * sizeof( struct Block ) ) ) ) /*15*/ Error( "Out of memory" ); /*16*/ for( i = 0; i < N; i++ ) /*17*/ Ptr[ i ] = &A[ i ]; /*18*/ /* Indirect Shellsort */ /*19*/ for( Gap = N/2; Gap > 0; Gap = Gap == 2 ? 1 : Gap / 2.2 ) /*20*/ for( i = Gap; i < N; i++ ) /*21*/ { /*22*/ Tmp = Ptr[ i ]; /*23*/ for( j = i; j >= Gap && /*24*/ Tmp->Key < Ptr[ j - Gap ]->Key; j -= Gap ) /*25*/ Ptr[ j ] = Ptr[ j - Gap ]; /*26*/ Ptr[ j ] = Tmp; /*27*/ } /*28*/ for( i = 0; i < N; i++ ) /* Make Sorted Array */ /*29*/ ACopy[ i ] = *Ptr[ i ]; /*30*/ for( i = 0; i < N; i++ ) /* Copy It Back */ /*31*/ A[ i ] = ACopy[ i ]; /*32*/ free( ACopy ); free( Ptr ); /* Clean Up */ /*33*/ } /* ECP: FILEname=fig9_16.c */ /* 1*/ /* Shellsort An Array Of Blocks. */ /* 2*/ /* Avoid Excessive Copying And Extra Array Of Blocks */ /* 3*/ void /* 4*/ Shellsort( Block A[ ], const unsigned int N ) /* 5*/ { /* 6*/ unsigned int Gap; /* 7*/ Block *Tmp; /* 8*/ unsigned int i, j, NextJ; /* Loop Counters */ /* 9*/ Block **Ptr; /* Array Of Pointers To Block */ /*10*/ int *Rank; /* Array Listing Correct Final Position */ /*11*/ Block ShuffleTmp; /* Temp for The Final Rearrangement */ /*12*/ /* Allocate And Initialize Pointers for Indirect Sort */ /*13*/ if( ! ( Ptr = malloc( N * sizeof( struct Block * ) ) ) ) /*14*/ Error( "Out of memory" ); /*15*/ if( ( Rank = malloc( N * sizeof( int ) ) ) == NULL ) /*16*/ Error( "Out of memory" ); /*17*/ for( i = 0; i < N; i++ ) /*18*/ Ptr[ i ] = &A[ i ]; /*19*/ /* Indirect Shellsort (Omitted -- Figure 9.15, 19-27) */ /*20*/ /* Determine Correct Positions */ /*21*/ for( i = 0; i < N; i++ ) /*22*/ Rank[ i ] = Ptr[ i ] - &A[ 0 ]; /*23*/ /* Shuffle It Back */ /*24*/ for( i = 0; i < N; i++ ) /*25*/ if( Rank[ i ] != i ) /*26*/ { /*27*/ ShuffleTmp = A[ i ]; /*28*/ for( j = i; Rank[ j ] != i; j = NextJ ) /*29*/ { /*30*/ A[ j ] = A[ Rank[ j ] ]; /*31*/ NextJ = Rank[ j ]; /*32*/ Rank[ j ] = j; /*33*/ } /*34*/ A[ j ] = ShuffleTmp; /*35*/ Rank[ j ] = j; /*36*/ } /*37*/ free( Rank ); free( Ptr ); /* Clean Up */ /*38*/ } /* ECP: FILEname=fig9_18.c */ /* 1*/ /* Shellsort An Array Of Unknowns. */ /* 2*/ /* Uses Only 2N Block Copies. */ /* 3*/ void /* 4*/ Shellsort( void *A, const unsigned int N, const size_t Size, /* 5*/ int Cmp( const void *, const void * ) ) { /* 6*/ unsigned int Gap; /* 7*/ void *Tmp; /* 8*/ unsigned int i, j; /* Loop Counters */ /* 9*/ void **Ptr; /* Array Of Pointers To Unknowns */ /*10*/ void *ACopy; /* Sorted Array */ /*11*/ /* Allocate And Initialize Pointers for Indirect Sort */ /*12*/ if( ( Ptr = malloc( N * sizeof( void * ) ) ) == NULL ) /*13*/ Error( "Out of memory" ); /*14*/ if( ( ACopy = malloc( N * Size ) ) == NULL ) /*15*/ Error( "Out of memory" ); /*16*/ for( i = 0; i < N; i++ ) /*17*/ Ptr[ i ] = A + i * Size; /*18*/ /* Indirect Shellsort */ /*19*/ for( Gap = N/2; Gap > 0; Gap = Gap == 2 ? 1 : Gap / 2.2 ) /*20*/ for( i = Gap; i < N; i++ ) /*21*/ { /*22*/ Tmp = Ptr[ i ]; /*23*/ for( j = i; j >= Gap && /*24*/ Cmp( Tmp, Ptr[ j - Gap ] ) < 0; j -= Gap ) /*25*/ Ptr[ j ] = Ptr[ j - Gap ]; /*26*/ Ptr[ j ] = Tmp; /*27*/ } /*28*/ for( i = 0; i < N; i++ ) /* Make Sorted Array */ /*29*/ memcpy( ACopy + i * Size, Ptr[ i ], Size ); /*30*/ /* Copy It Back */ /*31*/ memcpy( A, ACopy, N * Size ); /*32*/ free( ACopy ); free( Ptr ); /* Clean Up */ /*33*/ } /* ECP: FILEname=fig9_19.c */ /* 1*/ int /* 2*/ Comp( const void *Lhs, const void *Rhs ) /* 3*/ { /* 4*/ int Leftkey = ( ( Block * ) Lhs )->Key; /* 5*/ int Rightkey = ( ( Block * ) Rhs )->Key; /* 6*/ return Leftkey < Rightkey ? -1 : Leftkey != Rightkey; /* 7*/ } /* 8*/ /* ... */ /* 9*/ Shellsort( P, 2000, sizeof( Block ), Comp ); /*10*/ /* ... */ /* ECP: FILEname=fig9_20.c */ /* 1*/ /* Header File With Incomplete struct Declaration */ /* 2*/ typedef struct Complex *Complex; /* 3*/ Complex InitComplex( double Real, double Imag ); /* 4*/ void AddComplex( const Complex A, const Complex B, Complex Sum ); /* 5*/ void PrintComplex( const Complex A ); /* ECP: FILEname=fig9_21.c */ /* 1*/ #include /* 2*/ #include "complex.h" /* 3*/ struct Complex /* 4*/ { /* 5*/ double Real; /* 6*/ double Imag; /* 7*/ }; /* 8*/ void /* 9*/ PrintComplex( const Complex A ) /*10*/ { /*11*/ if( A != NULL ) /*12*/ printf( "%f+%f", A->Real, A->Imag ); /*13*/ else /*14*/ printf( "Uninitialized complex number detected\n" ); /*15*/ } /*16*/ /* InitComplex And AddComplex Are Similar */ /* ECP: FILEname=fig9_22.c */ /* 1*/ #include /* 2*/ #include "complex.h" /* 3*/ main( void ) /* 4*/ { /* 5*/ Complex A, B; /* 6*/ A = InitComplex( 2.0, 4.0 ); /* 7*/ B = InitComplex( 0.0, 0.0 ); /* 8*/ AddComplex( A, A, B ); /* 9*/ printf( "B is: " ); PrintComplex( B ); printf( "\n" ); /*10*/ return 0; /*11*/ } /* ECP: FILEname=fig9_23.c */ /* 1*/ #include /* 2*/ void Help( void ); /* 3*/ void Quit( void ); /* 4*/ void Reset( void ); /* 5*/ void Undo( void ); /* 6*/ typedef struct /* 7*/ { /* 8*/ char *Command; /* 9*/ void ( *Func )( void ); /*10*/ } CommStruct; /*11*/ static const CommStruct TheCommands[ ] = /*12*/ { /*13*/ "exit", Quit, /*14*/ "help", Help, /*15*/ "quit", Quit, /*16*/ "reset", Reset, /*17*/ "undo", Undo, /*18*/ NULL, NULL /* Place Last; No Match */ /*19*/ }; /*20*/ void /*21*/ DoCommand( const char *Comm ) /*22*/ { /*23*/ const CommStruct *Ptr; /*24*/ for( Ptr = TheCommands; Ptr->Command != NULL; Ptr++ ) /*25*/ if( strcmp( Comm, Ptr->Command ) == 0 ) /*26*/ { /*27*/ ( *Ptr->Func )( ); /*28*/ return; /*29*/ } /*30*/ printf( "Error: unrecognized command\n" ); /*31*/ } /* ECP: FILEname=fig9_27.c */ /* 1*/ #ifndef _Shape /* 2*/ #define _Shape /* 3*/ #include /* 4*/ #include /* 5*/ #define Pi 3.1416 /* 6*/ #define MaxStringLen 80 /* 7*/ typedef struct /* 8*/ { /* 9*/ int TheShape; /*10*/ double Area; /*11*/ union /* Stores The Dimensions Of The Object */ /*12*/ { /*13*/ double Radius; /* Circle */ /*14*/ double Side; /* Square */ /*15*/ struct /* Rectangle */ /*16*/ { /*17*/ double Length; /*18*/ double Width; /*19*/ } Rect; /*20*/ } Dimension; /*21*/ } ShapeType; /*22*/ void WriteShape( const ShapeType * Shape ); /*23*/ void AreaShape( ShapeType * Shape ); /*24*/ ShapeType * ReadShape( void ); /*25*/ #endif /* ECP: FILEname=fig9_28.c */ /* 1*/ #include "shape.h" /* 2*/ ShapeType * ReadCircle( void ); /* 3*/ void AreaCircle( ShapeType *Shape ); /* 4*/ void WriteCircle( const ShapeType *Shape ); /* ECP: FILEname=fig9_29.c */ /* 1*/ #include "circle.h" /* 2*/ ShapeType * /* 3*/ ReadCircle( void ) /* 4*/ { /* 5*/ ShapeType *S; /* 6*/ if ( S = malloc( sizeof ( ShapeType ) ) ) /* 7*/ { /* 8*/ printf( "Enter radius: " ); /* 9*/ if( scanf( "%lf", &S->Dimension.Radius ) == 1 ) /*10*/ return S; /*11*/ } /*12*/ return NULL; /*13*/ } /*14*/ void /*15*/ WriteCircle( const ShapeType * Shape ) /*16*/ { /*17*/ printf( "radius %.2f", Shape->Dimension.Radius ); /*18*/ } /*19*/ void /*20*/ AreaCircle( ShapeType * Shape ) /*21*/ { /*22*/ Shape->Area = Pi * Shape->Dimension.Radius /*23*/ * Shape->Dimension.Radius; /*24*/ } /* ECP: FILEname=fig9_30.c */ /* 1*/ /* To Add A New Shape */ /* 2*/ /* 1. Create Appropriate Header And Source */ /* 3*/ /* Read, Write, And Area Functions; */ /* 4*/ /* 2. Update #include Statements Below; */ /* 5*/ /* 3. Adjust typedef Shape */ /* 6*/ /* 7*/ #include "circle.h" /* 8*/ #include "square.h" /* 9*/ #include "rectangle.h" /*10*/ typedef struct /*11*/ { /*12*/ char *ShapeName; /*13*/ ShapeType * ( *ReadShape )( void ); /*14*/ void ( *WriteShape )( const ShapeType *Shape ); /*15*/ void ( *Area )( ShapeType *Shape ); /*16*/ } ShapeSwitch; /*17*/ static ShapeSwitch ShapeTable[ ] = /*18*/ { /*19*/ { "circle", ReadCircle, WriteCircle, AreaCircle }, /*20*/ { "rectangle", ReadRectangle, WriteRectangle, AreaRectangle }, /*21*/ { "square", ReadSquare, WriteSquare, AreaSquare }, /*22*/ { NULL, NULL, NULL, NULL } /*23*/ }; /*24*/ #include /* ECP: FILEname=fig9_31.c */ /* 1*/ #include "table.h" /* 2*/ #define StrConv1( Len ) ( "%" #Len "s" ) /* 3*/ #define StrConv( Len ) ( StrConv1( Len ) ) /* 4*/ ShapeType * /* 5*/ ReadShape( void ) /* 6*/ { /* 7*/ static char InputString[ MaxStringLen + 1 ]; /* 8*/ ShapeSwitch *Ptr; /* 9*/ ShapeType *Shape; /*10*/ printf( "Enter shape type: " ); /*11*/ if( scanf( StrConv( MaxStringLen ), InputString ) == 1 ) /*12*/ for( Ptr = ShapeTable; Ptr->ShapeName; Ptr++ ) /*13*/ if( strcmp( Ptr->ShapeName, InputString ) == 0 ) /*14*/ { /* Found The Type */ /*15*/ if( Shape = ( *Ptr->ReadShape )( ) ) /*16*/ Shape->TheShape = Ptr - ShapeTable; /*17*/ return Shape; /*18*/ } /*19*/ return NULL; /* No Match */ /*20*/ } /*21*/ void /*22*/ WriteShape( const ShapeType * Shape ) /*23*/ { /*24*/ printf( "Shape is a %s ", /*25*/ ShapeTable[ Shape->TheShape ].ShapeName ); /*26*/ ( *ShapeTable[ Shape->TheShape ].WriteShape )( Shape ); /*27*/ printf( "; the area is %.2f\n", Shape->Area ); /*28*/ } /*29*/ void /*30*/ AreaShape( ShapeType * Shape ) /*31*/ { /*32*/ ( *ShapeTable[ Shape->TheShape ].Area )( Shape ); /*33*/ } /* ECP: FILEname=fig9_32.c */ /* 1*/ #include "shape.h" /* 2*/ /* Comparison Function For qsort */ /* 3*/ int /* 4*/ Compare( const void *Left, const void *Right ) /* 5*/ { /* 6*/ ShapeType *LeftShape = * ( ShapeType ** ) Left; /* 7*/ ShapeType *RightShape = * ( ShapeType ** ) Right; /* 8*/ if( LeftShape->TheShape < RightShape->TheShape ) /* 9*/ return -1; /*10*/ else /*11*/ if( LeftShape->TheShape > RightShape->TheShape ) /*12*/ return 1; /*13*/ /* Same Shape */ /*14*/ if( LeftShape->Area < RightShape->Area ) /*15*/ return -1; /*16*/ else /*17*/ if( LeftShape->Area > RightShape->Area ) /*18*/ return 1; /*19*/ else /*20*/ return 0; /*21*/ } /*22*/ /* Read Some Shapes, Sort Them By Area, And Write Them Out */ /*23*/ #define MaxShapes 1000 /*24*/ main( void ) /*25*/ { /*26*/ ShapeType *Shapes[ MaxShapes ]; /*27*/ int ItemsRead, i; /*28*/ for( ItemsRead = 0; ItemsRead < MaxShapes; ItemsRead++ ) /*29*/ if( ( Shapes[ ItemsRead ] = ReadShape( ) ) == NULL ) /*30*/ break; /*31*/ else /*32*/ AreaShape( Shapes[ ItemsRead ] ); /*33*/ printf( "\n" ); /*34*/ qsort( Shapes, ItemsRead, sizeof( ShapeType * ), Compare ); /*35*/ for( i = 0; i < ItemsRead; i++ ) /*36*/ WriteShape( Shapes[ i ] ); /*37*/ return 0; /*38*/ } /* ECP: FILEname=fig9_33.c */ /* 1*/ static const long int A = 48271; /* 2*/ static const long int M = 2147483647; /* 2^31 - 1 */ /* 3*/ static const long int Q = 44488; /* M / A */ /* 4*/ static const long int R = 3399; /* M % A */ /* 5*/ unsigned long int Seed = 1; /* 6*/ unsigned long int /* 7*/ BetterRand( void ) /* 8*/ { /* 9*/ long int TmpSeed; /*10*/ TmpSeed = A * ( Seed % Q ) - R * ( Seed / Q ); /*11*/ if( TmpSeed >= 0 ) /*12*/ Seed = TmpSeed; /*13*/ else /*14*/ Seed = TmpSeed + M; /*15*/ return Seed; /*16*/ } /* ECP: FILEname=fig10_2.c */ /* 1*/ #include /* 2*/ typedef struct /* 3*/ { /* 4*/ int Sym; /* Not A char Because Of getchar */ /* 5*/ int Line; /* 6*/ } Symbol; /* ECP: FILEname=fig10_3.c */ /* 1*/ int /* 2*/ CheckMatch( const Symbol *OpSym, const Symbol *ClSym ) /* 3*/ { /* 4*/ if( OpSym->Sym == '(' && ClSym->Sym == ')' /* 5*/ || OpSym->Sym == '[' && ClSym->Sym == ']' /* 6*/ || OpSym->Sym == '{' && ClSym->Sym == '}' ) /* 7*/ return 0; /* 8*/ printf( "Found %c on line %d;" /* 9*/ " does not match %c at line %d\n", /*10*/ ClSym->Sym, ClSym->Line, OpSym->Sym, OpSym->Line ); /*11*/ return 1; /*12*/ } /* ECP: FILEname=fig10_4.c */ /* 1*/ int /* 2*/ CheckBalance( void ) /* 3*/ { /* 4*/ Stack S = StMakeEmpty( NULL ); /* 5*/ Symbol Last = { 0, 1 }, Match; /* 6*/ int Errors = 0; /* 7*/ while( ( Last.Sym = getchar( ) ) != EOF ) /* 8*/ switch( Last.Sym ) /* 9*/ { /*10*/ case '\n': /*11*/ Last.Line++; /*12*/ break; /*13*/ case '(': case '[': case '{': /*14*/ Push( Last, S ); /*15*/ break; /*16*/ case ')': case ']': case '}': /*17*/ if( StIsEmpty( S ) ) /*18*/ { /*19*/ Errors++; /*20*/ printf( "Extraneous %c at line %d\n", /*21*/ Last.Sym, Last.Line ); /*22*/ } /*23*/ else /*24*/ { /*25*/ Match = Top( S ); Pop( S ); /*26*/ if( CheckMatch( &Match, &Last ) ) /*27*/ Errors++; /*28*/ } /*29*/ break; /*30*/ default: /*31*/ break; /*32*/ } /*33*/ while( !StIsEmpty( S ) ) /* Unmatched Symbols */ /*34*/ { /*35*/ Errors++; /*36*/ Match = Top( S ); Pop( S ); /*37*/ printf( "Unmatched %c at line %d\n", /*38*/ Match.Sym, Match.Line ); /*39*/ } /*40*/ StRecycle( S ); /*41*/ return Errors; /*42*/ } /* ECP: FILEname=fig10_6.c */ /* 1*/ #include /* 2*/ #include /* 3*/ typedef Symbol StEtype; /* 4*/ typedef struct StackStr /* 5*/ { /* 6*/ StEtype *Array; /* The Array Of Elements */ /* 7*/ int TopOfStack; /* Index Of Top Element */ /* 8*/ int MaxSize; /* Maximum Stack Size */ /* 9*/ } *Stack; /*10*/ static const StInitSize = 5; /* 1*/ Stack /* 2*/ StMakeEmpty( Stack S ) /* 3*/ { /* 4*/ if( S == NULL ) /* 5*/ { /* 6*/ if( ! ( S = malloc( sizeof( struct StackStr ) ) ) ) /* 7*/ return NULL; /* 8*/ S->Array = malloc( sizeof( StEtype ) * StInitSize ); /* 9*/ if( S->Array == NULL ) /*10*/ return NULL; /*11*/ S->MaxSize = StInitSize; /*12*/ } /*13*/ S->TopOfStack = -1; /*14*/ return S; /*15*/ } /* 1*/ static void /* 2*/ StInsistGood( const Stack S ) /* 3*/ { /* 4*/ if( S == NULL ) /* 5*/ { /* 6*/ printf( "Stack routine received bad Stack\n" ); /* 7*/ exit( 1 ); /* 8*/ } /* 9*/ } /* ECP: FILEname=fig10_7.c */ /* 1*/ void /* 2*/ StRecycle( Stack S ) /* 3*/ { /* 4*/ StInsistGood( S ); /* 5*/ free( S->Array ); /* 6*/ free( S ); /* 7*/ } /* ECP: FILEname=fig10_8.c */ /* 1*/ int /* 2*/ StIsEmpty( const Stack S ) /* 3*/ { /* 4*/ StInsistGood( S ); /* 5*/ return S->TopOfStack == -1; /* 6*/ } /* 1*/ void /* 2*/ Push( StEtype X, Stack S ) /* 3*/ { /* 4*/ StInsistGood( S ); /* 5*/ if( ++S->TopOfStack == S->MaxSize ) /* 6*/ { /* 7*/ S->MaxSize *= 2; /* 8*/ S->Array = realloc( S->Array, /* 9*/ sizeof( StEtype ) * S->MaxSize ); /*10*/ if( S->Array == NULL ) /*11*/ { /*12*/ printf( "Can not extend the stack\n" ); /*13*/ exit( -1 ); /*14*/ } /*15*/ } /*16*/ S->Array[ S->TopOfStack ] = X; /*17*/ } /* 1*/ void /* 2*/ Pop( Stack S ) /* 3*/ { /* 4*/ if( StIsEmpty( S ) ) /* 5*/ printf( "Error: can not pop an empty stack\n" ); /* 6*/ else /* 7*/ S->TopOfStack--; /* 8*/ } /* 1*/ StEtype /* 2*/ Top( const Stack S ) /* 3*/ { /* 4*/ if( StIsEmpty( S ) ) /* 5*/ printf( "Error: can not top an empty stack\n" ); /* 6*/ else /* 7*/ return S->Array[ S->TopOfStack ]; /* 8*/ } /* ECP: FILEname=fig10_12.c */ /* 1*/ #include /* 2*/ #include /* 3*/ typedef struct /* 4*/ { /* 5*/ int *Array; /* 6*/ int Size; /* 7*/ } SortedInts; /* 1*/ /* Merge Two Sorted Lists. Since SortedInts Is */ /* 2*/ /* A Small Structure We Avoid Pointers */ /* 3*/ SortedInts /* 4*/ MergeTwo( SortedInts struct1, SortedInts struct2 ) /* 5*/ { /* 6*/ int *C; /* 7*/ int *A = struct1.Array, *B = struct2.Array; /* 8*/ int ACtr = 0, BCtr = 0, CCtr = 0; /* 9*/ C = malloc( sizeof( int ) * ( struct1.Size + struct2.Size ) ); /*10*/ if( C == NULL ) /*11*/ { /*12*/ printf( "Can not allocate temporary array\n" ); /*13*/ return struct1; /*14*/ } /*15*/ while( ACtr < struct1.Size && BCtr < struct2.Size ) /*16*/ if( A[ ACtr ] <= B[ BCtr ] ) /*17*/ C[ CCtr++ ] = A[ ACtr++ ]; /*18*/ else /*19*/ C[ CCtr++ ] = B[ BCtr++ ]; /*20*/ while( ACtr < struct1.Size ) /*21*/ C[ CCtr++ ] = A[ ACtr++ ]; /*22*/ while( BCtr < struct2.Size ) /*23*/ C[ CCtr++ ] = B[ BCtr++ ]; /*24*/ free( A ); free( B ); /*25*/ struct1.Size += struct2.Size; /*26*/ struct1.Array = C; /*27*/ return struct1; /*28*/ } /* ECP: FILEname=fig10_13.c */ /* 1*/ SortedInts /* 2*/ MergeM( const SortedInts A[ ], int M ) /* 3*/ { /* 4*/ Queue Q = QuMakeEmpty( NULL ); /* 5*/ SortedInts One, Two, Merged; /* 6*/ int i; /* 7*/ for( i = 0; i < M; i++ ) /* 8*/ Enqueue( A[ i ], Q ); /* 9*/ for( i = 0; i < M-1; i++ ) /*10*/ { /*11*/ Dequeue( &One, Q ); /*12*/ Dequeue( &Two, Q ); /*13*/ Enqueue( MergeTwo( One, Two ), Q ); /*14*/ } /*15*/ Dequeue( &Merged, Q ); /*16*/ QuRecycle( Q ); /*17*/ return Merged; /*18*/ } /* ECP: FILEname=fig10_16.c */ /* 1*/ typedef SortedInts QuEtype; /* 2*/ typedef struct QueueStr /* 3*/ { /* 4*/ QuEtype *Array; /* The Array Of Elements */ /* 5*/ int Front; /* Index Of Front Element */ /* 6*/ int Back; /* Index Of Back Element */ /* 7*/ int Size; /* Current Number Of Elements in Queue */ /* 8*/ int MaxSize; /* Maximum Queue Qize */ /* 9*/ } *Queue; /*10*/ static const QuInitSize = 5; /* 1*/ Queue /* 2*/ QuMakeEmpty( Queue Q ) /* 3*/ { /* 4*/ if( Q == NULL ) /* 5*/ { /* 6*/ if( ! ( Q = malloc( sizeof( struct QueueStr ) ) ) ) /* 7*/ return NULL; /* 8*/ Q->Array = malloc( sizeof( QuEtype ) * QuInitSize ); /* 9*/ if( Q->Array == NULL ) /*10*/ return NULL; /*11*/ Q->MaxSize = QuInitSize; /*12*/ } /*13*/ Q->Size = 0; /*14*/ Q->Front = 0; /*15*/ Q->Back = -1; /*16*/ return Q; /*17*/ } /* ECP: FILEname=fig10_17.c */ /* 1*/ int /* 2*/ QuIsEmpty( const Queue Q ) /* 3*/ { /* 4*/ QuInsistGood( Q ); /* 5*/ return Q->Size == 0; /* 6*/ } /* 1*/ static int /* 2*/ Increment( int QParam, int QSize ) /* 3*/ { /* 4*/ if( ++QParam == QSize ) /* 5*/ return 0; /* 6*/ else /* 7*/ return QParam; /* 8*/ } /* 1*/ void /* 2*/ Dequeue( QuEtype *X, Queue Q ) /* 3*/ { /* 4*/ if( QuIsEmpty( Q ) ) /* 5*/ printf( "Error: can not pop an empty queue\n" ); /* 6*/ else /* 7*/ { /* 8*/ *X = Q->Array[ Q->Front ]; /* 9*/ Q->Front = Increment( Q->Front, Q->MaxSize ); /*10*/ Q->Size--; /*11*/ } /*12*/ } /* ECP: FILEname=fig10_18.c */ /* 1*/ /* After Queue Is Doubled, Arrangement May Be Bad. */ /* 2*/ /* This Routine Fixes It, And Avoids Excessive Moves */ /* 3*/ static void /* 4*/ FixWraparound( Queue Q ) /* 5*/ { /* 6*/ const int OrigSz = Q->MaxSize / 2; /* 7*/ if( Q->Front < OrigSz / 2 ) /* 8*/ { /* 9*/ memcpy( &Q->Array[ OrigSz ], &Q->Array[ 0 ], /*10*/ Q->Front * sizeof( QuEtype ) ); /*11*/ Q->Back += OrigSz; /*12*/ } /*13*/ else /*14*/ { /*15*/ memcpy( &Q->Array[ OrigSz + Q->Front ], /*16*/ &Q->Array[ Q->Front ], /*17*/ ( OrigSz - Q->Front ) * sizeof( QuEtype ) ); /*18*/ Q->Front += OrigSz; /*19*/ } /*20*/ } /*21*/ /* 1*/ void /* 2*/ Enqueue( QuEtype X, Queue Q ) /* 3*/ { /* 4*/ QuInsistGood( Q ); /* 5*/ if( Q->Size == Q->MaxSize ) /* 6*/ { /* 7*/ Q->MaxSize *= 2; /* 8*/ Q->Array = realloc( Q->Array, /* 9*/ sizeof( QuEtype ) * Q->MaxSize ); /*10*/ if( Q->Array == NULL ) /*11*/ { /*12*/ printf( "Can not extend the queue\n" ); /*13*/ exit( -1 ); /*14*/ } /*15*/ if( Q->Front != 0 ) /*16*/ FixWraparound( Q ); /*17*/ } /*18*/ Q->Back = Increment( Q->Back, Q->MaxSize ); /*19*/ Q->Array[ Q->Back ] = X; /*20*/ Q->Size++; /*21*/ } /* ECP: FILEname=fig10_22.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #define NotFound (-1) /* 4*/ typedef struct HashEntry /* 5*/ { /* 6*/ char *Word; /* 7*/ int Num; /* 8*/ } Cell; /* 9*/ typedef struct HashStr /*10*/ { /*11*/ Cell *Array; /* The Array Of Cells */ /*12*/ int Size; /* Current Number Of Elements in Table */ /*13*/ int MaxSize; /* Maximum Table Size */ /*14*/ } *HashTbl; /*15*/ static const HaInitSize = 17; /* 1*/ unsigned int /* 2*/ Hash( const char *Key, const unsigned int TableSize ) /* 3*/ { /* 4*/ unsigned int HashVal = 0; /* 5*/ while( *Key != '\0' ) /* 6*/ HashVal = HashVal * 37 + *Key++; /* 7*/ return HashVal % TableSize; /* 8*/ } /* ECP: FILEname=fig10_23.c */ /* 1*/ HashTbl /* 2*/ HaMakeEmpty( HashTbl H ) /* 3*/ { /* 4*/ int i; /* 5*/ const Cell InitCell = { NULL, NotFound }; /* 6*/ if( H != NULL ) /* 7*/ { /* 8*/ for( i = 0; i < H->MaxSize; i++ ) /* 9*/ { /*10*/ free( H->Array[ i ].Word ); /*11*/ H->Array[ i ].Num = NotFound; /*12*/ } /*13*/ H->Size = 0; /*14*/ return H; /*15*/ } /*16*/ free( H ); /* Safe Even if H == NULL */ /*17*/ if( ( H = malloc( sizeof( struct HashStr ) ) ) == NULL ) /*18*/ return NULL; /*19*/ H->Array = malloc( sizeof( Cell ) * HaInitSize ); /*20*/ if( H->Array == NULL ) /*21*/ return NULL; /*22*/ H->Size = 0; /*23*/ H->MaxSize = HaInitSize; /*24*/ for( i = 0; i < H->MaxSize; i++ ) /*25*/ H->Array[ i ] = InitCell; /*26*/ return H; /*27*/ } /* 1*/ void /* 2*/ HaRecycle( HashTbl H ) /* 3*/ { /* 4*/ int i; /* 5*/ HaInsistGood( H ); /* 6*/ for( i = 0; i < H->MaxSize; i++ ) /* 7*/ free( H->Array[ i ].Word ); /* 8*/ free( H->Array ); /* 9*/ free( H ); /*10*/ } /* ECP: FILEname=fig10_24.c */ /* 1*/ static int /* 2*/ FindPos( const char *Key, const HashTbl H ) /* 3*/ { /* 4*/ unsigned int Pos; /* 5*/ Pos = Hash( Key, H->MaxSize ); /* 6*/ while( H->Array[ Pos ].Num != NotFound && /* 7*/ strcmp( H->Array[ Pos ].Word, Key ) ) /* 8*/ if( ++Pos == H->MaxSize ) /* 9*/ Pos = 0; /*10*/ return Pos; /*11*/ } /* 1*/ int /* 2*/ Find( const char *Key, const HashTbl H ) /* 3*/ { /* 4*/ return H->Array[ FindPos( Key, H ) ].Num; /* 5*/ } /* 1*/ /* Insert A new Key Into H, Making A Duplicate */ /* 2*/ int /* 3*/ Insert( const char *Key, HashTbl H ) /* 4*/ { /* 5*/ unsigned int Pos; /* 6*/ if( H->Size > H->MaxSize / 2 ) /* 7*/ Rehash( H ); /* 8*/ Pos = FindPos( Key, H ); /* 9*/ if( H->Array[ Pos ].Num == NotFound ) /*10*/ { /*11*/ H->Array[ Pos ].Word = Strdup( Key ); /*12*/ H->Array[ Pos ].Num = H->Size++; /*13*/ } /*14*/ return H->Array[ Pos ].Num; /*15*/ } /* ECP: FILEname=fig10_25.c */ /* 1*/ static void /* 2*/ Rehash( HashTbl H ) /* 3*/ { /* 4*/ unsigned int i, Pos, OldSize = H->MaxSize; /* 5*/ Cell *OldArray = H->Array; /* 6*/ const Cell InitCell = { NULL, NotFound }; /* 7*/ H->MaxSize = NextPrime( 2 * OldSize ); /* 8*/ H->Array = malloc( sizeof( Cell ) * H->MaxSize ); /* 9*/ if( H->Array == NULL ) /*10*/ { /*11*/ printf( "Can not rehash\n" ); /*12*/ exit( -1 ); /*13*/ } /*14*/ H->Size = 0; /*15*/ for( i = 0; i < H->MaxSize; i++ ) /*16*/ H->Array[ i ] = InitCell; /*17*/ /* Reinsert Old Elements Into new Table */ /*18*/ for( i = 0; i < OldSize; i++ ) /*19*/ if( OldArray[ i ].Num >= 0 ) /*20*/ { /*21*/ Pos = FindPos( OldArray[ i ].Word, H ); /*22*/ H->Array[ Pos ] = OldArray[ i ]; /*23*/ H->Size++; /*24*/ } /*25*/ free( OldArray ); /*26*/ } /* ECP: FILEname=fig10_27.c */ /* 1*/ typedef int ArEtype; /* 2*/ typedef struct /* 3*/ { /* 4*/ int CurrentSize; /* 5*/ int MaxSize; /* 6*/ ArEtype *Array; /* 7*/ } VarArray; /* 1*/ void /* 2*/ Add( ArEtype X, VarArray *A ) /* 3*/ { /* 4*/ if( A->CurrentSize == A->MaxSize ) /* 5*/ { /* 6*/ if( A->CurrentSize == 0 ) /* 7*/ { /* 8*/ A->MaxSize = 2; /* 9*/ A->Array = malloc( sizeof( ArEtype ) * A->MaxSize ); /*10*/ } /*11*/ else /*12*/ { /*13*/ A->MaxSize *= 2; /*14*/ A->Array = realloc( A->Array, sizeof( ArEtype ) * /*15*/ A->MaxSize ); /*16*/ } /*17*/ if( A->Array == NULL ) /*18*/ { /*19*/ printf( "Out of space\n" ); /*20*/ exit( -1 ); /*21*/ } /*22*/ } /*23*/ A->Array[ A->CurrentSize++ ] = X; /*24*/ } /* ECP: FILEname=fig10_28.c */ /* 1*/ typedef int DisType; /* 2*/ #define Infinity IntMax /* 3*/ #define MaxNodes 3000 /* 4*/ typedef struct /* Basic Vertex Structure */ /* 5*/ { /* 6*/ char *NodeName; /* Name */ /* 7*/ DisType Distance; /* Distance From Start */ /* 8*/ int PreviousNode; /* Previous Vertex On Path */ /* 9*/ VarArray Adj; /* List Of Adjacent Vertices */ /*10*/ } Vertex; /* 1*/ int /* 2*/ AddNode( const char *Name, HashTbl H, Vertex Graph[ ] ) /* 3*/ { /* 4*/ int NodeNum; /* 5*/ const Vertex NewVert = { NULL, Infinity, -1, { 0, 0, NULL } }; /* 6*/ if( ( NodeNum = Find( Name, H ) ) < 0 ) /* 7*/ { /* 8*/ NodeNum = Insert( Name, H ); /* 9*/ if( NodeNum == MaxNodes ) /*10*/ { /*11*/ printf( "Graph is full. Increase MaxNodes\n" ); /*12*/ exit( -1 ); /*13*/ } /*14*/ Graph[ NodeNum ] = NewVert; /*15*/ Graph[ NodeNum ].NodeName = Strdup( Name ); /*16*/ } /*17*/ return NodeNum; /*18*/ } /* 1*/ void /* 2*/ AddEdge( int Source, int Dest, Vertex Graph[ ] ) /* 3*/ { /* 4*/ Add( Dest, &Graph[ Source ].Adj ); /* 5*/ } /* ECP: FILEname=fig10_29.c */ /* 1*/ #define MaxNodeLen 80 /* 2*/ typedef char NodeName[ MaxNodeLen + 1 ]; /* 3*/ const char *Term = "##"; /* 4*/ void /* 5*/ ReadGraph( Vertex Graph[ ], HashTbl H ) /* 6*/ { /* 7*/ NodeName Source, Dest; /* 8*/ int RetVal; /* 9*/ while( ( RetVal = GetTwoStrings( Source, Dest, MaxNodeLen ) ) /*10*/ > 0 ) /*11*/ { /*12*/ if( RetVal != 2 ) /*13*/ printf( "Warning: skipped an input line\n" ); /*14*/ else /*15*/ if( !strcmp( Source, Term ) && !strcmp( Dest, Term ) ) /*16*/ return; /*17*/ else /*18*/ AddEdge( AddNode( Source, H, Graph ), /*19*/ AddNode( Dest, H, Graph ), Graph ); /*20*/ } /*21*/ printf( "Input terminated early???\n" ); /*22*/ } /* ECP: FILEname=fig10_30.c */ /* 1*/ void /* 2*/ PrintPath( int DestNode, const Vertex Graph[ ] ) /* 3*/ { /* 4*/ Stack S = StMakeEmpty( NULL ); /* 5*/ int Intermediate; /* 6*/ if( Graph[ DestNode ].Distance == Infinity ) /* 7*/ printf( "%s unreachable\n", Graph[ DestNode ].NodeName ); /* 8*/ else /* 9*/ { /*10*/ Intermediate = Graph[ DestNode ].PreviousNode; /*11*/ while( Intermediate != -1 ) /*12*/ { /*13*/ Push( Intermediate, S ); /*14*/ Intermediate = Graph[ Intermediate ].PreviousNode; /*15*/ } /*16*/ while( !StIsEmpty( S ) ) /*17*/ { /*18*/ printf( "%s to ", Graph[ Top( S ) ].NodeName ); /*19*/ Pop( S ); /*20*/ } /*21*/ printf( "%s\n", Graph[ DestNode ].NodeName ); /*22*/ } /*23*/ StRecycle( S ); /*24*/ } /* ECP: FILEname=fig10_31.c */ /* 1*/ void /* 2*/ ProcessRequests( Vertex Graph[ ], HashTbl H ) /* 3*/ { /* 4*/ NodeName Source, Dest; /* 5*/ int SourceNum, DestNum; /* 6*/ int RetVal; /* 7*/ while( ( RetVal = GetTwoStrings( Source, Dest, MaxNodeLen ) ) /* 8*/ > 0 ) /* 9*/ { /*10*/ if( RetVal != 2 ) /*11*/ { /*12*/ printf( "Format error: skipping this line\n" ); /*13*/ continue; /*14*/ } /*15*/ SourceNum = Find( Source, H ); /*16*/ DestNum = Find( Dest, H ); /*17*/ if( SourceNum == -1 || DestNum == -1 ) /*18*/ printf( "Illegal vertex specified\n" ); /*19*/ else /*20*/ { /*21*/ EvaluateShort( SourceNum, Graph ); /*22*/ PrintPath( DestNum, Graph ); /*23*/ } /*24*/ } /*25*/ } /* 1*/ main( void ) /* 2*/ { /* 3*/ HashTbl H = HaMakeEmpty( NULL ); /* 4*/ Vertex G[ MaxNodes + 1 ]; /* 5*/ ReadGraph( G, H ); /* 6*/ ProcessRequests( G, H ); /* 7*/ return 0; /* 8*/ } /* ECP: FILEname=fig10_32.c */ /* 1*/ void /* 2*/ EvaluateShort( int StartNode, Vertex Graph[ ] ) /* 3*/ { /* 4*/ int i, V, W; /* 5*/ Queue Q = QuMakeEmpty( NULL ); /* 6*/ for( i = 0; Graph[ i ].NodeName != NULL; i++ ) /* 7*/ { /* 8*/ Graph[ i ].Distance = Infinity; /* 9*/ Graph[ i ].PreviousNode = -1; /*10*/ } /*11*/ Graph[ StartNode ].Distance = 0; /*12*/ Enqueue( StartNode, Q ); /*13*/ while( !QuIsEmpty( Q ) ) /*14*/ { /*15*/ Dequeue( &V, Q ); /*16*/ for( i = 0; i < Graph[ V ].Adj.CurrentSize; i++ ) /*17*/ { /*18*/ W = Graph[ V ].Adj.Array[ i ]; /*19*/ if( Graph[ W ].Distance == Infinity ) /*20*/ { /*21*/ Graph[ W ].Distance = Graph[ V ].Distance + 1; /*22*/ Graph[ W ].PreviousNode = V; /*23*/ Enqueue( W, Q ); /*24*/ } /*25*/ } /*26*/ } /*27*/ QuRecycle( Q ); /*28*/ } /* ECP: FILEname=fig10_33.c */ /* 1*/ typedef struct Cell /* 2*/ { /* 3*/ int Number; /* 4*/ struct Cell *Next; /* 5*/ } CellType; /* 6*/ CellType * /* 7*/ GetCell( int CellNo ) /* 8*/ { /* 9*/ CellType *CellPtr = malloc( sizeof( CellType ) ); /*10*/ if( CellPtr == NULL ) /*11*/ Error( "Out of memory" ); /*12*/ CellPtr->Number = CellNo; /*13*/ return CellPtr; /*14*/ } /*15*/ int /*16*/ Jos( int People, int Passes ) /*17*/ { /*18*/ CellType *BeforeBall, *Last, *First, *Loser; /*19*/ int i; /*20*/ /* Create The List */ /*21*/ First = Last = GetCell( 1 ); /*22*/ for( i = 2; i <= People; i++ ) /*23*/ Last = Last->Next = GetCell( i ); /*24*/ Last->Next = First; /* Make List Circular */ /*25*/ for( BeforeBall = Last; People != 1; People-- ) /*26*/ { /*27*/ /* Pass The Ball */ /*28*/ for( i = 0; i < Passes; i++ ) /*29*/ BeforeBall = BeforeBall->Next; /*30*/ /* Remove A Player */ /*31*/ Loser = BeforeBall->Next; /*32*/ BeforeBall->Next = Loser->Next; /*33*/ free( Loser ); /* See Text Warning */ /*34*/ } /*35*/ return BeforeBall->Number; /*36*/ } /* ECP: FILEname=fig11_1.c */ /* 1*/ /* Compute Sum Of The First N Integers Recursively */ /* 2*/ unsigned long int /* 3*/ Sum( unsigned int N ) /* 4*/ { /* 5*/ if( N == 1 ) /* Base Case */ /* 6*/ return 1; /* 7*/ else /* Recursive Call */ /* 8*/ return Sum( N - 1 ) + N; /* 9*/ } /* ECP: FILEname=fig11_2.c */ /* 1*/ /* Print N As A Decimal Number */ /* 2*/ void /* 3*/ PrintDecimal( unsigned int N ) /* 4*/ { /* 5*/ if( N >= 10 ) /* 6*/ PrintDecimal( N / 10 ); /* 7*/ putchar( '0' + N % 10 ); /* 8*/ } /* ECP: FILEname=fig11_3.c */ /* 1*/ /* Print N In Any Base */ /* 2*/ /* Assumes 2 <= Base <= 16 */ /* 3*/ void /* 4*/ PrintInt( unsigned int N, unsigned int Base ) /* 5*/ { /* 6*/ static char DigitTable[ ] = "0123456789abcdef"; /* 7*/ if( N >= Base ) /* 8*/ PrintInt( N / Base, Base ); /* 9*/ putchar( DigitTable[ N % Base ] ); /*10*/ } /* ECP: FILEname=fig11_4.c */ /* 1*/ /* Print N In Any Base */ /* 2*/ static char DigitTable[ ] = "0123456789abcdef"; /* 3*/ static const MaxBase = sizeof( DigitTable ) - 1; /* 4*/ static void /* 5*/ PrintInt1( unsigned int N, unsigned int Base ) /* 6*/ { /* 7*/ if( N >= Base ) /* 8*/ PrintInt1( N / Base, Base ); /* 9*/ putchar( DigitTable[ N % Base ] ); /*10*/ } /*11*/ void /*12*/ PrintInt( unsigned int N, unsigned int Base ) /*13*/ { /*14*/ if( Base <= 1 || Base > MaxBase ) /*15*/ printf( "Can not print in base %u\n", Base ); /*16*/ else /*17*/ PrintInt1( N, Base ); /*18*/ } /* ECP: FILEname=fig11_5.c */ /* 1*/ /* PrintPath Is A Driver; PrintPath1 Does The Real Work */ /* 2*/ static void /* 3*/ PrintPath1( int DestNode, const Vertex Graph[ ] ) /* 4*/ { /* 5*/ if( Graph[ DestNode ].PreviousNode != -1 ) /* 6*/ { /* 7*/ PrintPath1( Graph[ DestNode ].PreviousNode, Graph ); /* 8*/ printf( " to " ); /* 9*/ } /*10*/ printf( "%s", Graph[ DestNode ].NodeName ); /*11*/ } /* 1*/ void /* 2*/ PrintPath( int DestNode, const Vertex Graph[ ] ) /* 3*/ { /* 4*/ if( Graph[ DestNode ].Distance == Infinity ) /* 5*/ printf( "%s unreachable", Graph[ DestNode ].NodeName ); /* 6*/ else /* 7*/ PrintPath1( DestNode, Graph ); /* 8*/ printf( "\n" ); /* 9*/ } /* ECP: FILEname=fig11_6.c */ /* 1*/ /* Compute The N th Fibonacci Number */ /* 2*/ /* Bad Algorithm */ /* 3*/ unsigned long int /* 4*/ Fib( unsigned int N ) /* 5*/ { /* 6*/ if( N <= 1 ) /* 7*/ return N; /* 8*/ else /* 9*/ return Fib( N - 1 ) + Fib( N - 2 ); /*10*/ } /* ECP: FILEname=fig11_7.c */ /* 1*/ /* Compute X^N ( Mod P ) */ /* 2*/ HugeInt /* 3*/ Power( const HugeInt X, const HugeInt N, const HugeInt P ) /* 4*/ { /* 5*/ HugeInt Tmp; /* 6*/ if( N == 0 ) /* 7*/ return 1; /* 8*/ Tmp = Power( ( X * X ) % P, N / 2, P ); /* 9*/ /*10*/ if( N % 2 ) /*11*/ Tmp = ( Tmp * X ) % P; /*12*/ return Tmp; /*13*/ } /* ECP: FILEname=fig11_8.c */ /* 1*/ /* If Witness Does Not return 1, N Is Definitely Composite */ /* 2*/ /* Do This By Computing A^i ( Mod N ) And Look For */ /* 3*/ /* Non-Trivial Square Roots Of 1 Along The Way */ /* 4*/ HugeInt /* 5*/ Witness( const HugeInt A, const HugeInt i, const HugeInt N ) /* 6*/ { /* 7*/ HugeInt X, Y; /* 8*/ if( i == 0 ) /* 9*/ return 1; /*10*/ X = Witness( A, i / 2, N ); /*11*/ if( X == 0 ) /* If N Is Recursively Composite, Stop */ /*12*/ return 0; /*13*/ /* N Is Not Prime if We Find A Non-Trivial Root Of 1 */ /*14*/ Y = ( X * X ) % N; /*15*/ if( Y == 1 && X != 1 && X != N - 1 ) /*16*/ return 0; /*17*/ if( i % 2 ) /*18*/ Y = ( A * Y ) % N; /*19*/ return Y; /*20*/ } /* 1*/ /* Make NumTrials Call To Witness To Check if N Is Prime */ /* 2*/ int /* 3*/ IsPrime( const HugeInt N ) /* 4*/ { /* 5*/ const int NumTrials = 5; /* 6*/ int Counter; /* 7*/ for( Counter = 0; Counter < NumTrials; Counter++ ) /* 8*/ if( Witness( RandInt( 2, N - 2 ), N - 1, N ) != 1 ) /* 9*/ return 0; /*10*/ return 1; /*11*/ } /* ECP: FILEname=fig11_9.c */ /* 1*/ HugeInt /* 2*/ Gcd( const HugeInt A, const HugeInt B ) /* 3*/ { /* 4*/ if( B == 0 ) /* 5*/ return A; /* 6*/ else /* 7*/ return Gcd( B, A % B ); /* 8*/ } /* ECP: FILEname=fig11_10.c */ /* 1*/ /* Given A And B, Assume Gcd( A, B ) = 1 */ /* 2*/ /* Find X And Y Such That A X + B Y = 1 */ /* 3*/ void /* 4*/ FullGcd( const HugeInt A, const HugeInt B, HugeInt *X, HugeInt *Y ) /* 5*/ { /* 6*/ HugeInt X1, Y1; /* 7*/ if( B == 0 ) /* 8*/ { /* 9*/ *X = 1; /* If A != 1, There Is No Inverse */ /*10*/ *Y = 0; /* We Omit this Check */ /*11*/ } /*12*/ else /*13*/ { /*14*/ FullGcd( B, A % B, &X1, &Y1 ); /*15*/ *X = Y1; /*16*/ *Y = X1 - ( A / B ) * Y1; /*17*/ } /*18*/ } /* 1*/ /* Solve A X == 1 ( Mod N ) */ /* 2*/ /* Assume That Gcd( A, N ) = 1 */ /* 3*/ HugeInt /* 4*/ Inverse( const HugeInt A, const HugeInt N ) /* 5*/ { /* 6*/ HugeInt X, Y; /* 7*/ FullGcd( A, N, &X, &Y ); /* 8*/ return X > 0 ? X : X + N; /* 9*/ } /* ECP: FILEname=fig11_12.c */ /* 1*/ /* Return Position Of X in A */ /* 2*/ int /* 3*/ BinarySearch1( const char *A[ ], const char *X, int Low, int High ) /* 4*/ { /* 5*/ int Mid = ( Low + High ) / 2 ; /* 6*/ int Cmp; /* 7*/ if( Low > High ) /* Not Found */ /* 8*/ return -1; /* 9*/ if( ( Cmp = strcmp( X, A[ Mid ] ) ) < 0 ) /* X < A[ Mid ] */ /*10*/ return BinarySearch1( A, X, Low, Mid - 1 ); /*11*/ if( Cmp > 0 ) /* X > A[ Mid ] */ /*12*/ return BinarySearch1( A, X, Mid + 1, High ); /*13*/ return Mid; /* X = A[ Mid ] */ /*14*/ } /*15*/ int /*16*/ BinarySearch( const char *A[ ], const char *X, int N ) /*17*/ { /*18*/ return BinarySearch1( A, X, 0, N - 1 ); /*19*/ } /* ECP: FILEname=fig11_14.c */ /* 1*/ typedef struct TreeNode *Tree; /* 2*/ typedef struct TreeNode /* 3*/ { /* 4*/ char *Item; /* The Item */ /* 5*/ int Count; /* Frequency Of Occurrence */ /* 6*/ Tree Left; /* Left Tree, Recursively Defined */ /* 7*/ Tree Right; /* Right Tree, Recursively Defined */ /* 8*/ } TreeNode; /* ECP: FILEname=fig11_15.c */ /* 1*/ /* Return A Pointer To Node Storing X if X Is Found */ /* 2*/ TreeNode * /* 3*/ Find( const Tree Root, const char *X ) /* 4*/ { /* 5*/ int Cmp; /* 6*/ if( Root == NULL ) /* Not Found */ /* 7*/ return NULL; /* 8*/ if( ( Cmp = strcmp( X, Root->Item ) ) < 0 ) /* 9*/ return Find( Root->Left, X ); /* X < Root->Item */ /*10*/ if( Cmp > 0 ) /*11*/ return Find( Root->Right, X ); /* X > Root->Item */ /*12*/ return Root->Count ? Root : NULL; /* X = Root->Item */ /*13*/ } /* ECP: FILEname=fig11_16.c */ /* 1*/ void /* 2*/ Remove( Tree Root, const char *X ) /* 3*/ { /* 4*/ int Cmp; /* 5*/ if( Root == NULL ) /* Not Found */ /* 6*/ return; /* Do Nothing */ /* 7*/ else if( ( Cmp = strcmp( X, Root->Item ) ) < 0 ) /* 8*/ Remove( Root->Left, X ); /* 9*/ else if( Cmp > 0 ) /*10*/ Remove( Root->Right, X ); /*11*/ else if( Root->Count > 0 ) /*12*/ Root->Count--; /*13*/ } /* ECP: FILEname=fig11_17.c */ /* 1*/ Tree /* 2*/ Insert( Tree Root, const char *X ) /* 3*/ { /* 4*/ int Cmp; /* 5*/ if( Root == NULL ) /* Spot Found */ /* 6*/ { /* 7*/ Root = malloc( sizeof( struct TreeNode ) ); /* 8*/ if( Root == NULL || ! ( Root->Item = Strdup( X ) ) ) /* 9*/ Error( "Out of space!!" ); /*10*/ Root->Count = 1; /*11*/ Root->Left = Root->Right = NULL; /*12*/ } /*13*/ else /* X < Root->Item */ /*14*/ if( ( Cmp = strcmp( X, Root->Item ) ) < 0 ) /*15*/ Root->Left = Insert( Root->Left, X ); /*16*/ else /*17*/ if( Cmp > 0 ) /* X > Root->Item */ /*18*/ Root->Right = Insert( Root->Right, X ); /*19*/ else /*20*/ Root->Count++; /* X Was Previously Seen */ /*21*/ return Root; /*22*/ } /* ECP: FILEname=fig11_18.c */ /* 1*/ void /* 2*/ PrintInOrder( const Tree T ) /* 3*/ { /* 4*/ if( T != NULL ) /* 5*/ { /* 6*/ PrintInOrder( T->Left ); /* 7*/ if( T->Count ) /* 8*/ printf( "%s occurs %d times\n", T->Item, T->Count ); /* 9*/ PrintInOrder( T->Right ); /*10*/ } /*11*/ } /* ECP: FILEname=fig11_21.c */ /* 1*/ static void /* 2*/ QuickSort1( ElementType A[ ], int Low, int High ) /* 3*/ { /* 4*/ int PivotPos; /* 5*/ if( Low < High ) /* 6*/ { /* 7*/ PivotPos = Partition( A, Low, High ); /* 8*/ QuickSort1( A, Low, PivotPos - 1 ); /* 9*/ QuickSort1( A, PivotPos + 1, High ); /*10*/ } /*11*/ } /* 1*/ void /* 2*/ QuickSort( ElementType A[ ], const unsigned int N ) /* 3*/ { /* 4*/ QuickSort1( A, ( int ) 0, ( int ) N - 1 ); /* 5*/ } /* ECP: FILEname=fig11_23.c */ /* 1*/ #define SwapElements( i, j ) \ /* 2*/ { ElementType Tmp = A[ i ]; A[ i ] = A[ j ]; A[ j ] = Tmp; } /* 3*/ static int /* 4*/ Partition( ElementType A[ ], int Low, int High ) /* 5*/ { /* 6*/ int Center = ( Low + High ) / 2; /* 7*/ const ElementType Pivot = A[ Center ]; /* 8*/ int i = Low - 1, j = High; /* 9*/ SwapElements( Center, High ); /*10*/ for( ; ; ) /*11*/ { /*12*/ while( A[ ++i ] < Pivot ) /* Find A "large" Element */ /*13*/ ; /* i < High Is Guaranteed */ /*14*/ while( A[ --j ] > Pivot ) /* Find A "small" Element */ /*15*/ if( j == 0 ) /* Don't run off the end! */ /*16*/ break; /*17*/ if( i >= j ) /*18*/ break; /*19*/ /* Invariant: i < j, A[ i ] >= Pivot, A[ j ] <= Pivot */ /*20*/ SwapElements( i, j ); /*21*/ } /*22*/ SwapElements( i, High ); /*23*/ return i; /*24*/ } /* ECP: FILEname=fig11_24.c */ /* 1*/ /* Find The Best Move, And return Its Value */ /* 2*/ /* Assumes: Humanwin < Draw < Computerwin */ /* 3*/ int /* 4*/ ChooseMove( BoardType B, Side S, int *BestRow, int *BestColumn ) /* 5*/ { /* 6*/ Side Opp; /* The Opponent */ /* 7*/ int Reply; /* Value Of Opponent's Reply */ /* 8*/ int Value; /* Value Of Best Move, So Far */ /* 9*/ Piece Mypiece; /* Piece Corresponding To Side S */ /*10*/ int Row, Column; /* Counters */ /*11*/ int Z; /* Placeholder */ /*12*/ int SimpleEval; /* Result Of A Simple Evaluation */ /*13*/ if( ( SimpleEval = Terminal( B ) ) != Unclear ) /*14*/ return SimpleEval; /* Immediate Win, Lose, Or Draw */ /*15*/ /* Set Some Variables Depending On Who S Is */ /*16*/ if( S == Me ) /*17*/ { /*18*/ Opp = You; Value = HumanWin; Mypiece = Computer; /*19*/ } /*20*/ else /*21*/ { /*22*/ Opp = Me; Value = ComputerWin; Mypiece = Human; /*23*/ } /*24*/ /* Search for A Move */ /*25*/ for( Row = 0; Row < Bsize; Row++ ) /*26*/ for( Column = 0; Column < Bsize; Column++ ) /*27*/ if( IsEmpty( B, Row, Column ) ) /*28*/ { /*29*/ Place( B, Row, Column, Mypiece ); /*30*/ Reply = ChooseMove( B, Opp, &Z, &Z ); /*31*/ Unplace( B, Row, Column ); /*32*/ /* Test if S Gets A Better Position */ /*33*/ /* If So, Update */ /*34*/ if( S == Me && Reply > Value || /*35*/ S == You && Reply < Value ) /*36*/ { /*37*/ Value = Reply; /*38*/ *BestRow = Row; *BestColumn = Column; /*39*/ } /*40*/ } /*41*/ return Value; /*42*/ } /* ECP: FILEname=fig11_25.c */ /* 1*/ /* Same As ChooseMove, But Use Alpha Beta Pruning. */ /* 2*/ int /* 3*/ Choose( BoardType B, Side S, int *BestRow, int *BestColumn, /* 4*/ int Alpha, int Beta ) /* 5*/ { /*14*/ /* Up To Here, Everything Is Identical... */ /*15*/ /* Set Some Variables Depending On Who S Is */ /*16*/ if( S == Me ) /*17*/ { /*18*/ Opp = You; Value = Alpha; Mypiece = Computer; /*19*/ } /*20*/ else /*21*/ { /*22*/ Opp = Me; Value = Beta; Mypiece = Human; /*23*/ } /*24*/ /* Search for A Move */ /*25*/ for( Row = 0; Row < Bsize; Row++ ) /*26*/ for( Column = 0; Column < Bsize; Column++ ) /*27*/ if( IsEmpty( B, Row, Column ) ) /*28*/ { /*29*/ Place( B, Row, Column, Mypiece ); /*30*/ if( S == Me ) /*31*/ { /*32*/ Reply = Choose( B, Opp, &Z, &Z, Value, Beta ); /*33*/ Unplace( B, Row, Column ); /*34*/ if( Reply > Value ) /*35*/ { /*36*/ *BestRow = Row; *BestColumn = Column; /*37*/ if( ( Value = Reply ) >= Beta ) /*38*/ return Value; /* Refutation Found */ /*39*/ } /*40*/ } /*41*/ else /*42*/ { /*43*/ Reply = Choose( B, Opp, &Z, &Z, Alpha, Value ); /*44*/ Unplace( B, Row, Column ); /*45*/ if( Reply < Value ) /*46*/ { /*47*/ *BestRow = Row; *BestColumn = Column; /*48*/ if( ( Value = Reply ) <= Alpha ) /*49*/ return Value; /* Refutation Found */ /*50*/ } /*51*/ } /*52*/ } /*53*/ return Value; /*54*/ } /* ECP: FILEname=fig12_6.c */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ double X; /* 5*/ scanf( "%f", &X ); /* 3 */ /* 6*/ printf( "%f\n", X ); /* 32.000000 */ /* 7*/ printf( "%lf\n", X ); /* Undefined */ /* 8*/ scanf( "%lf", &X ); /* 3 */ /* 9*/ printf( "%f\n", X ); /* 3.000000 */ /*10*/ printf( "%lf\n", X ); /* Undefined */ /*11*/ return 0; /*12*/ } /* ECP: FILEname=fig12_7.c */ /* 1*/ /* Read A Bunch Of Integers */ /* 2*/ /* Wrong Way To Check for Errors */ /* 3*/ #include /* 4*/ main( void ) /* 5*/ { /* 6*/ int X, ArgsMatched; /* 7*/ for( ; ; ) /* 8*/ { /* 9*/ printf( "Enter an integer: " ); /*10*/ ArgsMatched = scanf( "%d", &X ); /*11*/ if( ArgsMatched == 0 ) /*12*/ { /*13*/ printf( "You did not enter an integer... \n" ); /*14*/ continue; /* Wrong: No Digestion Of Input */ /*15*/ } /*16*/ else /*17*/ if( ArgsMatched == 1 ) /*18*/ printf( "Read %d\n", X ); /*19*/ else /*20*/ break; /* EOF */ /*21*/ } /*22*/ return 0; /*23*/ } /* ECP: FILEname=fig12_9.c */ /* 1*/ void /* 2*/ SkipLine( void ) /* 3*/ { /* 4*/ scanf( "%*[^\n]" ); /* Skip To The End Of The Line */ /* 5*/ scanf( "%*1[\n]" ); /* Skip One Newline */ /* 6*/ } /* ECP: FILEname=fig12_12.c */ /* 1*/ /* Skip Over Current Lines And Any Subsequent Blank Lines */ /* 2*/ void /* 3*/ SkipLines( FILE *Fp ) /* 4*/ { /* 5*/ int Ch; /* 6*/ while( ( Ch = getc( Fp ) ) != EOF ) /* 7*/ if( Ch == '\n' ) /* End Of Current Line */ /* 8*/ { /* 9*/ /* Skip Over Newlines */ /*10*/ while( ( Ch = getc( Fp ) ) != EOF && Ch == '\n' ) /*11*/ ; /*12*/ /* Push Back Non-Newline */ /*13*/ if( Ch != EOF ) /*14*/ ungetc( Ch, Fp ); /*15*/ break; /*16*/ } /*17*/ } /* ECP: FILEname=fig12_13.c */ /* 1*/ #include /* 2*/ #include /* 3*/ /* Copy From Sourcefile To Destfile And return The Number */ /* 4*/ /* Of Characters Copied; -1 For Errors */ /* 5*/ int /* 6*/ Copy( const char *DestFile, const char *SourceFile ) /* 7*/ { /* 8*/ int CharsCounted = 0; /* 9*/ int Ch; /*10*/ FILE *Sfp, *Dfp; /*11*/ if( strcmp( SourceFile, DestFile ) == 0 ) /*12*/ { /*13*/ printf( "Can not copy to self\n" ); /*14*/ return -1; /*15*/ } /*16*/ if( ( Sfp = fopen( SourceFile, "r" ) ) == NULL ) /*17*/ { /*18*/ printf( "Can not open input file %s\n", SourceFile ); /*19*/ return -1; /*20*/ } /*21*/ if( ( Dfp = fopen( DestFile, "w" ) ) == NULL ) /*22*/ { /*23*/ printf( "Can not open output file %s\n", DestFile ); /*24*/ fclose( Sfp ); return -1; /*25*/ } /*26*/ while( ( Ch = getc( Sfp ) ) != EOF ) /*27*/ if( putc( Ch, Dfp ) == EOF ) /*28*/ { /*29*/ printf( "Unexpected error during write.\n" ); /*30*/ break; /*31*/ } /*32*/ else /*33*/ CharsCounted++; /*34*/ fclose( Sfp ); /*35*/ fclose( Dfp ); /*36*/ return CharsCounted; /*37*/ } /* ECP: FILEname=fig12_14.c */ /* 1*/ struct utmp { /* 2*/ char ut_line[ 8 ]; /* Tty Name */ /* 3*/ char ut_name[ 8 ]; /* User Id */ /* 4*/ char ut_host[ 16 ]; /* Host Name, if Remote */ /* 5*/ long ut_time; /* Time On */ /* 6*/ }; /* ECP: FILEname=fig12_15.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ static const char *Wtmp = "/var/adm/wtmp"; /* 5*/ static const UtmpSize = sizeof( struct utmp ); /* 6*/ #define NameLen 8 /* 7*/ #define LineLen 8 /* 8*/ int /* 9*/ Logins( const char *SearchName ) /*10*/ { /*11*/ int HowMany = 0; /*12*/ struct utmp UtEntry; /*13*/ FILE *Ufp; /*14*/ if( ( Ufp = fopen( Wtmp, "rb" ) ) == NULL ) /*15*/ { /*16*/ fprintf( stderr, "Can not open %s\n", Wtmp ); /*17*/ return -1; /*18*/ } /*19*/ while( fread( &UtEntry, UtmpSize, 1, Ufp ) == 1 ) /*20*/ { /*21*/ char Name[ NameLen + 1 ] = "", Line[ LineLen + 1 ] = ""; /*22*/ if( strncmp( UtEntry.ut_name, SearchName, NameLen ) == 0 ) /*23*/ { /*24*/ strncpy( Name, UtEntry.ut_name, NameLen ); /*25*/ strncpy( Line, UtEntry.ut_line, LineLen ); /*26*/ printf( "%-*s %-*s %26s", NameLen, Name, LineLen, /*27*/ Line, ctime( &UtEntry.ut_time ) ); /*28*/ HowMany++; /*29*/ } /*30*/ } /*31*/ fclose( Ufp ); /*32*/ return HowMany; /*33*/ } /* ECP: FILEname=fig12_16.c */ /* 1*/ #include /* 2*/ #include /* 3*/ /* Print Last HowMany Characters in FileName */ /* 4*/ void /* 5*/ LastChars( const char *FileName, unsigned int HowMany ) /* 6*/ { /* 7*/ FILE *Fp; /* 8*/ char *Buffer; /* 9*/ int CharsRead; /*10*/ int FileSize; /*11*/ if( ( Buffer = malloc( HowMany ) ) == NULL ) /*12*/ { /*13*/ fprintf( stderr, "Out of space!!\n" ); /*14*/ return; /*15*/ } /*16*/ if( ( Fp = fopen( FileName, "rb" ) ) == NULL ) /*17*/ fprintf( stderr, "Can not open %s\n", FileName ); /*18*/ else /*19*/ { /*20*/ /* Get The Size Of The File */ /*21*/ fseek( Fp, 0, SEEK_END ); /*22*/ FileSize = ftell( Fp ); /*23*/ if( FileSize < HowMany ) /*24*/ HowMany = FileSize; /*25*/ /* Copy Its End */ /*26*/ fseek( Fp, - HowMany, SEEK_END ); /*27*/ CharsRead = fread( Buffer, 1, HowMany, Fp ); /*28*/ fwrite( Buffer, 1, CharsRead, stdout ); /*29*/ fclose( Fp ); /*30*/ } /*31*/ free( Buffer ); /*32*/ } /* ECP: FILEname=fig12_17.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ static const char *Wtmp = "/var/adm/wtmp"; /* 5*/ static const UtmpSize = sizeof( struct utmp ); /* 6*/ #define NameLen 8 /* 7*/ #define LineLen 8 /* 8*/ int /* 9*/ Logins( const char *SearchName ) /*10*/ { /*11*/ int HowMany = 0; /*12*/ struct utmp UtEntry; /*13*/ FILE *Ufp; /*14*/ if( ( Ufp = fopen( Wtmp, "rb" ) ) == NULL ) /*15*/ { /*16*/ fprintf( stderr, "Can not open %s\n", Wtmp ); /*17*/ return -1; /*18*/ } /*19*/ fseek( Ufp, -UtmpSize, SEEK_END ); /*20*/ while( fread( &UtEntry, UtmpSize, 1, Ufp ) == 1 ) /*21*/ { /*22*/ char Name[ NameLen + 1 ] = "", Line[ LineLen + 1 ] = ""; /*23*/ if( !strncmp( UtEntry.ut_name, SearchName, NameLen ) ) /*24*/ { /*25*/ strncpy( Name, UtEntry.ut_name, NameLen ); /*26*/ strncpy( Line, UtEntry.ut_line, LineLen ); /*27*/ printf( "%-*s %-*s %26s", NameLen, Name, LineLen, /*28*/ Line, ctime( &UtEntry.ut_time ) ); /*29*/ HowMany++; /*30*/ } /*31*/ /* Back Up Past Current Structure */ /*32*/ if( fseek( Ufp, -UtmpSize * 2, SEEK_CUR ) == -1 ) /*33*/ break; /*34*/ } /*35*/ fclose( Ufp ); /*36*/ return HowMany; /*37*/ } /* ECP: FILEname=fig12_18.c */ /* 1*/ #include /* 2*/ #include /* 3*/ int Cflag = 1; /* Print out Character Counts */ /* 4*/ int Lflag = 1; /* Print out Line Counts */ /* 5*/ int Wflag = 1; /* Print out Word Counts */ /* 6*/ main( int argc, char *argv[ ] ) /* 7*/ { /* 8*/ argv++; argc--; /* Skip Command Name */ /* 9*/ if( argc > 0 && **argv == '-' ) /*10*/ { /*11*/ SetOptions( *argv ); /*12*/ argv++; argc--; /*13*/ } /*14*/ /* If No Files, Use Standard Input */ /*15*/ if( argc == 0 ) /*16*/ Wc( stdin ); /*17*/ else /*18*/ do /*19*/ { /*20*/ FILE *Ifp = fopen( *argv, "r" ); /*21*/ if( Ifp == NULL ) /*22*/ fprintf( stderr, "Can not open %s\n", *argv ); /*23*/ else /*24*/ { /*25*/ Wc( Ifp ); /*26*/ fclose( Ifp ); /*27*/ printf( " %s", *argv ); /*28*/ } /*29*/ printf( "\n" ); /*30*/ argv++; /*31*/ } while( --argc > 0 ); /*32*/ return 0; /*33*/ } /* ECP: FILEname=fig12_19.c */ /* 1*/ void /* 2*/ SetOptions( const char *Option ) /* 3*/ { /* 4*/ Lflag = Wflag = Cflag = 0; /* 5*/ while( *++Option ) /* 6*/ switch( *Option ) /* 7*/ { /* 8*/ case 'l': /* 9*/ Lflag++; break; /*10*/ case 'w': /*11*/ Wflag++; break; /*12*/ case 'c': /*13*/ Cflag++; break; /*14*/ default: /*15*/ fprintf( stderr, "Illegal option %c\n", *Option ); /*16*/ } /*17*/ } /* ECP: FILEname=fig12_20.c */ /* 1*/ void /* 2*/ Wc( FILE *Ifp ) /* 3*/ { /* 4*/ int Ch, InWord = 0, Words = 0, Lines = 0, Chars = 0; /* 5*/ while( ( Ch = getc( Ifp ) ) != EOF ) /* 6*/ { /* 7*/ Chars++; /* 8*/ if( Ch == '\n' ) /* 9*/ Lines++; /*10*/ if( isspace( Ch ) ) /*11*/ InWord = 0; /*12*/ else if( !InWord ) /*13*/ { /*14*/ /* New Word Seen */ /*15*/ InWord = 1; /*16*/ Words++; /*17*/ } /*18*/ } /*19*/ if( Lflag ) printf( "%8d", Lines ); /*20*/ if( Wflag ) printf( "%8d", Words ); /*21*/ if( Cflag ) printf( "%8d", Chars ); /*22*/ } /* ECP: FILEname=fig12_21.c */ /* 1*/ #include /* 2*/ #include /* 3*/ main( int argc, char *argv[ ], char *envp[ ] ) /* 4*/ { /* 5*/ int i; /* 6*/ for( i = 0; envp[ i ] != NULL; i++ ) /* 7*/ printf( "%s\n", envp[ i ] ); /* 8*/ printf( "TERMINAL TYPE IS: %s\n", getenv( "TERM" ) ); /* 9*/ return 0; /*10*/ } /* ECP: FILEname=fig13_2.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ #include /* 5*/ #include /* 6*/ #include /* 7*/ /* Return Number Of Seconds Terminal Has Been Idle */ /* 8*/ /* -1 Is Returned On Error */ /* 9*/ #define MaxLen 32 /*10*/ #define DevLen 6 /* strlen( "/dev/" ) + 1 */ /*11*/ int /*12*/ Idle( const char *Terminal ) /*13*/ { /*14*/ struct stat StatBuf; /*15*/ char TerminalName[ MaxLen ] = "/dev/"; /*16*/ time_t Now; /*17*/ strncat( TerminalName, Terminal, MaxLen - DevLen ); /*18*/ if( lstat( TerminalName, &StatBuf ) < 0 ) /*19*/ perror( TerminalName ); /*20*/ else /*21*/ if( !S_ISCHR( StatBuf.st_mode ) ) /*22*/ fprintf( stderr, "%s: Not a terminal\n", TerminalName ); /*23*/ else /*24*/ { /*25*/ time( &Now ); /*26*/ return ( int ) difftime( StatBuf.st_atime, Now ); /*27*/ } /*28*/ return -1; /* Error Indicator */ /*29*/ } /* ECP: FILEname=fig13_6.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ #include /* For MAXPATHLEN */ /* 5*/ #include /* 6*/ #include /* 7*/ struct stat Slash; /* Stores Info For "/" */ /* 1*/ int /* 2*/ main( void ) /* 3*/ { /* 4*/ if( lstat( "/", &Slash ) < 0 ) /* 5*/ perror( "/" ); /* 6*/ else /* 7*/ Pwd( "." ); /* 8*/ return 0; /* 9*/ } /* 1*/ int /* 2*/ IsMatch( const struct stat *F1, const struct stat *F2 ) /* 3*/ { /* 4*/ return F1->st_ino == F2->st_ino && F1->st_dev == F2->st_dev; /* 5*/ } /* 1*/ void /* 2*/ Pwd( const char *DirName ) /* 3*/ { /* 4*/ struct stat Dot; /* 5*/ if( lstat( DirName, &Dot ) < 0 ) /* 6*/ perror( DirName ); /* 7*/ else /* 8*/ if( IsMatch( &Dot, &Slash ) ) /* 9*/ printf( "/" ); /*10*/ else /*11*/ Pwd1( ".", &Dot ); /*12*/ printf( "\n" ); /*13*/ } /* ECP: FILEname=fig13_7.c */ /* 1*/ void /* 2*/ Pwd1( const char *DirName, const struct stat *Dot ) /* 3*/ { /* 4*/ struct stat DotDot, Buf; /* 5*/ char FileName[ MAXPATHLEN ], Parent[ MAXPATHLEN ]; /* 6*/ DIR *ParentDir; /* 7*/ struct dirent *Slot; /* 8*/ if( IsMatch( Dot, &Slash ) ) /* Base Case */ /* 9*/ return; /* We Are At Slash */ /*10*/ /* First, Recursively Print Up To The Parent */ /*11*/ sprintf( Parent, "%s/..", DirName ); /*12*/ if( lstat( Parent, &DotDot ) < 0 ) /*13*/ { /*14*/ perror( Parent ); /*15*/ return; /*16*/ } /*17*/ Pwd1( Parent, &DotDot ); /*18*/ /* Now, Print Last Component Of The Pathname */ /*19*/ if( ( ParentDir = opendir( Parent ) ) == NULL ) /*20*/ { /*21*/ perror( Parent ); /*22*/ return; /*23*/ } /*24*/ while( ( Slot = readdir( ParentDir ) ) != NULL ) /*25*/ { /*26*/ sprintf( FileName, "%s/%s", Parent, Slot->d_name ); /*27*/ if( !lstat( FileName, &Buf ) && IsMatch( &Buf, Dot ) ) /*28*/ { /*29*/ printf( "/%s", Slot->d_name ); /*30*/ closedir( ParentDir ); /*31*/ return; /*32*/ } /*33*/ } /*34*/ printf( "/???" ); /* This Should Never Occur */ /*35*/ } /* ECP: FILEname=fig13_8.c */ /* 1*/ /* Simple du Program. List Disk Usage. Double */ /* 2*/ /* Counts Hard Links Or It Would Be The Same As du */ /* 3*/ #include /* 4*/ #include /* 5*/ #include /* 6*/ #include /* 7*/ #include /* 8*/ #include /* 9*/ #include /*10*/ int aflag = 0; /*11*/ long int du( const char *Dir ); /*12*/ int /*13*/ main( int argc, char **argv ) /*14*/ { /*15*/ if( argc > 1 ) /*16*/ { /*17*/ if( strcmp( argv[ 1 ], "-a" ) == 0 ) /*18*/ { /*19*/ argv++; argc--; aflag = 1; /*20*/ } /*21*/ } /*22*/ if( argc == 1 ) /*23*/ du( "." ); /*24*/ else /*25*/ while( --argc ) /*26*/ du( *++argv ); /*27*/ return 0; /*28*/ } /* ECP: FILEname=fig13_9.c */ /* 1*/ long /* 2*/ du( const char *DirName ) /* 3*/ { /* 4*/ DIR *DirPtr; /* Pointer To Directory Stream */ /* 5*/ struct dirent *Slot; /* Slot in Directory */ /* 6*/ struct stat StatBuf; /* 7*/ long Blocks = 0L; /* 8*/ char FileName[ MAXPATHLEN ]; /* 9*/ if( ( DirPtr = opendir( DirName ) ) == NULL ) /*10*/ { /*11*/ perror( DirName ); /*12*/ return 0L; /*13*/ } /*14*/ while( ( Slot = readdir( DirPtr ) ) != NULL ) /*15*/ { /*16*/ if( strcmp( Slot->d_name, ".." ) == 0 ) /*17*/ continue; /* Skip Parent */ /*18*/ sprintf( FileName, "%s/%s", DirName, Slot->d_name ); /*19*/ if( lstat( FileName, &StatBuf ) != 0 ) /*20*/ { /*21*/ perror( FileName ); /*22*/ continue; /*23*/ } /*24*/ if ( S_ISDIR( StatBuf.st_mode ) ) /* Directories */ /*25*/ { /*26*/ if( strcmp( Slot->d_name, "." ) == 0 ) /*27*/ Blocks += StatBuf.st_blocks; /*28*/ else /*29*/ Blocks += du( FileName ); /*30*/ continue; /*31*/ } /*32*/ /* Print The Answer in 1k Blocks, Not 512 Byte Blocks */ /*33*/ if( aflag ) /*34*/ printf( "%-8ld%s\n", StatBuf.st_blocks/2, FileName ); /*35*/ Blocks += StatBuf.st_blocks; /*36*/ } /*37*/ if( Blocks ) /*38*/ printf( "%-8ld%s\n", Blocks/2, DirName ); /*39*/ closedir( DirPtr ); /*40*/ return Blocks; /*41*/ } /* ECP: FILEname=fig13_11.c */ /* 1*/ /* Copy From SrcFile To DestFile */ /* 2*/ /* Return Number Of Characters Copied, -1 For Errors */ /* 3*/ #include /* 4*/ #include /* 5*/ #include /* 6*/ #include /* 7*/ #include /* 8*/ #include /* 9*/ #define BufSize 8192 /*10*/ long int /*11*/ Copy( const char *DestFile, const char *SrcFile ) /*12*/ { /*13*/ long int CharsRead, CharsCounted = 0; /*14*/ int SrcDesc, DestDesc; /*15*/ char Buffer[ BufSize ]; /*16*/ const CreateFlag = O_WRONLY | O_CREAT | O_TRUNC; /*17*/ const Mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; /*18*/ if( strcmp( SrcFile, DestFile ) == 0 ) /*19*/ { /*20*/ fprintf( stderr, "Can not copy to self\n" ); /*21*/ return -1L; /*22*/ } /*23*/ if( ( SrcDesc = open( SrcFile, O_RDONLY ) ) < 0 ) /*24*/ { /*25*/ perror( SrcFile ); /*26*/ return -1L; /*27*/ } /*28*/ if( ( DestDesc = open( DestFile, CreateFlag, Mode ) ) < 0 ) /*29*/ { /*30*/ perror( DestFile ); /*31*/ return -1L; /*32*/ } /*33*/ while( ( CharsRead = read( SrcDesc, Buffer, BufSize ) ) > 0 ) /*34*/ if( write( DestDesc, Buffer, CharsRead ) < CharsRead ) /*35*/ { /*36*/ perror( DestFile ); /*37*/ break; /*38*/ } /*39*/ else /*40*/ CharsCounted += CharsRead; /*41*/ close( SrcDesc ); close( DestDesc ); /*42*/ return CharsCounted; /*43*/ } /* ECP: FILEname=fig13_14.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ main( void ) /* 5*/ { /* 6*/ pid_t Pid; /* 7*/ long int i; /* 8*/ if( ( Pid = fork( ) ) == -1 ) /* 9*/ { /*10*/ perror( "" ); /*11*/ exit( -1 ); /*12*/ } /*13*/ if( Pid == 0 ) /*14*/ printf( "I am the child; my parent is %d.", getppid( ) ); /*15*/ else /*16*/ printf( "I am the parent; my child is %d.", Pid ); /*17*/ /* Both Processes Execute Their Own Copies Of this */ /*18*/ printf( " My process id is %d.\n", getpid( ) ); /*19*/ fflush( stdout ); /*20*/ for( i = 0; i < 3000000; i++ ) /*21*/ if( i % 1000000 == 0 ) /*22*/ { /*23*/ printf( "%s\n", Pid ? "Parent" : "Child" ); /*24*/ fflush( stdout ); /*25*/ } /*26*/ return 0; /*27*/ } /* ECP: FILEname=fig13_15.c */ /* 1*/ #include /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ printf( "No flush because no newline" ); /* 6*/ fork( ); /* No Error Checks */ /* 7*/ return 0; /* Call To exit( ) Is Implicit */ /* 8*/ } /* ECP: FILEname=fig13_16.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ #include /* 5*/ #include /* 6*/ int /* 7*/ SimpleSystem( const char *Command ) /* 8*/ { /* 9*/ pid_t Pid; /*10*/ int Status; /*11*/ if( Command == NULL ) /*12*/ return 1; /*13*/ Pid = fork( ); /*14*/ if( Pid < 0 ) /* Error */ /*15*/ return -1; /*16*/ if( Pid == 0 ) /* Child */ /*17*/ { /*18*/ execl( "/bin/sh", "sh", "-c", Command, NULL ); /*19*/ _exit( 127 ); /* execl Failed; Give Up On Child */ /*20*/ } /*21*/ /* else Parent */ /*22*/ waitpid( Pid, &Status, 0 ); /*23*/ return Status; /*24*/ } /* ECP: FILEname=fig13_18.c */ /* 1*/ #include /* Other Includes Omitted For Brevity */ /* 2*/ int /* 3*/ WrongSystem( const char *Command ) /* 4*/ { /* 5*/ pid_t Pid; /* 6*/ int Status; /* 7*/ void ( *SaveIntr )( ), ( *SaveQuit )( ); /* 8*/ if( Command == NULL ) /* 9*/ return 1; /*10*/ Pid = fork( ); /*11*/ if( Pid < 0 ) /* Error */ /*12*/ return -1; /*13*/ if( Pid == 0 ) /* Child */ /*14*/ { /*15*/ execl( "/bin/sh", "sh", "-c", Command, NULL ); /*16*/ _exit( 127 ); /* execl Failed; Give Up On Child */ /*17*/ } /*18*/ /* Parent */ /*19*/ SaveIntr = signal( SIGINT, SIG_IGN ); /* Ignore */ /*20*/ SaveQuit = signal( SIGQUIT, SIG_IGN ); /* Signals */ /*21*/ waitpid( Pid, &Status, 0 ); /*22*/ signal( SIGINT, SaveIntr ); /* Restore */ /*23*/ signal( SIGQUIT, SaveQuit ); /* Signals */ /*24*/ return Status; /*25*/ } /* ECP: FILEname=fig13_19.c */ /* 1*/ #include /* Other Includes Omitted For Brevity */ /* 2*/ int /* 3*/ RealSystem( const char *Command ) /* 4*/ { /* 5*/ pid_t Pid; /* 6*/ int Status; /* 7*/ void ( *SaveIntr )( ), ( *SaveQuit )( ); /* 8*/ if( Command == NULL ) /* 9*/ return 1; /*10*/ SaveIntr = signal( SIGINT, SIG_IGN ); /* Ignore */ /*11*/ SaveQuit = signal( SIGQUIT, SIG_IGN ); /* Signals */ /*12*/ Pid = fork( ); /*13*/ if( Pid < 0 ) /* Error */ /*14*/ return -1; /*15*/ if( Pid == 0 ) /* Child */ /*16*/ { /*17*/ signal( SIGINT, SaveIntr ); /* Restore */ /*18*/ signal( SIGQUIT, SaveQuit ); /* Signals */ /*19*/ execl( "/bin/sh", "sh", "-c", Command, NULL ); /*20*/ _exit( 127 ); /* execl Failed; Give Up On Child */ /*21*/ } /*22*/ /* Parent */ /*23*/ waitpid( Pid, &Status, 0 ); /*24*/ signal( SIGINT, SaveIntr ); /* Restore */ /*25*/ signal( SIGQUIT, SaveQuit ); /* Signals */ /*26*/ return Status; /*27*/ } /* ECP: FILEname=fig13_20.c */ /* 1*/ /* Simple Demonstration Of Signal Handling */ /* 2*/ /* Buffers Are Flushed On Interrupt */ /* 3*/ #include /* 4*/ #include /* 5*/ #include /* 6*/ #include /* 7*/ void /* 8*/ Doexit( void ) /* 9*/ { /*10*/ exit( SIGINT ); /* Flush Buffers */ /*11*/ } /*12*/ main( void ) /*13*/ { /*14*/ signal( SIGINT, Doexit ); /*15*/ for( ; ; ) /*16*/ { /*17*/ sleep( 1 ); /*18*/ printf( "junk" ); /*19*/ } /*20*/ return 0; /*21*/ } /* ECP: FILEname=fig13_21.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ #include /* 5*/ static jmp_buf RestartLoop; /* 6*/ static void /* 7*/ IntrHandler( int SigNum ) /* 8*/ { /* 9*/ static int NumCalls = 0; /*10*/ if( ++NumCalls == 3 ) /* Allow Three Per Program */ /*11*/ { /*12*/ fprintf( stderr, "Quitting...\n" ); /*13*/ exit( 0 ); /*14*/ } /*15*/ fprintf( stderr, "Caught an interrupt: resetting\n" ); /*16*/ longjmp( RestartLoop, NumCalls ); /*17*/ } /*18*/ main( void ) /*19*/ { /*20*/ setjmp( RestartLoop ); /*21*/ signal( SIGINT, IntrHandler ); /*22*/ for( ; ; ) /*23*/ DoCommands( ); /*24*/ return 0; /*25*/ } /* ECP: FILEname=fig13_22.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ #include /* 5*/ static sigjmp_buf RestartLoop; /* 6*/ static void /* 7*/ IntrHandler( int SigNum ) /* 8*/ { /* 9*/ static int NumCalls = 0; /*10*/ if( ++NumCalls == 3 ) /* Allow Three Per Program */ /*11*/ { /*12*/ fprintf( stderr, "Quitting...\n" ); /*13*/ exit( 0 ); /*14*/ } /*15*/ fprintf( stderr, "Caught an interrupt: resetting\n" ); /*16*/ siglongjmp( RestartLoop, NumCalls ); /*17*/ } /*18*/ main( void ) /*19*/ { /*20*/ sigsetjmp( RestartLoop, 1 ); /*21*/ signal( SIGINT, IntrHandler ); /*22*/ for( ; ; ) /*23*/ DoCommands( ); /*24*/ return 0; /*25*/ } /* ECP: FILEname=fig13_24.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ #include /* 5*/ #include /* 6*/ #include /* 7*/ #include /* 8*/ #include /* 9*/ #include /*10*/ /* Simple Shell */ /*11*/ /* A Simple Command Is An Array Of Up To MaxArgc+1 Strings */ /*12*/ /* The Last String Is NULL */ /*13*/ /* This Can Be Used Directly For execvp */ /*14*/ /* Very Limited Error Checking To Keep Code Short */ /*15*/ #define MaxArgc 10 /*16*/ #define MaxPipes 10 /*17*/ #define FileNameLen MaxLineLen /*18*/ #define MaxLineLen 256 /*19*/ typedef char *SimpleCommand[ MaxArgc + 1 ]; /*20*/ typedef struct /*21*/ { /*22*/ char InFile[ FileNameLen ]; /*23*/ char OutFile[ FileNameLen ]; /*24*/ int NumPipes; /*25*/ SimpleCommand Commands[ MaxPipes ]; /*26*/ int Background; /*27*/ } FullCommand; /*28*/ enum { Eoln, Error, From, To, Pipe, Word, Amper }; /*29*/ /* Read A Line, return NULL On EOF */ /*30*/ #define GetLine( S ) ( fgets( S, MaxLineLen, stdin ) ) /*31*/ /* Return Pointer Indicating Where To Begin Next Search */ /*32*/ /* Str Will Be Filled if *Token Is Word, From, Or To */ /*33*/ char *GetToken( char *TheLine, char *Str, int *Token ); /* ECP: FILEname=fig13_25.c */ /* 1*/ /* Fill The Structure Referenced By Buf */ /* 2*/ int /* 3*/ Parse( char *TheLine, FullCommand *Buf ) /* 4*/ { /* 5*/ int CommandNum = 0, Token; /* 6*/ char Str[ MaxLineLen ]; /* 7*/ int NumStr = 0; /* # Of Strings In Current Command */ /* 8*/ Buf->NumPipes = Buf->Background = 0; /* 9*/ strcpy( Buf->InFile, "" ); /*10*/ strcpy( Buf->OutFile, "" ); /*11*/ for( ; TheLine = GetToken( TheLine, Str, &Token ); ) /*12*/ switch( Token ) /*13*/ { /*14*/ default: /*15*/ case Error: /*16*/ printf( "Syntax error\n" ); /*17*/ return -1; /*18*/ case From: /*19*/ strcpy( Buf->InFile, Str ); /*20*/ break; /*21*/ case To: /*22*/ strcpy( Buf->OutFile, Str ); /*23*/ break; /*24*/ case Amper: /*25*/ Buf->Background++; /*26*/ break; /*27*/ case Pipe: /*28*/ Buf->NumPipes++; /*29*/ case Eoln: /*30*/ Buf->Commands[ CommandNum++ ][ NumStr ] = NULL; /*31*/ NumStr = 0; /*32*/ break; /*33*/ case Word: /*34*/ Buf->Commands[ CommandNum ][ NumStr++ ] = /*35*/ Strdup( Str ); /* Note: This Is A Memory Leak */ /*36*/ break; /*37*/ } /*38*/ return 0; /*39*/ } /* ECP: FILEname=fig13_26.c */ /* 1*/ /* Print A Prompt */ /* 2*/ void /* 3*/ Prompt( int Num ) /* 4*/ { /* 5*/ printf( "[%d] ", Num ); /* 6*/ fflush( stdout ); /* 7*/ } /* 8*/ /* Simple main */ /* 9*/ main( void ) /*10*/ { /*11*/ FullCommand OneComm; /*12*/ char OneLine[ MaxLineLen ]; /*13*/ int RetCode; /*14*/ int CommandNum = 1; /*15*/ /*16*/ signal( SIGINT, SIG_IGN ); /* Ignore Signals */ /*17*/ signal( SIGQUIT, SIG_IGN ); /*18*/ for( Prompt( CommandNum ); GetLine( OneLine ) != NULL; ) /*19*/ { /*20*/ if( OneLine[ 0 ] != '\n' ) /*21*/ { /*22*/ CommandNum++; /*23*/ Parse( OneLine, &OneComm ); /*24*/ RunCommand( &OneComm ); /*25*/ } /*26*/ Prompt( CommandNum ); /*27*/ } /*28*/ return 0; /*29*/ } /* ECP: FILEname=fig13_27.c */ /* 1*/ void /* 2*/ SetFiles( FullCommand *Buf ) /* 3*/ { /* 4*/ if( Buf->InFile[ 0 ] ) /* 5*/ if( freopen( Buf->InFile, "r", stdin ) == NULL ) /* 6*/ { /* 7*/ perror( Buf->InFile ); /* 8*/ _exit( 127 ); /* 9*/ } /*10*/ if( Buf->OutFile[ 0 ] ) /*11*/ if( freopen( Buf->OutFile, "w", stdout ) == NULL ) /*12*/ { /*13*/ perror( Buf->OutFile ); /*14*/ _exit( 127 ); /*15*/ } /*16*/ } /* 1*/ void /* 2*/ UsePipe( int Fd[ 2 ], int WhichEnd ) /* 3*/ { /* 4*/ dup2( Fd[ WhichEnd ], WhichEnd ); /* 5*/ close( Fd[ 0 ] ); /* 6*/ close( Fd[ 1 ] ); /* 7*/ } /* ECP: FILEname=fig13_28.c */ /* 1*/ int /* 2*/ RunCommand( FullCommand *Buf ) /* 3*/ { /* 4*/ pid_t Pid; /* 5*/ int Fd[ 2 ]; /* 6*/ int i; /* 7*/ if( ( Pid = fork( ) ) < 0 ) /* Error */ /* 8*/ return -1; /* 9*/ if( Pid == 0 ) /* Child */ /*10*/ { /*11*/ SetFiles( Buf ); /*12*/ if( !Buf->Background ) /*13*/ { /*14*/ signal( SIGINT, SIG_DFL ); /* Restore Signals */ /*15*/ signal( SIGQUIT, SIG_DFL ); /* Before Exec */ /*16*/ } /*17*/ /* For Each pipe, We Need An Additional Process */ /*18*/ for( i = Buf->NumPipes; i > 0 ; i-- ) /*19*/ { /*20*/ if( pipe( Fd ) < 0 ) /*21*/ { /*22*/ perror( Buf->Commands[ 0 ][ 0 ] ); /*23*/ _exit( 127 ); /*24*/ } /*25*/ if( ( Pid = fork( ) ) < 0 ) /*26*/ return -1; /*27*/ UsePipe( Fd, Pid ? STDIN_FILENO : STDOUT_FILENO ); /*28*/ if( Pid != 0 ) /* Parent */ /*29*/ break; /*30*/ } /*31*/ execvp( Buf->Commands[ i ][ 0 ], Buf->Commands[ i ] ); /*32*/ perror( Buf->Commands[ i ][ 0 ] ); /*33*/ _exit( 127 ); /* execl Failed; Give Up On Child */ /*34*/ } /*35*/ /* Shell Process: Note Pid Is Last Command In Pipeline */ /*36*/ if( !Buf->Background ) /*37*/ waitpid( Pid, NULL, 0 ); /*38*/ return 0; /*39*/ } /* ECP: FILEname=fig13_33.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #define Milli( X ) ( ( X.tv_sec * 1000 + X.tv_usec / 1000 ) ) /* 4*/ long int /* 5*/ MilliElapsed( void ) /* 6*/ { /* 7*/ struct Rusage Buf; /* 8*/ static struct Timeval LastUtime; /* 9*/ long int ElapsedTime; /*10*/ /*11*/ getrusage( RUSAGE_SELF, &Buf ); /*12*/ ElapsedTime = Milli( Buf.ru_utime ) - Milli( LastUtime ); /*13*/ LastUtime = Buf.ru_utime; /*14*/ return ElapsedTime; /*15*/ } /* ECP: FILEname=fig13_34.make */ # Makefile for following situation: # tester.c and sub.c both include tester.h # The source files may also use stuff from # our library tester: tester.o sub.o gcc -o tester tester.o sub.o $(HOME)/lib/my_lib.a tester.o: tester.c tester.h gcc -O -I$(HOME)/include -c tester.c sub.o: sub.c tester.h gcc -O -I$(HOME)/include -c sub.c /* ECP: FILEname=fig13_35.make */ # Makefile for following situation: # tester.c and sub.c both include tester.h # The source files may also use stuff from # our library CC = gcc CFLAGS = -O INCLS = -I$(HOME)/include LIBS = $(HOME)/lib/my_lib.a OBJS = tester.o sub.o EFILE = tester $(EFILE): $(OBJS) $(CC) $(CFLAGS) -o $(EFILE) $(OBJS) $(LIBS) $(OBJS): tester.h $(CC) $(CFLAGS) $(INCLS) -c $*.c /* ECP: FILEname=fig13_36.c */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ pid_t Pid; /* 5*/ void /* 6*/ Handler1( void ) /* 7*/ { /* 8*/ printf( "Entering Handler1\n" ); /* 9*/ kill( Pid, SIGUSR2 ); /*10*/ printf( "Leaving Handler1\n" ); /*11*/ } /*12*/ void /*13*/ Handler2( void ) /*14*/ { /*15*/ printf( "Entering Handler2\n" ); /*16*/ kill( Pid, SIGUSR1 ); /*17*/ printf( "Leaving Handler2\n" ); /*18*/ } /*19*/ main( void ) /*20*/ { /*21*/ Pid = getpid( ); /*22*/ signal( SIGUSR1, Handler1 ); /*23*/ signal( SIGUSR2, Handler2 ); /*24*/ kill( Pid, SIGUSR1 ); /*25*/ return 0; /*26*/ } /* ECP: FILEname=fig14_1.cpp */ /* 1*/ #include /* 2*/ // First C++ Program. /* 3*/ main( void ) /* 4*/ { /* 5*/ cout << "This is C++" << endl; /* 6*/ return 0; /* 7*/ } /* ECP: FILEname=fig14_2.cpp */ /* 1*/ // Program to double space input. /* 2*/ #include /* 3*/ main( void ) /* 4*/ { /* 5*/ char Ch; /* 6*/ while( cin.get( Ch ) ) /* 7*/ { /* 8*/ cout.put( Ch ); /* 9*/ if( Ch == '\n' ) /*10*/ cout.put( '\n' ); /*11*/ } /*12*/ return 0; /*13*/ } /* ECP: FILEname=fig14_3.cpp */ /* 1*/ #include /* 2*/ #include /* 3*/ #include /* 4*/ // Copy from sourcefile to destfile. Return number of /* 5*/ // Characters copied; -1 for errors. /* 6*/ int /* 7*/ Copy( const char *DestFile, const char *SourceFile ) /* 8*/ { /* 9*/ int CharsCounted = 0; /*10*/ char Ch; /*11*/ if( strcmp( SourceFile, DestFile ) == 0 ) /*12*/ { /*13*/ cerr << "Can not copy to self" << endl; /*14*/ return -1; /*15*/ } /*16*/ ifstream Sfp( SourceFile, ios::in ); /*17*/ if( !Sfp ) /*18*/ { /*19*/ cerr << "Can not open input file " << SourceFile << endl; /*20*/ return -1; /*21*/ } /*22*/ ofstream Dfp( DestFile, ios::out ); /*23*/ if( !Dfp ) /*24*/ { /*25*/ cerr << "Can not open output file " << DestFile << endl; /*26*/ return -1; /*27*/ } /*28*/ while( Sfp.get( Ch ) ) /*29*/ if( !Dfp.put( Ch ) ) /*30*/ { /*31*/ cerr << "Unexpected error during write." << endl; /*32*/ break; /*33*/ } /*34*/ else /*35*/ CharsCounted++; /*36*/ return CharsCounted; /*37*/ } /* ECP: FILEname=fig14_5.cpp */ /* 1*/ #include /* 1*/ void /* 2*/ Swap( int & A, int & B ) /* 3*/ { /* 4*/ int Tmp = A; /* 5*/ A = B; /* 6*/ B = Tmp; /* 7*/ } /* 1*/ main( void ) /* 2*/ { /* 3*/ int X = 5, Y = 7; /* 4*/ Swap( X, Y ); /* 5*/ cout << X << ' ' << Y << endl; // Prints 7 5. /* 6*/ return 0; /* 7*/ } /* ECP: FILEname=fig14_6.cpp */ /* 1*/ template /* 2*/ void /* 3*/ Shellsort( Etype A[ ], const unsigned int N ) /* 4*/ { /* 5*/ unsigned int Gap; /* 6*/ Etype Tmp; /* 7*/ unsigned int i, j; // Loop counters. /* 8*/ for( Gap = N/2; Gap > 0; /* 9*/ Gap = Gap == 2 ? 1 : ( unsigned int ) ( Gap / 2.2 ) ) /*10*/ for( i = Gap; i < N; i++ ) /*11*/ { /*12*/ Tmp = A[ i ]; /*13*/ for( j = i; j >= Gap && Tmp < A[ j - Gap ]; j -= Gap ) /*14*/ A[ j ] = A[ j - Gap ]; /*15*/ A[ j ] = Tmp; /*16*/ } /*17*/ } /* ECP: FILEname=fig14_7.cpp */ /* 1*/ #include /* 2*/ // Read an arbitrary number of doubles, sort and print them. /* 3*/ main( void ) /* 4*/ { /* 5*/ double *Array = NULL, X; /* 6*/ unsigned int ItemsRead = 0, MaxSize = 0; /* 7*/ cout << "Enter items to sort:" << endl; /* 8*/ while( cin >> X ) /* 9*/ { /*10*/ if( ItemsRead >= MaxSize ) /*11*/ DoubleArray( Array, MaxSize ); /*12*/ Array[ ItemsRead++ ] = X; /*13*/ } /*14*/ Shellsort( Array, ItemsRead ); /*15*/ cout << "Sorted items are: " << "\n"; /*16*/ for( int i = 0; i < ItemsRead; i++ ) /*17*/ cout << Array[ i ] << "\n"; /*18*/ return 0; /*19*/ } /* ECP: FILEname=fig14_8.cpp */ /* 1*/ template /* 2*/ void /* 3*/ DoubleArray( Etype * & Array, unsigned int & CurrentSize ) /* 4*/ { /* 5*/ Etype * OldArray = Array; /* 6*/ const MinSize = 5; /* 7*/ unsigned int NewSize = Array ? 2 * CurrentSize : MinSize; /* 8*/ Array = new Etype [ NewSize ]; /* 9*/ if( Array == NULL ) /*10*/ { /*11*/ cerr << "Error doubling array!" << endl; /*12*/ CurrentSize = 0; /*13*/ } /*14*/ else /*15*/ { /*16*/ for( unsigned int i = 0; i < CurrentSize; i++ ) /*17*/ Array[ i ] = OldArray[ i ]; /*18*/ CurrentSize = NewSize; /*19*/ } /*20*/ delete [ ] OldArray; // Safe even if OldArray is NULL. /*21*/ } /* ECP: FILEname=fig14_9.cpp */ /* 1*/ #include /* 2*/ main( void ) /* 3*/ { /* 4*/ const Date D( 1995, Jun, 30 ); // End of fiscal year. /* 5*/ Date i; /* 6*/ /* 7*/ for( i = Date( 1995, May ); i < D; i++ ) /* 8*/ cout << i << ": " << D - i << /* 9*/ " days till fiscal year ends" << endl; /*10*/ return 0; /*11*/ } /* ECP: FILEname=fig14_10.cpp */ /* 1*/ // Simple Date class. This is the interface. /* 2*/ #include /* 3*/ enum Month { Jan, Feb, Mar, Apr, May, Jun, /* 4*/ Jul, Aug, Sep, Oct, Nov, Dec }; /* 5*/ class Date /* 6*/ { /* 7*/ public: /* 8*/ enum { FirstYear = 1800 }; /* 9*/ enum { MaxYear = 2100 }; /*10*/ private: /*11*/ long int TotalDays; // Since day zero. /*12*/ static int DaysTillFirstOfMonth[ ]; /*13*/ static long int *DaysTillJan1; /*14*/ void SetJan1Array( void ); /*15*/ public: /*16*/ // Constructor. /*17*/ Date( int Y = FirstYear, int M = 0, int D = 1 ); /*18*/ // Assignment Operator. /*19*/ const Date & operator += ( long int Days ); /*20*/ // Unary Operators. /*21*/ Date operator ++ ( ); // Prefix. /*22*/ Date operator ++ ( int ); // Postfix. /*23*/ // Binary Operators . /*24*/ long int operator - ( const Date & Right ) const; /*25*/ int operator < ( const Date & Right ) const; /*26*/ // Friends for I/O. /*27*/ friend ostream & operator << /*28*/ ( ostream & Output, const Date & TheDate ); /*29*/ friend istream & operator >> /*30*/ ( istream & Input, Date & TheDate ); /*31*/ }; /* ECP: FILEname=fig14_11.cpp */ /* 1*/ int Date::DaysTillFirstOfMonth[ ] = /* 2*/ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /* 3*/ long int *Date::DaysTillJan1 = NULL; /* 1*/ // Create DaysTillJan1 array for first Date object. /* 2*/ void /* 3*/ Date::SetJan1Array( void ) /* 4*/ { /* 5*/ if( DaysTillJan1 != NULL ) /* 6*/ return; /* 7*/ DaysTillJan1 = new long int [ MaxYear - FirstYear + 1 ]; /* 8*/ int DaysSinceStart = 0; /* 9*/ for( int i = FirstYear; i <= MaxYear; i++ ) /*10*/ { /*11*/ DaysTillJan1[ i - FirstYear ] = DaysSinceStart; /*12*/ DaysSinceStart += 365 + IsLeap( i ); /*13*/ } /*14*/ } /* ECP: FILEname=fig14_12.cpp */ /* 1*/ Date::Date( int Y, int M, int D ) /* 2*/ { /* 3*/ SetJan1Array( ); /* 4*/ // Simplistic algorithm; no error checks. /* 5*/ TotalDays = DaysTillJan1[ Y - FirstYear ]; /* 6*/ TotalDays += DaysTillFirstOfMonth[ M ]; /* 7*/ TotalDays += D; /* 8*/ TotalDays += IsLeap( Y ); /* 9*/ } /* ECP: FILEname=fig14_13.cpp */ /* 1*/ const Date & /* 2*/ Date::operator += ( long int Days ) /* 3*/ { /* 4*/ TotalDays += Days; /* 5*/ return *this; /* 6*/ } /* ECP: FILEname=fig14_14.cpp */ /* 1*/ Date /* 2*/ Date::operator ++ ( ) /* 3*/ { /* 4*/ TotalDays++; /* 5*/ return *this; /* 6*/ } /* 1*/ Date /* 2*/ Date::operator ++ ( int ) /* 3*/ { /* 4*/ Date Tmp = *this; /* 5*/ TotalDays++; /* 6*/ return Tmp; /* 7*/ } /* ECP: FILEname=fig14_15.cpp */ /* 1*/ long int /* 2*/ Date::operator - ( const Date & Right ) const /* 3*/ { /* 4*/ return TotalDays - Right.TotalDays; /* 5*/ } /* 1*/ int /* 2*/ Date::operator < ( const Date & Right ) const /* 3*/ { /* 4*/ return TotalDays < Right.TotalDays; /* 5*/ } /* ECP: FILEname=fig14_16.cpp */ /* 1*/ ostream & /* 2*/ operator << ( ostream & Output, const Date & TheDate ) /* 3*/ { /* 4*/ long int TotalDays = TheDate.TotalDays; /* 5*/ int Month = -1, Year = -1; /* 6*/ // Find the year. /* 7*/ while( Date::DaysTillJan1[ ++Year ] < TotalDays ) /* 8*/ ; /* 9*/ Year--; /*10*/ TotalDays -= Date::DaysTillJan1[ Year ]; /*11*/ Year += Date::FirstYear; /*12*/ // Compute the month. /*13*/ if( IsLeap( Year ) ) /*14*/ Date::DaysTillFirstOfMonth[ Mar ] = 60; /*15*/ while( Date::DaysTillFirstOfMonth[ ++Month ] < TotalDays ) /*16*/ ; /*17*/ Month--; /*18*/ // The rest gives the day of the month. /*19*/ TotalDays -= Date::DaysTillFirstOfMonth[ Month ]; /*20*/ // Restore to non-leap year default. /*21*/ Date::DaysTillFirstOfMonth[ Mar ] = 59; /*22*/ // Now output the date. /*23*/ static char *MonthName[ ] = /*24*/ { "Jan", "Feb", "Mar", "Apr", "May", "Jun", /*25*/ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /*26*/ Output << MonthName[ Month ] << ' ' << TotalDays /*27*/ << ", " << Year; /*28*/ return Output; /*29*/ } /* ECP: FILEname=fig14_17.cpp */ /* 1*/ // Simple >>, just to allow compilation. /* 2*/ istream & /* 3*/ operator >> ( istream & Input, Date & TheDate ) /* 4*/ { /* 5*/ int M, D, Y; /* 6*/ Input >> M >> D >> Y; /* 7*/ TheDate = Date( Y, M, D ); /* 8*/ return Input; /* 9*/ } /* ECP: FILEname=fig14_18.cpp */ /* 1*/ #include /* 2*/ #include /* 3*/ class String /* 4*/ { /* 5*/ char *Storage; // Storage for the string. /* 6*/ unsigned int StorageLen; // Amount of allocated memory. /* 7*/ inline void GetStorage( const unsigned int MaxLength ); /* 8*/ public: /* 9*/ // Constructors. /*10*/ String ( const char * Value = NULL ); /*11*/ String ( const String & Value ); /*12*/ // Destructor. /*13*/ ~String ( ) { delete [ ] Storage; } /*14*/ // Assignment operator. /*15*/ const String & operator = ( const String & Value ); /*16*/ /*17*/ // Get a single character. /*18*/ char & operator [ ] ( unsigned int Index ) const; /*19*/ // Get the length. /*20*/ unsigned int Length ( ) const { return strlen( Storage ); } /*21*/ // Friends. /*22*/ friend int operator == /*23*/ ( const String & Lhs, const String & Rhs ); /*24*/ friend int operator != /*25*/ ( const String & Lhs, const String & Rhs ); /*26*/ friend int operator < /*27*/ ( const String & Lhs, const String & Rhs ); /*28*/ friend int operator > /*29*/ ( const String & Lhs, const String & Rhs ); /*30*/ friend ostream & operator << /*31*/ ( ostream & Output, const String & Str ); /*32*/ friend istream & operator >> /*33*/ ( istream & Input, String & Str ); /*34*/ }; /* ECP: FILEname=fig14_19.cpp */ /* 1*/ inline void /* 2*/ String::GetStorage( const unsigned int MaxLength ) /* 3*/ { /* 4*/ StorageLen = MaxLength + 1; /* 5*/ Storage = new char [ StorageLen ]; /* 6*/ if( Storage == NULL ) /* 7*/ Error( "Out of space" ); /* 8*/ } /* 1*/ String::String( const char * Value ) /* 2*/ { /* 3*/ const char * TheValue = Value ? Value : ""; /* 4*/ GetStorage( strlen( TheValue ) ); /* 5*/ strcpy( Storage, TheValue ); /* 6*/ } /* 1*/ String::String( const String & Value ) /* 2*/ { /* 3*/ GetStorage( strlen( Value.Storage ) ); /* 4*/ strcpy( Storage, Value.Storage ); /* 5*/ } /* ECP: FILEname=fig14_20.cpp */ /* 1*/ const String & /* 2*/ String::operator = ( const String & Value ) /* 3*/ { /* 4*/ const int Len = strlen( Value.Storage ); /* 5*/ if( this != &Value ) // Do not copy to yourself. /* 6*/ { /* 7*/ if( Len >= StorageLen ) /* 8*/ { /* 9*/ delete [ ] Storage; /*10*/ GetStorage( Len ); /*11*/ } /*12*/ /*13*/ strcpy( Storage, Value.Storage ); /*14*/ } /*15*/ return *this; /*16*/ } /* ECP: FILEname=fig14_21.cpp */ /* 1*/ char & /* 2*/ String::operator [ ] ( unsigned int Index ) const /* 3*/ { /* 4*/ if( Index > strlen( Storage ) ) /* 5*/ cerr << "Warning: out of bounds string access" << endl; /* 6*/ return Storage[ Index ]; /* 7*/ } /* ECP: FILEname=fig14_22.cpp */ /* 1*/ inline int /* 2*/ operator == ( const String & Lhs, const String & Rhs ) /* 3*/ { /* 4*/ return strcmp( Lhs.Storage, Rhs.Storage ) == 0; /* 5*/ } /* 1*/ inline int /* 2*/ operator != ( const String & Lhs, const String & Rhs ) /* 3*/ { /* 4*/ return strcmp( Lhs.Storage, Rhs.Storage ) != 0; /* 5*/ } /* 1*/ inline int /* 2*/ operator < ( const String & Lhs, const String & Rhs ) /* 3*/ { /* 4*/ return strcmp( Lhs.Storage, Rhs.Storage ) < 0; /* 5*/ } /* 1*/ inline int /* 2*/ operator > ( const String & Lhs, const String & Rhs ) /* 3*/ { /* 4*/ return strcmp( Lhs.Storage, Rhs.Storage ) > 0; /* 5*/ } /* ECP: FILEname=fig14_23.cpp */ /* 1*/ ostream & /* 2*/ operator << ( ostream & Output, const String & Str ) /* 3*/ { /* 4*/ Output << Str.Storage; /* 5*/ return Output; /* 6*/ } /* 1*/ istream & /* 2*/ operator >> ( istream & Input, String & Str ) /* 3*/ { /* 4*/ static char Tmp[ 512 ]; // Should be enough for most cases. /* 5*/ Input >> Tmp; /* 6*/ Str = Tmp; /* 7*/ return Input; /* 8*/ } /* ECP: FILEname=fig14_24.cpp */ /* 1*/ template /* 2*/ class Stack /* 3*/ { /* 4*/ Stack( const Stack & ); // Disable copy constructor. /* 5*/ Stack & operator=( const Stack & ); // Disable operator=. /* 6*/ Etype *Array; // The array of elements. /* 7*/ int TopOfStack; // Index of top element. /* 8*/ unsigned int MaxSize; // Maximum stack size; /* 9*/ public: /*10*/ enum { DefaultInitSize = 5 }; /*11*/ // Constructor. /*12*/ Stack( unsigned int InitSize = DefaultInitSize ); /*13*/ // Destructor. /*14*/ ~Stack( ) { delete [ ] Array; } /*15*/ // Member functions. /*16*/ int IsEmpty( ) const; // True if empty. /*17*/ void Push( const Etype & X ); // Push. /*18*/ const Etype & Pop( ); // Combine pop and top. /*19*/ void ClearStack( ); // Make it empty. /*20*/ }; /* 1*/ template /* 2*/ Stack::Stack( unsigned int InitSize ) /* 3*/ { /* 4*/ Array = new Etype [ MaxSize = InitSize ]; /* 5*/ if( Array == NULL ) /* 6*/ Error( "Out of memory" ); /* 7*/ ClearStack( ); /* 8*/ } /* ECP: FILEname=fig14_25.cpp */ /* 1*/ template /* 2*/ inline int /* 3*/ Stack::IsEmpty( ) const /* 4*/ { /* 5*/ return TopOfStack == -1; /* 6*/ } /* 1*/ template /* 2*/ void /* 3*/ Stack::Push( const Etype & X ) /* 4*/ { /* 5*/ if( ++TopOfStack == MaxSize ) /* 6*/ DoubleArray( Array, MaxSize ); /* 7*/ Array[ TopOfStack ] = X; /* 8*/ } /* 1*/ template /* 2*/ const Etype & /* 3*/ Stack::Pop( ) /* 4*/ { /* 5*/ if( IsEmpty( ) ) /* 6*/ { /* 7*/ cerr << "Pop on empty stack" << endl; /* 8*/ return Array[ 0 ]; /* 9*/ } /*10*/ else /*11*/ return Array[ TopOfStack-- ]; /*12*/ } /* 1*/ template /* 2*/ inline void /* 3*/ Stack::ClearStack( ) /* 4*/ { /* 5*/ TopOfStack = -1; /* 6*/ } /* ECP: FILEname=fig14_26.cpp */ /* 1*/ int /* 2*/ CheckBalance( const String & FileName ) /* 3*/ { /* 4*/ Stack S; /* 5*/ Symbol Last = { 0, 1 }, Match; /* 6*/ int Errors = 0; /* 7*/ ifstream Ifp( FileName, ios::in ); /* 8*/ while( Ifp.get( Last.Sym ) ) /* 9*/ switch( Last.Sym ) /*10*/ { /*11*/ case '\n': /*12*/ Last.Line++; /*13*/ break; /*14*/ case '(': case '[': case '{': /*15*/ S.Push( Last ); /*16*/ break; /*17*/ case ')': case ']': case '}': /*18*/ if( S.IsEmpty( ) ) /*19*/ { /*20*/ Errors++; /*21*/ cout << "Extraneous " << Last.Sym << /*22*/ " at line " << Last.Line << endl; /*23*/ } /*24*/ else /*25*/ { /*26*/ Match = S.Pop( ); /*27*/ if( CheckMatch( Match, Last ) ) /*28*/ Errors++; /*29*/ } /*30*/ break; /*31*/ default: /*32*/ break; /*33*/ } /*34*/ while( !S.IsEmpty( ) ) // Unmatched symbols. /*35*/ { /*36*/ Errors++; /*37*/ Match = S.Pop( ); /*38*/ cout << "Unmatched " << Match.Sym << " at line " /*39*/ << Match.Line << endl; /*40*/ } /*41*/ return Errors; /*42*/ } /* ECP: FILEname=fig14_27.cpp */ /* 1*/ #include /* 2*/ #include /* 3*/ #include "string.h" /* 4*/ struct Symbol /* 5*/ { /* 6*/ char Sym; /* 7*/ int Line; /* 8*/ }; /* 1*/ int /* 2*/ CheckMatch( const Symbol & OpSym, const Symbol & ClSym ) /* 3*/ { /* 4*/ if( OpSym.Sym == '(' && ClSym.Sym == ')' || /* 5*/ OpSym.Sym == '[' && ClSym.Sym == ']' || /* 6*/ OpSym.Sym == '{' && ClSym.Sym == '}' ) /* 7*/ return 0; /* 8*/ cout << "Found " << ClSym.Sym << " on line " << /* 9*/ ClSym.Line << "; does not match " << OpSym.Sym << /*10*/ " at line " <> File; /* 6*/ return CheckBalance( File ); /* 7*/ } /* ECP: FILEname=fig14_28.cpp */ /* 1*/ // Base class shape. /* 2*/ class Shape /* 3*/ { /* 4*/ protected: /* 5*/ const char *Name; // Shape identifier. /* 6*/ public: /* 7*/ Shape( ) { } // Constructor. /* 8*/ virtual double Area( ) const = 0; // Area function. /* 9*/ int operator < ( const Shape & Rhs ) const // < /*10*/ { return Area( ) < Rhs.Area( ); } /*11*/ friend ostream & operator << // Output. /*12*/ ( ostream & Output, const Shape & S ); /*13*/ }; /* 1*/ ostream & operator << ( ostream & Output, const Shape & S ) /* 2*/ { /* 3*/ Output << S.Name << " of area " << S.Area( ) << "\n"; /* 4*/ return Output; /* 5*/ } /* ECP: FILEname=fig14_29.cpp */ /* 1*/ const double Pi = 3.1416; /* 2*/ class Circle : public Shape /* 3*/ { /* 4*/ private: /* 5*/ double Radius; /* 6*/ public: /* 7*/ Circle( double R = 0.0 ) : Radius( R ) /* 8*/ { Name = "circle"; } /* 9*/ double Area( ) const /*10*/ { return Pi * Radius * Radius; } /*11*/ }; /* 1*/ class Rectangle : public Shape /* 2*/ { /* 3*/ private: /* 4*/ double Length; /* 5*/ double Width; /* 6*/ public: /* 7*/ Rectangle( double L = 0.0, double W = 0.0 ) : /* 8*/ Length( L ), Width( W ) /* 9*/ { Name = "rectangle"; } /*10*/ double Area( ) const /*11*/ { return Length * Width; } /*12*/ }; /* 1*/ class Square : public Rectangle /* 2*/ { /* 3*/ public: /* 4*/ Square( double S = 0.0 ) : Rectangle( S, S ) /* 5*/ { Name = "square"; } /* 6*/ }; /* ECP: FILEname=fig14_30.cpp */ /* 1*/ main( void ) /* 2*/ { /* 3*/ const NumShapes = 5; /* 4*/ Shape *Array[ NumShapes ]; // 5 pointers to shapes. /* 5*/ // Read the shapes. /* 6*/ for( int i = 0; i < NumShapes; i++ ) /* 7*/ { /* 8*/ cout << "Enter a shape: "; /* 9*/ cin >> Array[ i ]; /*10*/ } /*11*/ Shellsort( Array, ( unsigned int ) NumShapes ); /*12*/ cout << "Sorted by increasing size:" << endl; /*13*/ for( i = 0; i < NumShapes; i++ ) /*14*/ cout << *Array[ i ]; /*15*/ return 0; /*16*/ } /* ECP: FILEname=fig14_31.cpp */ /* 1*/ // Read a pointer to a shape. /* 2*/ // Bare bones, with no error checking. /* 3*/ istream & operator >> ( istream & Input, Shape * & S ) /* 4*/ { /* 5*/ char Ch; /* 6*/ double D1, D2; /* 7*/ Input >> Ch; // First character represents shape. /* 8*/ switch( Ch ) /* 9*/ { /*10*/ case 'c': /*11*/ Input >> D1; /*12*/ S = new Circle( D1 ); /*13*/ break; /*14*/ case 'r': /*15*/ Input >> D1 >> D2; /*16*/ S = new Rectangle( D1, D2 ); /*17*/ break; /*18*/ case 's': /*19*/ Input >> D1; /*20*/ S = new Square( D1 ); /*21*/ break; /*22*/ default: /*23*/ cerr << "Needed one of c, r, or s" << endl; /*24*/ S = new Circle; // Radius is 0. /*25*/ break; /*26*/ } /*27*/ return Input; /*28*/ } /* ECP: FILEname=fig14_32.cpp */ /* 1*/ // Shellsort an array of arbitrary pointers. /* 2*/ template /* 3*/ void /* 4*/ Shellsort( Etype *A[ ], const unsigned int N ) /* 5*/ { /* 6*/ unsigned int Gap; /* 7*/ Etype *Tmp; /* 8*/ unsigned int i, j; // Loop counters. /* 9*/ for( Gap = N/2; Gap > 0; /*10*/ Gap = Gap == 2 ? 1 : ( unsigned int ) ( Gap / 2.2 ) ) /*11*/ for( i = Gap; i < N; i++ ) /*12*/ { /*13*/ Tmp = A[ i ]; /*14*/ for( j = i; j >= Gap && *Tmp < *A[ j - Gap ]; j -= Gap ) /*15*/ A[ j ] = A[ j - Gap ]; /*16*/ A[ j ] = Tmp; /*17*/ } /*18*/ } /* ECP: FILEname=figD_1.c */ /* 1*/ #include /* 2*/ #include /* 3*/ void /* 4*/ PrintStrings( const char *Str1, ... ) /* 5*/ { /* 6*/ char *NextStr; /* 7*/ va_list Argp; /* 8*/ /* 9*/ puts( Str1 ); /*10*/ va_start( Argp, Str1 ); /*11*/ while( NextStr = va_arg( Argp, char * ) ) /*12*/ puts( NextStr ); /*13*/ va_end( Argp ); /*14*/ } /*15*/ main( void ) /*16*/ { /*17*/ PrintStrings( "This", "is", "a", "test", 0 ); /*18*/ return 0; /*19*/ }