, PA A[0], *(PA+1) A[1], PA+I - A[I], *(PA+I) - A[I]. A. " 1 ", , - , , , . , I PA+I , PA. - . - . - . . - , PA=&A[0] PA = A , - , , A[I] *(A+I). A[I] "C" *(A+I); . & , , &A[I] A+I : A+I - I- A. , PA , : PA[I] - *(PA+I). , , , , . , . - , PA=A PA++ . - , : A=PA A++, P=&A . , . - , , , .. - , . - STRLEN, - . STRLEN(S) /* RETURN LENGTH OF STRING S */ CHAR *S; { INT N; FOR (N = 0; *S != '\0'; S++) N++; RETURN(N); } S , ; S++ - STRLEN , STRLEN . - CHAR S[]; CHAR *S; ; - , , - . , , - , , , , - . , - . , - . , A - , F(&A[2]) F(A+2) F A[2], &A[2], A+2 , A. F : F(ARR) INT ARR[]; { ... } F(ARR) INT *ARR; { ... } F, , - , . 5.4.  P , , , P++ P , , P +=I P , - , I - . . "C" ; , . ( , ) - . : ALLOC(N) - P, - N , - ALLOC - ; FREE(P) , . "", FREE , , ALLOC. , ALLOC FREE - , - . "C" , , , , 8 . , , - ALLOC - . , - , ALLOCBUF. ALLOC FREE. , , . , .. - , ALLOC FREE, - . ; - . , ALLOCBUF . , ALLOCP. - ALLOC N , - , ALLOCBUF. - , ALLOC ALLOCP (.. ), N, . - FREE(P) ALLOCP P , P ALLOCBUF. DEFINE NULL 0 /* POINTER VALUE FOR ERROR REPORT */ DEFINE ALLOCSIZE 1000 /* SIZE OF AVAILABLE SPACE */ TATIC CHAR ALLOCBUF[ALLOCSIZE];/* STORAGE FOR ALLOC */ TATIC CHAR *ALLOCP = ALLOCBUF; /* NEXT FREE POSITION */ HAR *ALLOC(N) /* RETURN POINTER TO N CHARACTERS */ INT N; ( IF (ALLOCP + N <= ALLOCBUF + ALLOCSIZE) { ALLOCP += N; RETURN(ALLOCP - N); /* OLD P */ } ELSE /* NOT ENOUGH ROOM */ RETURN(NULL); ) REE(P) /* FREE STORAGE POINTED BY P */ HAR *P; ( IF (P >= ALLOCBUF && P < ALLOCBUF + ALLOCSIZE) ALLOCP = P; ) . , - , , - NULL ( ) , - - . STATIC CHAR *ALLOCP = ALLOCBUF; ALLOCP , ALLOCBUF, .. - . - , STATIC CHAR *ALLOCP = &ALLOCBUF[0]; , - . IF (ALLOCP + N <= ALLOCBUF + ALLOCSIZE) , , - N . , - ALLOCP , - ALLOCBUF. , ALLOC ( ). , ALLOC - , , . "C" , , - , . , , NULL, , - . , - , - - . IF (ALLOCP + N <= ALLOCBUF + ALOOCSIZE) IF (P >= ALLOCBUF && P < ALLOCBUF + ALLOCSIZE) - . - , . P Q , , <, >= .., . , P < Q , P , Q. == != . - NULL. , , . , . , - . -, , . P + N N- , P . , - P ; - N P - , P. , PDP-11 1 CHAR, 2 INT SHORT, 4 LONG FLOAT 8 DOUBLE. : P Q , P-Q - P Q. - STRLEN: STRLEN(S) /* RETURN LENGTH OF STRING S */ CHAR *S; { CHAR *P = S; WHILE (*P != '\0') P++; RETURN(P-S); } P S, - . WHILE - , \0. \0 , WHILE , 0, - . WHILE (*P) P++; P , P++ - P , - . P-S , .. . : FLOAT, - , CHAR, P FLOAT, P++ P FLOAT. , ALLOC, FLOAT, CHAR, ALLOC FREE CHAR FLOAT. - , , . ( - , - ), - . , , - , , FLOAT DOUBLE. 5.5.  , , , "I AM A STRING" . \0, . , - . - , , , PRINTF ("HELLO, WORLD\N"); , , - , ; PRINTF - . , - . MESSAGE CHAR *MESSAGE; MESSAGE = "NOW IS THE TIME"; MESSAGE . ; . "C" - . , - -, 7. - STRCPY(S,T), - S. , , T S S = T : STRCPY(S, T) /* COPY T TO S */ CHAR S[], T[]; { INT I; I = 0; WHILE ((S[I] = T[I]) != '\0') I++; } STRCPY - . STRCPY(S, T) /* COPY T TO S; POINTER VERSION 1 */ CHAR *S, *T; { WHILE ((*S = *T) != '\0') { S++; T++; } } , STRCPY S T , . , , , - S T \0. STRCPY , . : STRCPY(S, T) /* COPY T TO S; POINTER VERSION 2 */ CHAR *S, *T; { WHILE ((*S++ = *T++) != '\0') ; } S T . - *T++ , T - ; ++ T, - . S, S . , , - \0, T S. , - \0 , STRCPY(S, T) /* COPY T TO S; POINTER VERSION 3 */ CHAR *S, *T; { WHILE (*S++ = *T++) ; } - , . , - "C"-. - STRCMP(S, T), - S , , , , S, T. - , S T . STRCMP(S, T) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */ CHAR S[], T[]; { INT I; I = 0; WHILE (S[I] == T[I]) IF (S[I++] == '\0') RETURN(0); RETURN(S[I]-T[I]); } STRCMP : STRCMP(S, T) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */ CHAR *S, *T; { FOR ( ; *S == *T; S++, T++) IF (*S == '\0') RETURN(0); RETURN(*S-*T); } ++ -- , , * ++ --, . *++P P , P, *--P P.  5-2 --------------- STRCAT 2: STRCAT(S, T) T S.  5-3 --------------- STRCPY.  5-4 -------------- - , . GETLINE / 1 4/, ATOI, ITOA / 2, 3 4/, REVERSE / 3/, INDEX GETOP / 4/. 5.6. -  , , ""-- . , - , - ; . , , , , - . - , , STRSAVE(S), S , - ALLOC, . : CHAR *STRSAVE(S) /* SAVE STRING S SOMEWHERE */ CHAR *S; { CHAR *P, *ALLOC(); IF ((P = ALLOC(STRLEN(S)+1)) != NULL) STRCPY(P, S); RETURN(P); } : *STRSAVE(S) /* SAVE STRING S SOMEWHERE */ { CHAR *P; IF ((P = ALLOC(STRLEN(S)+1)) != NULL) STRCPY(P, S); RETURN(P); } - , INT, . , - - . . (- LINT , ). 5.7.  "C" - , - . . . , 1- 60- - 61- . : DAY_OF_YEAR , MONTH_DAY - . , : MONTH_DAY(1977, 60, &M, &D) M 3 D 1 (1- ). - , . - , , , . : STATIC INT DAY_TAB[2][13] = { (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) }; DAY_OF_YEAR(YEAR, MONTH, DAY) /* SET DAY OF YEAR */ INT YEAR, MONTH, DAY; /* FROM MONTH & DAY */ { INT I, LEAP; LEAP = YEAR%4 == 0 && YEAR%100 != 0 \!\! YEAR%400 == 0; FOR (I = 1; I < MONTH; I++) DAY += DAY_TAB[LEAP][I]; RETURN(DAY); { MONTH_DAY(YEAR, YEARDAY, PMONTH, PDAY) /*SET MONTH,DAY */ INT YEAR, YEARDAY, *PMONTH, *PDAY; /* FROM DAY OF YEAR */ { LEAP = YEAR%4 == 0 && YEAR%100 != 0 \!\! YEAR%400 == 0; FOR (I = 1; YEARDAY > DAY_TAB[LEAP][I]; I++) YEARDAY -= DAY_TAB[LEAP][I]; *PMONTH = I; *PDAY = YEARDAY; } DAY_TAB DAY_OF_YEAR, MONTH_DAY, - . DAY_TAB , - . "C" , - . DAY_TAB[I][J] DAY_TAB [I, J] . , . , .. - . - , ; - . DAY_TAB - , 1 12, 0 11. , , - . , - ; , , , . - , 13 INT. , - DAY_TAB F, F : F(DAY_TAB) INT DAY_TAB[2][13]; { ... } , - F : INT DAY_TAB[][13]; INT (*DAY_TAB)[13]; , 13 . , [] - , *; , INT *DAY_TAB[13]; 13 . 5.8. ;  , - . . - , SORT - UNIX. 3 , - . - , , , , . - , . . - (, , ALLOC), . . , STRCMP. , , . : . : , - , . - -. , , , . , . - , , , -1. , - , . #DEFINE NULL 0 #DEFINE LINES 100 /* MAX LINES TO BE SORTED */ MAIN() /* SORT INPUT LINES */ \( CHAR *LINEPTR[LINES]; /*POINTERS TO TEXT LINES */ INT NLINES; /* NUMBER OF INPUT LINES READ */ IF ((NLINES = READLINES(LINEPTR, LINES)) >= 0) \( SORT(LINEPTR, NLINES); WRITELINES(LINEPTR, NLINES); \) ELSE PRINTF("INPUT TOO BIG TO SORT\N"); \) #DEFINE MAXLEN 1000 READLINES(LINEPTR, MAXLINES) /* READ INPUT LINES */ CHAR *LINEPTR[]; /* FOR SORTING */ INT MAXLINES; \( INT LEN, NLINES; CHAR *P, *ALLOC(), LINE[MAXLEN]; NLINES = 0; WHILE ((LEN = GETLINE(LINE, MAXLEN)) > 0) IF (NLINES >= MAXLINES) RETURN(-1); ELSE IF ((P = ALLOC(LEN)) == NULL) RETURN (-1); ELSE \( LINE[LEN-1] = '\0'; /* ZAP NEWLINE */ STRCPY(P,LINE); LINEPTR[NLINES++] = P; \) RETURN(NLINES); \) , , . WRITELINES(LINEPTR, NLINES) /* WRITE OUTPUT LINES */ CHAR *LINEPTR[]; INT NLINES; \( INT I; FOR (I = 0; I < NLINES; I++) PRINTF("%S\N", LINEPTR[I]); \) CHAR *LINEPTR[LINES]; , LINEPTR LINES , - CHAR. , LINEPTR[I] - , *LINEPTR[I] . LINEPTR , - WRITELINES, - , - . : WRITELINES(LINEPTR, NLINES) /* WRITE OUTPUT LINES */ CHAR *LINEPTR[]; INT NLINES; \( INT I; WHILE (--NLINES >= 0) PRINTF("%S\N", *LINEPTR++); \) *LINEPTR ; , NLINES . , - . 3 : - , . - , - , - . SORT(V, N) /* SORT STRINGS V[0] ... V[N-1] */ CHAR *V[]; /* INTO INCREASING ORDER */ INT N; \( INT GAP, I, J; CHAR *TEMP; FOR (GAP = N/2; GAP > 0; GAP /= 2) FOR (I = GAP; I < N; I++) FOR (J = I - GAP; J >= 0; J -= GAP) \( IF (STRCMP(V[J], V[J+GAP]) <= 0) BREAK; TEMP = V[J]; V[J] = V[J+GAP]; V[J+GAP] = TEMP; \) \) V ( , LINEPTR) , TEMP , . , . - , , , - , READLINES, LINE, - ALLOC. , , "- " . , -, , . , , , . 1 , WHILE FOR , - , - , , . , , , .  5-5 -------------- READLINES , , MAIN, , ALLOC. - ? 5.9.  MONTH_NAME(N), - , N- . - . MONTH_NAME - . - . CHAR *MONTH_NAME(N) /* RETURN NAME OF N-TH MONTH */ INT N; \( STATIC CHAR *NAME[] = \( "ILLEGAL MONTH", "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUN", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" \); RETURN ((N < 1 \!\! N > 12) ? NAME[0] : NAME[N]); \) NAME , LINEPTR . ; - . , I- - , NAME[I]. NAME , . 5.10.  "" - , NAME . INT A[10][10]; INT *B[10]; A B , A[5][5], B[5][5] INT. A - : 100 - - . B, , 10 ; , . , 10 , - 100 . , - . - : - , , - . , B 10 ; - , - , . , - , , MONTH_NAME, - .  5-6 -------------- DAY_OF_YEAR MONTH_DAY, . 5.11.  , - "", . MAIN , - . ( ARGC) , ; (ARGV) - , - , . - - . ECHO, - , . , ECHO HELLO, WORLD HELLO, WORLD ARGV[0] , - , ARGC 1. - ARGC 3, ARGV[0], ARGV[1] ARGV[2] "ECHO", "HELLO," "WORLD". ARGV[1], - ARGV[ARGC-1]. ARGC 1, . - ECHO: MAIN(ARGC, ARGV) /* ECHO ARGUMENTS; 1ST VERSION */ INT ARGC; CHAR *ARGV[]; \( INT I; FOR (I = 1; I < ARGC; I++) PRINTF("%S%C", ARGV[I], (I<ARGC-1) ? ' ' : '\N'); \) ARGV , , - , . . MAIN(ARGC, ARGV) /* ECHO ARGUMENTS; 2ND VERSION */ INT ARGC; CHAR *ARGV[]; \( WHILE (--ARGC > 0) PRINTF("%S%C",*++ARGV, (ARGC > 1) ? ' ' : '\N'); \) ARGV -- , , 1 (++ARGV), ARGV[1], ARGV[0]. ; *ARGV - . ARGC ; - , . : MAIN(ARGC, ARGV) /* ECHO ARGUMENTS; 3RD VERSION */ INT ARGC; CHAR *ARGV[]; \( WHILE (--ARGC > 0) PRINTF((ARGC > 1) ? "%S" : "%S\N", *++ARGV); \) , PRINTF , , . - , . , - 4. , , . GREP UNIX, - , - . #DEFINE MAXLINE 1000 MAIN(ARGC, ARGV) /* FIND PATTERN FROM FIRST ARGUMENT */ INT ARGC; CHAR *ARGV[]; \( CHAR LINE[MAXLINE]; IF (ARGC != 2) PRINTF ("USAGE: FIND PATTERN\N"); ELSE WHILE (GETLINE(LINE, MAXLINE) > 0) IF (INDEX(LINE, ARGV[1] >= 0) PRINTF("%S", LINE); \) , - . , . : " , - ", : " - ". ""- , , , - . , , - , -X, -N(""), FIND -X -N THE NOW IS THE TIME FOR ALL GOOD MEN TO COME TO THE AID OF THEIR PARTY. 2:FOR ALL GOOD MEN , - , - . , INDEX ARGV[2], , ARGV[1], . , - , : FIND -NX THE : #DEFINE MAXLINE 1000 MAIN(ARGC, ARGV) /* FIND PATTERN FROM FIRST ARGUMENT */ INT ARGC; CHAR *ARGV[]; \( CHAR LINE[MAXLINE], *S; LONG LINENO = 0; INT EXCEPT = 0, NUMBER = 0; WHILE (--ARGC > 0 && (*++ARGV)[0] == '-') FOR (S = ARGV[0]+1; *S != '\0'; S++) SWITCH (*S) \( CASE 'X': EXCEPT = 1; BREAK; CASE 'N': NUMBER = 1; BREAK; DEFAULT: PRINTF("FIND: ILLEGAL OPTION %C\N", *S); ARGC = 0; BREAK; \) IF (ARGC != 1) PRINTF("USAGE: FIND -X -N PATTERN\N"); ELSE WHILE (GETLIN(LINE, MAXLINE) > 0) \( LINENO++; IF ((INDEX(LINE, *ARGV) >= 0) != EXCEPT) \ IF (NUMBER) PRINTF("%LD: ", LINENO); PRINTF("%S", LINE); \) \) \) ARGV , ARGC . , ARGC 1, *ARGV . , *++ARGV ; (*++ARGV)[0] - . , ( ) *++(ARGV[0]). - **++ARGV.  5-7 -------------- ADD, . , ADD 2 3 4 + * 2*(3+4).  5-8 -------------- ENTAB DETAB ( - 1) , . - , .  5-9 -------------- ENTAB DETAB , - ENTAB M +N N , M. ( ) .  5-10 --------------- TAIL, - N . N - 10, - , TAIL -N N . - , - N. , - : , SORT, . 5.12.  "" , , , , .. , , -N , . - , - , - , , , - , . - , ,