printf( "%-15s %d\n", tbl->name, tbl->value ); } } int main(){ char buf[80]; struct elem *ptr; printtable(table); for(;;){ printf( "-> " ); if( gets( buf ) == NULL) break; /* EOF */ if( ! strcmp( buf, "q" )) exit(0); /* quit: */ ptr = find( buf, table, SIZE-1 ); if( ptr ) printf( "%d\n", ptr->value ); else { printf( "--- ---\n" ); printtable(table); } } return 0; } 7.26. , , , - . , , UNIX - : , less (more) . #define LEN 9 /* 256 */ char input[] = "(xxx+yyy)/123.75=?"; char output[LEN]; void main( void ){ int len=LEN, i; void bi_conv(); char c; bi_conv(input, output, &len); if(len > LEN){ printf(" LEN %d\n", len); len = LEN; /* */ } for(i=0; i < len && (c = output[i]); ++i) putchar(c); putchar('\n'); } /* , include- * ! */ #include <stdio.h> #include <ctype.h> #define PUT(c) { count++; \ if(put < *len){ *p++ = (c); ++put;}} #define GET() (*s ? *s++ : EOF) void bi_conv( . , 1992-95 - 290 - UNIX /*IN*/ char *s, /*OUT*/ char *p, /*INOUT*/ int *len ){ int count, put, c; for(count=put=0; (c=GET()) != EOF; ){ /* : C\bC */ /* : _\bC */ if(isalpha(c)){ PUT('_'); PUT('\b'); } else if(isdigit(c)){ PUT( c ); PUT('\b'); } PUT(c); } PUT('\0'); /* */ *len = count; #undef PUT #undef GET } . , input output ; , , #define PUT(c) if(c)putchar(c) #define GET() getchar() , . 7.27. , . - C\b #include <stdio.h> #define NOPUT (-1) /* ASCII */ /* - */ typedef enum { NORMAL=1, ITALICS, BOLD, RED=BOLD } font; int ontty; font textfont; /* */ #define setfont(f) textfont=(f) #define getfont() (textfont) #define SetTtyFont(f) if(ontty) tfont(f) /* */ void tfont(font f){ /* ANSI */ static font ttyfont = NORMAL; if(ttyfont == f) return; printf("\033[0m"); /* set NORMAL font */ switch(ttyfont = f){ case NORMAL: /* */ break; case BOLD: printf("\033[1m"); break; case ITALICS: /* use reverse video */ printf("\033[7m"); break; } } void put(int c){ /* */ if(c == NOPUT) return; /* '\b' */ SetTtyFont(getfont()); putchar(c); setfont(NORMAL); /* C\b - */ } void main(){ register int c, cprev = NOPUT; /* - ? */ ontty = isatty(fileno(stdout)); setfont(NORMAL); while((c = getchar()) != EOF){ . , 1992-95 - 291 - UNIX if(c == '\b'){ /* */ if((c = getchar()) == EOF) break; if(c == cprev) setfont(BOLD); else if(cprev == '_') setfont(ITALICS); else /* A\bB */ setfont(RED); } else put(cprev); cprev = c; } put(cprev); /* */ SetTtyFont(NORMAL); } 7.28. -. . , - ( - ). : - , . : '\r' - ; , , , ( , '\t'). 7.29. , - . - , "", 'c' - - . EPSON-FX ( EP-2424) (ESC '\033'): (bold) ESC G ESC H (emphasized) ESC E ESC F (italics) ESC 4 ESC 5 (underline) ESC - 1 ESC - 0 ESC x 1 ESC x 0 (near letter quality) nlq draft (superscript) ESC S 0 ESC T (subscript) ESC S 1 ESC T (17 /) '\017' '\022' (condensed) ESC W 1 ESC W 0 (expanded) ESC p 1 ESC p 0 (proportional spacing) . : pitch ( ) pica (10 /) ESC P elite (12 /) ESC M micron (15 /) ESC g font () (draft (Roman)) ESC k '\0' (text (Sans Serif)) ESC k '\1' (courier) ESC k '\2' 0 '0' '\0'; 1 '1' '\1'. : printf( "This is \033Gboldface\033H word\n"); . , 1992-95 - 292 - UNIX 7.30. , - . '\f' (form feed) . 7.31. . - : ( ), (), . - - , ( ) . : - main(), , . : , ( ). /* : pr.c */ #include <stdio.h> #include <string.h> #define YES 1 #define NO 0 #define FORMFEED '\f' #define LINEFEED '\n' extern char *malloc(unsigned); extern char *strchr(char *, char); void untab(register char *s); void resetsheet( void ); void addsheet( char *s, FILE *fpout ); void flushsheet( FILE *fpout ); void printline( int y, char *s, char *attr, FILE *fpout ); void doattr( register char *abuf, register char *vbuf ); void printcopy( FILE *fpin, FILE *fpout ); void main(void); char *strdup (const char *s){ char *p = malloc(strlen(s)+1); strcpy(p,s); return p; /* return strcpy((char *) malloc(strlen(s)+1), s); */ } /* ... untab() ... */ int Sline; /* */ int Shalf; /* */ int npage; /* */ int startpage = 1; /* 1 */ int fline; /* */ int topline = 0; /* */ int halfwidth; /* */ int twocolumns = YES; /* ? */ int lshift, rshift = 1; /* */ typedef unsigned short ushort; int COLS = 128; /* () */ int LINES = 66; /* () */ ushort *mem; /* */ #define AT(x,y) mem[ (x) + (y) * COLS ] /* */ void resetsheet ( void ){ register x; if( mem == NULL ){ /* */ . , 1992-95 - 293 - UNIX if ((mem = (ushort *) malloc (COLS * LINES * sizeof(ushort))) == NULL ){ fprintf(stderr, "Out of memory.\n"); exit(1); } } /* */ for( x= COLS * LINES - 1 ; x >= 0 ; x-- ) mem[x] = ' ' & 0xFF; halfwidth = (twocolumns ? COLS/2 : COLS ) - (lshift + rshift ); Sline = topline; Shalf = 0; } #define NEXT_HALF \ if( twocolumns == YES && Shalf == 0 ){ \ /* */ \ Shalf = 1; /* */ \ Sline = topline; \ } else \ flushsheet(fpout) /* */ /* */ void addsheet ( char *s, FILE *fpout ) { register x, y; register i; char *rest = NULL; int wrap = NO; /* YES */ /* ? */ x = (Shalf == 0 ? 0 : COLS/2) + lshift; y = Sline; i = 0; /* s */ while (*s) { if( *s == '\f' ){ /* form feed */ rest = strdup( s+1 ); /* */ NEXT_HALF; if( *rest ) addsheet(rest, fpout); free( rest ); return; } if( i >= halfwidth ){ /* */ wrap = YES; rest = strdup(s); break; } /* */ if( s[1] == '\b' ){ while( s[1] == '\b' ){ AT(x, y) = (s[0] << 8) | (s[2] & 0xFF); /* overstrike */ s += 2; } s++; x++; i++; } else { AT (x, y) = *s++ & 0xFF; . , 1992-95 - 294 - UNIX x++; i++; } } /* /_ */ Sline++; if (Sline == LINES) { /* */ NEXT_HALF; } if( wrap && rest ) { /* */ addsheet(rest, fpout); free(rest); } } int again; /* ? */ /* */ void flushsheet ( FILE *fpout ){ register x, y, xlast; char *s, *p; static char outbuf[BUFSIZ], attr[BUFSIZ]; /* attr - */ ushort c; if( npage >= startpage ) for (y = 0; y < LINES; y++) { /* */ for (xlast = (-1), x = COLS - 1; x >= 0; x--) if (AT (x, y) != ' ') { xlast = x; break; } again = NO; s = outbuf; p = attr; for (x = 0; x <= xlast; x++){ c = AT(x, y); *s++ = c & 0xFF; /* ? */ c >>= 8; c &= 0xFF; *p++ = c ? c : ' '; if( c ) again = YES; } *s = '\0'; *p = '\0'; printline(y, outbuf, attr, fpout); } npage++; /* next page */ resetsheet(); /* */ } /* */ void printline ( int y, char *s, char *attr, FILE *fpout ){ register x; if( again ){ doattr(attr, s); fprintf(fpout, "%s\r", attr ); } fprintf(fpout, "%s", s); /* */ fputc( y == LINES-1 ? FORMFEED : LINEFEED, fpout ); } /* - */ void doattr ( register char *abuf, register char *vbuf ){ for(; *abuf; abuf++, vbuf++ ) if( !strchr(" _-!|\177", *abuf)) *abuf = *vbuf; } . , 1992-95 - 295 - UNIX /* */ void printcopy ( FILE *fpin, FILE *fpout ) { char inbuf[BUFSIZ]; npage = 1; /* 1 */ fline = 0; /* - 0 */ resetsheet(); /* */ while( fgets(inbuf, sizeof inbuf - 1, fpin ) != NULL ){ register l = strlen( inbuf ); if( l && inbuf[l-1] == '\n' ) inbuf[--l] = '\0' ; fline++; untab ( inbuf ); addsheet( inbuf, fpout ); } if( !(Sline == topline && Shalf == 0)) /* ... */ flushsheet(fpout); fprintf(stderr, "%d , %d .\n", fline, npage-1); } /* : pr <  > /dev/lp */ void main (){ printcopy(stdin, stdout); } - UNIX /dev/lp , MS DOS - prn. 7.32. , . : - malloc() strcpy(). , . , 80 50. : char text[50][80]; 50*80 = 4000 . , 10 . 50 * (10 + 1) = 550 4000 - 50 * (10 + 1) = 3450 (+1 '\0' ). char *text[50]; int i=0; : char buffer[81], *malloc(), *gets(); while( gets(buffer) != NULL ){ text[i] = (char *) malloc(strlen(buffer)+1); /* +1 \0, strlen- */ strcpy(text[i++], buffer); } , . ( sizeof(char *)==4) . , 1992-95 - 296 - UNIX 50 * 4 + 50 * (10 + 1 + 4) = 950 + malloc (+4 - malloc), . , , malloc()- ( free()). malloc , NULL: if((text[i] = malloc(....)) == NULL) { fprintf(stderr, " \n"); break; } : for(--i; i >= 0; i-- ){ printf("%s\n", text[i]); free( text[i] ); } free(ptr) ""|- malloc() calloc() ptr , malloc() - . free(). ( ) , malloc()-!  , , , , , , .  , - . - . 7.33. , . ! " " " " , " ". ____________________ |- , , . malloc - - ? . . , 1992-95 - 297 - UNIX /* . * , - * , */ #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #define BUFS 4096 /* */ void main(int argc, char **argv ) { FILE *fp; struct stat st; long len; char buffer[ BUFS+1 ]; FILE *fpnew; /* */ int lgt; if( argc != 2 ){ printf("Error: must be filename\n"); exit(1); } if( (fp= fopen( argv[1], "r" )) == NULL ){ printf( "Can not open %s\n", argv[1] ); exit(2); } stat( argv[1], &st ); /* fstat(fileno(fp), &st); */ len = st.st_size; /* */ if( (fpnew = fopen( "inv.out", "w" ))== NULL ){ printf("Can not create file\n"); exit(3); } while( fgets( buffer, sizeof buffer, fp ) != NULL ){ lgt = strlen( buffer ); fseek(fpnew, len - lgt , 0); /* , lseek fseek - * long, int. * * lseek(fd, (long) off, whence); */ len -= lgt; fprintf( fpnew, "%s", buffer ); /* fputs(buffer, fpnew); */ } fclose( fp ); fclose( fpnew ); } 7.34. , , "" , - . "" . , : . , 1992-95 - 298 - UNIX ----------- ----------- |###### A | |###### A | 1 |#### A | |#### A | |##### A | |##### A | | | | | |###### B | | | ----------- ----------- |#### B | |###### B | 2 | | |#### B | ... | | , - . ( !). - . /* , * */ #include <stdio.h> #include <ctype.h> extern void *malloc(unsigned); extern int atoi(char *); FILE *fpin = stdin, *fpout = stdout; /* */ char *strdup (const char *s) { char *ptr = (char *) malloc (strlen (s) + 1); if( ptr ) strcpy (ptr, s); return ptr; } int page_length = 66; /* */ int current_line; /* ( ) */ int numbered = 0; /* ? */ #define MAXLINES 256 /* . */ int stored = 0; /* */ char *lines[MAXLINES]; /* */ /* */ void remember (char *s) { if (stored >= MAXLINES) { fprintf (stderr, " .\n"); return; } else if((lines[stored++] = strdup (s)) == NULL ){ fprintf (stderr, " (Out of memory).\n"); exit(13); } } /* */ void newpage () { current_line = 0; putc('\f', fpout); } . , 1992-95 - 299 - UNIX /* */ void newline (void) { if (current_line == page_length - 1) newpage (); /* */ else { current_line++; if( numbered ) fprintf(fpout, "%02d\n", current_line); else putc ('\n', fpout); } } /* */ void nextpage () { while (current_line != 0) newline (); } /* */ void throwout () { register i; for (i = 0; i < stored; i++) { if( numbered ) fprintf(fpout, "%02d %s", current_line, lines[i]); else fputs (lines[i], fpout); newline (); free (lines[i]); } stored = 0; } /* , */ void flush () { int rest_of_page = page_length - current_line; /* */ if ((stored > page_length && rest_of_page < page_length / 4) || rest_of_page < stored) nextpage (); throwout (); if (current_line) /* */ newline (); /* */ } /* */ void process () { char buffer[512]; int l; while (fgets (buffer, sizeof buffer, fpin) != NULL) { if ((l = strlen (buffer)) && buffer[l - 1] == '\n') buffer[ --l] = '\0'; if (l) remember (buffer); /* - */ else if (stored) flush (); } if (stored) flush (); nextpage(); } . , 1992-95 - 300 - UNIX void main (int argc, char *argv[]) { argc--; argv++; while (*argv) { if (**argv == '-') { char *key = *argv + 1, *arg; switch (*key) { case 'l': if (! key[1]) { if( argv[1] ){ arg = argv[1]; argv++; argc--; } else arg = ""; } else arg = key+1; if( isdigit(*arg) ){ page_length = atoi(arg); fprintf (stderr, " : %d \n", page_length); } else fprintf(stderr, "-l \n"); break; case 'n': numbered++; break; default: fprintf (stderr, " %s\n", key); break; } } argv++; argc--; } process (); exit(0); } 7.35. , . , abcdef ... oklmn 987654321 ..... ..... 123456789 nmlko ... fedcba : . : (). 7.36. , - . - . : - . . , 1992-95 - 301 - UNIX /* */ #include <stdio.h> char buf[240]; /* */ int lines; /* */ typedef struct node{ struct _data{ /* */ char *key; /* - */ int line; /* */ } data; /* */ struct node *l, /* */ *r; /* */ } Node; Node *root = NULL; /* ( ) */ /* */ Node *newNode(s) char *s; /* */ { Node *tmp; extern char *malloc(); /* */ tmp = (Node *) malloc(sizeof(Node)); if( tmp == NULL ){ fprintf( stderr, " .\n"); exit(1); } tmp -> l = tmp -> r = NULL; /* */ tmp -> data.line = lines; /* */ tmp -> data.key = malloc( strlen(s) + 1 ); /* +1 - '\0' */ strcpy(tmp -> data.key, s); /* */ return tmp; } int i; /* , * auto-, * */ . , 1992-95 - 302 - UNIX /* */ void printtree(root, tree, level, c) Node *root; /* */ Node *tree; /* */ int level; /* */ char c; /* */ { if( root == NULL ){ printf(" .\n"); return; } if( tree == NULL ) return; /* - */ printtree (root, tree -> l, level + 1, '/'); /* 'L' */ /* */ for( i=0; i < level; i++ ) printf(" "); printf("%c%3d--\"%s\"\n", c, tree-> data.line, tree -> data.key); /* - */ printtree(root, tree -> r, level + 1, '\\'); /* 'R' */ } void prTree(tree) Node *tree; { printtree(tree, tree, 0, '*'); } /* key tree */ void addnode(tree, key) Node **tree; /* : , * */ char *key; /* */ { #define TREE (*tree) if( TREE == NULL ){ /* */ TREE = newNode( key ); return; } /* */ if ( strcmp (key, TREE -> data.key) < 0 ) { /* */ if ( TREE -> l == NULL ){ /* */ TREE -> l = newNode(key); return; } else addnode( & TREE ->l , key); } . , 1992-95 - 303 - UNIX else{ /* */ if ( TREE -> r == NULL ){ /* */ TREE -> r = newNode(key); return; } else addnode ( & TREE ->r, key) ; } } /* . */ typedef struct node *NodePtr; static NodePtr delNode; /* */ void delete(key, tree) char *key; /* */ NodePtr *tree; /* */ { extern void doDelete(); if(*tree == NULL){ printf( "%s \n", key ); return; } /* */ else if(strcmp(key, (*tree)->data.key) < 0) delete( key, &(*tree)->l ); else if(strcmp(key, (*tree)->data.key) > 0) delete( key, &(*tree)->r ); else{ /* */ delNode = *tree; /* */ if(delNode->r == NULL) *tree = delNode->l; else if(delNode->l == NULL) *tree = delNode->r; else doDelete( & delNode->l ); free(delNode); } } static void doDelete(rt) NodePtr *rt; { if( (*rt)->r != NULL ) /* */ doDelete( &(*rt)->r ); else{ /* */ delNode->data = (*rt)->data; delNode = *rt; /* free() */ *rt = (*rt)->l; } } . , 1992-95 - 304 - UNIX void main(){ extern char *gets(); char *s; while (gets(buf) != NULL){ /* */ lines++; addnode( & root, buf ); } prTree(root); /* */ freopen("/dev/tty", "r", stdin); do{ printf( " ? " ); if((s = gets(buf)) == NULL) break; delete(buf, &root); prTree( root ); } while( s && root ); printf("Bye-bye.\n"); exit(0); } 7.37. , 10  , . . #include <stdio.h> #include <ctype.h> #define INT 'i' #define STR 's' struct data { char tag; /* , . . */ union { int i; char *s; } value; } a[10]; int counter = 0; /* */ void main(){ char word[128]; int i; char *malloc(unsigned); /* : */ for(counter=0; counter < 10; counter++){ if( gets(word) == NULL ) break; if( isdigit((unsigned char) *word)){ a[counter].value.i = atoi(word); a[counter].tag = INT; } else { a[counter].value.s = malloc(strlen(word)+1); strcpy(a[counter].value.s, word); a[counter].tag = STR; } } /* : */ for(i=0; i < counter; i++) switch(a[i].tag){ case INT: printf(" %d\n", a[i].value.i); break; case STR: printf(" %s\n", a[i].value.s); free(a[i].value.s); break; } . , 1992-95 - 305 - UNIX } 7.38. , , - . , . , - ? . - - . ! 7.38.1. /* . * . */ #include <stdio.h> /* printf(), NULL */ #include <string.h> /* strdup() */ #include <stdlib.h> /* malloc() */ #define A_INT 1 #define A_STR 2 #define A_NULL 0 typedef struct arg { int type; union jack { char *s; int d; } data; struct arg *next; } Arg; void doit(Arg args[], int n){ int i; for(i=0; i < n; i++) switch(args[i].type){ case A_INT: printf("%d", args[i].data.d); break; case A_STR: printf("%s", args[i].data.s); break; default: fprintf(stderr, "Unknown type!\n"); break; } } . , 1992-95 - 306 - UNIX /* union * . */ Arg sample[] = { { A_INT, (char *) 123 }, { A_STR, (char *) " hello, " }, { A_INT, (char *) 456 }, { A_STR, (char *) " world\n" } }; int main(int ac, char *av[]){ doit(sample, sizeof sample / sizeof sample[0]); return 0; } 7.38.2. /* . * : * : * . : * , * . * , * . * C++ * . */ #include <stdio.h> /* printf(), NULL */ #include <string.h> /* strdup() */ #include <stdlib.h> /* malloc() */ #define A_INT 1 #define A_STR 2 #define A_NULL 0 typedef struct arg { int type; union jack { char *s; int d; } data; struct arg *next; } Arg; . , 1992-95 - 307 - UNIX void doit(Arg *arglist){ for( ; arglist; arglist=arglist->next) switch(arglist->type){ case A_INT: printf("%d", arglist->data.d); break; case A_STR: printf("%s", arglist->data.s); break; default: fprintf(stderr, "Unknown type!\n"); break; } } Arg *new_int(int n, Arg *next){ Arg *ptr = (Arg *) malloc(sizeof(Arg)); ptr->type = A_INT; ptr->data.d = n; ptr->next = next; return ptr; } Arg *new_str(char *s, Arg *next){ Arg *ptr = (Arg *) malloc(sizeof(Arg)); ptr->type = A_STR; ptr->data.s = strdup(s); ptr->next = next; return ptr; } int main(int ac, char *av[]){ doit( new_int(123, new_str(" hello, ", new_int(456, new_str(" world\n", NULL)))) ); return 0; } 7.38.3. /* * . */ #include <stdio.h> /* printf(), NULL */ #include <stdarg.h> /* va_... */ #define A_INT 1 #define A_STR 2 #define A_NULL 0 . , 1992-95 - 308 - UNIX void doit(...){ /* */ va_list args; /* - , ... * - ! */ va_start(args, ); for(;;){ switch(va_arg(args, int)){ case A_INT: printf("%d", va_arg(args, int)); break; case A_STR: printf("%s", va_arg(args, char *)); break; case A_NULL: goto breakloop; default: fprintf(stderr, "Unknown type!\n"); break; } } breakloop: va_end(args); } int main(int ac, char *av[]){