doit(
A_INT, 123,
A_STR, " hello, ",
A_INT, 456,
A_STR, " world\n",
A_NULL
);
return 0;
}
7.39. .
- , :
struct data {
int b_key; /* */
char b_data[ DATALEN ]; /* */
};
:
-
-
- ( )
- .
(..
). . fread, fwrite,
fseek. n- :
fseek( fp, (long) n * sizeof(struct data), 0 );
, ,
. , 1992-95 - 309 - UNIX
char b_key[ KEYLEN ];
- KEYLEN , '\0', -
KEYLEN '\0' ( d_name
). , -
(hash - , . ).
.
struct record_header {
int b_key ; /* */
long b_offset; /* */
int b_length; /* () */
};
.
. b_offset
. , fseek b_offset
b_length .
7.40. .
(). : -
( ), , (
, ), -
, (
!). () ( )
, short.
: ( -
) .
. ,
, : .
: 1 - , 0 -
- .
7.41. match(,); -
. :
* - (0 );
? - .
:
[] - .
[!] - , .
[h-z] - h z .
: "" -
.
, , ,
(, "[]**"). ,
, .
. , 1992-95 - 310 - UNIX
#include <stdio.h>
#include <string.h>
#include <locale.h>
#define U(c) ((c) & 0377) /* */
#define QUOT '\\' /* */
#ifndef MATCH_ERR
# define MATCH_ERR printf(" ]\n")
#endif
/* s -
* p - . \ .
*/
int match (register char *s, register char *p)
{
register int scc; /* */
int c, cc, lc; /* lc - [...] */
int ok, notflag;
for (;;) {
scc = U(*s++); /* */
switch (c = U (*p++)) { /* */
case QUOT: /* a*\*b */
c = U (*p++);
if( c == 0 ) return(0); /* : pattern\ */
else goto def;
case '[': /* */
ok = notflag = 0;
lc = 077777; /* */
if(*p == '!'){ notflag=1; p++; }
while (cc = U (*p++)) {
if (cc == ']') { /* */
if (ok)
break; /* */
return (0); /* */
}
if (cc == '-') { /* */
if (notflag){
/* - OK */
if (!syinsy (lc, scc, U (*p++)))
ok++;
/* - */
else return (0);
} else {
/* - OK */
if (syinsy (lc, scc, U (*p++)))
ok++;
}
}
else {
if (cc == QUOT){ /* [\[\]] */
cc = U(*p++);
if(!cc) return(0);/* */
}
if (notflag){
if (scc && scc != (lc = cc))
ok++; /* */
else return (0);
} else {
. , 1992-95 - 311 - UNIX
if (scc == (lc = cc)) /* */
ok++;
}
}
}
if (cc == 0){ /* */
MATCH_ERR;
return (0); /* */
}
continue;
case '*': /* */
if (!*p)
return (1);
for (s--; *s; s++)
if (match (s, p))
return (1);
return (0);
case 0:
return (scc == 0);
default: def:
if (c != scc)
return (0);
continue;
case '?': /* */
if (scc == 0)
return (0);
continue;
}
}
}
/* , smy smax smin
*/
int syinsy (unsigned smin, unsigned smy, unsigned smax)
{
char left [2];
char right [2];
char middle [2];
left [0] = smin; left [1] = '\0';
right [0] = smax; right [1] = '\0';
middle[0] = smy; middle[1] = '\0';
return (strcoll(left, middle) <= 0 && strcoll(middle, right) <= 0);
}
, UNIX , *.c,
( MS DOS), -
(shell: /bin/sh, /bin/csh, /bin/ksh). (
) .
7.42. man regexp include- /usr/include/regexp.h,
compile step
ed, lex, grep:
C
\. \[ \* \$ \^ \\ ;
. , 1992-95 - 312 - UNIX
. \n;
[abc]
[a-b] ( );
[abc-]
-;
[]abc]
[] ] ;
[^a-z]
^ , .. ;
[a-z^]
;
[\*.]
[] , ;
C* (0 ) C;
.* ;
*
(0 ) , [0-9]*
( ) .
;
\{n,m\}
n m (), 255;
\{n,\}
n , [0-9]\{1,\} ;
\{n\}
n ;
$
, , .*define.*\\$
^
, ;
\n ;
\(.....\)
. ;
\N N . N- (
1).
matchReg, .
, matchReg .
:
#include <stdio.h>
#include <ctype.h>
#define INIT register char *sp = instring;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(ptr) return
#define ERROR(code) \
{fprintf(stderr,"%s:ERR%d\n",instring,code);exit(177);}
# include <regexp.h>
#define EOL '\0' /* end of line */
#define ESIZE 512
int matchReg(char *str, char *pattern){
static char oldPattern[256];
static char compiledExpr[ESIZE];
if( strcmp(pattern, oldPattern)){ /* */
/* compile regular expression */
compile(pattern,
compiledExpr, &compiledExpr[ESIZE], EOL);
. , 1992-95 - 313 - UNIX
strcpy(oldPattern, pattern); /* */
}
return step(str, compiledExpr); /* */
}
/* : reg '^int' 'int$' char | less */
/* reg 'putchar.*(.*)' < reg.c | more */
void main(int ac, char **av){
char inputline[BUFSIZ]; register i;
while(gets(inputline)){
for(i=1; i < ac; i++)
if(matchReg(inputline, av[i])){
char *p; extern char *loc1, *loc2;
/*printf("%s\n", inputline);*/
/* ,
* */
for(p=inputline; p != loc1; p++) putchar(*p);
for( ; p != loc2; p++)
if(isspace((unsigned char) *p))
putchar(*p);
else printf("%c\b%c", *p, *p);
for( ; *p; p++) putchar(*p);
putchar('\n');
break;
}
}
}
7.43. <regexp.h> ,
. -
. :
$ regsub '\([0-9]\{1,\}\)' '(\1)'
$ regsub 'f(\(.*\),\(.*\))' 'f(\2,\1)' < file
f(a,b) f(b,a). , -
\(...\), \N
, N - , .
\, : \\.
. , 1992-95 - 314 - UNIX
/* */
#include <stdio.h>
#include <ctype.h>
#define INIT register char *sp = instring;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(ptr) return
#define ERROR(code) regerr(code)
void regerr();
# include <regexp.h>
#define EOL '\0' /* end of line */
#define ESIZE 512
short all = 0;
/* -a , (global, all):
* regsub -a int INT
* "aa int bbb int cccc" -> "aa INT bbb INT cccc"
*
* step() , ,
* regsub 'f(\(.*\),\(.*\))' 'f(\2,\1)'
* "aa f(1,2) bb f(3,4) cc" -> "aa f(4,1,2) bb f(3) cc'
* |___________|_| |_|___________|
*/
char compiled[ESIZE], line[512];
. , 1992-95 - 315 - UNIX
void main(int ac, char *av[]){
register char *s, *p; register n; extern int nbra;
extern char *braslist[], *braelist[], *loc1, *loc2;
if( ac > 1 && !strcmp(av[1], "-a")){ ac--; av++; all++; }
if(ac != 3){
fprintf(stderr, "Usage: %s [-a] pattern subst\n", av[0]);
exit(1);
}
compile(av[1], compiled, compiled + sizeof compiled, EOL);
while( gets(line) != NULL ){
if( !step(s = line, compiled)){
printf("%s\n", line); continue;
}
do{
/* */
for( ; s != loc1; s++) putchar(*s);
/* */
for(s=av[2]; *s; s++)
if(*s == '\\'){
if(isdigit(s[1])){ /* */
int num = *++s - '1';
if(num < 0 || num >= nbra){
fprintf(stderr, "Bad block number %d\n", num+1);
exit(2);
}
for(p=braslist[num]; p != braelist[num]; ++p)
putchar(*p);
} else if(s[1] == '&'){
++s; /* */
for(p=loc1; p != loc2; ++p)
putchar(*p);
} else putchar(*++s);
} else putchar(*s);
} while(all && step(s = loc2, compiled));
/* */
for(s=loc2; *s; s++) putchar(*s);
putchar('\n');
} /* endwhile */
}
. , 1992-95 - 316 - UNIX
void regerr(int code){ char *msg;
switch(code){
case 11: msg = "Range endpoint too large."; break;
case 16: msg = "Bad number."; break;
case 25: msg = "\\digit out of range."; break;
case 36: msg = "Illegal or missing delimiter."; break;
case 41: msg = "No remembered search string."; break;
case 42: msg = "\\(~\\) imbalance."; break;
case 43: msg = "Too many \\(."; break;
case 44: msg = "More than 2 numbers given in \\{~\\\"}."; break;
case 45: msg = "} expected after \\."; break;
case 46: msg = "First number exceeds second in \\{~\\}."; break;
case 49: msg = "[ ] imbalance."; break;
case 50: msg = "Regular expression overflow."; break;
default: msg = "Unknown error"; break;
} fputs(msg, stderr); fputc('\n', stderr); exit(code);
}
void prfields(){
int i;
for(i=0; i < nbra; i++)
prfield(i);
}
void prfield(int n){
char *fbeg = braslist[n], *fend = braelist[n];
printf("\\%d='", n+1);
for(; fbeg != fend; fbeg++)
putchar(*fbeg);
printf("'\n");
}
7.44. . ,
. (
) , .
main().
/* .
* . , . , 1976 Texas
* : Communications of the ACM 20, 10 (Oct., 1977), 762-772
*
*
* , -
* strlen(str).
* ,
* , .
* slen/plen .
*/
char *pattern; /* ( ) */
static int plen; /* */
static int d[256]; /* ; ASCII -
* 256 . */
/* i */
#define DISTANCE(i) ((plen-1) - (i))
. , 1992-95 - 317 - UNIX
/* :
* pattern str,
* -1,
*/
int indexBM( str ) char *str; /* */
{
int slen = strlen(str); /* */
register int pindx; /* */
register int cmppos; /* */
register int endpos; /* , ""
* */
/* */
for( endpos = plen-1; endpos < slen ; ){
/* : pr(str, pattern, endpos - (plen-1), 0); /**/
/* */
for( cmppos = endpos, pindx = (plen - 1);
pindx >= 0 ;
cmppos--, pindx-- )
if( str[cmppos] != pattern[pindx] ){
/* ,
* str[endpos] endpos-
* .
* ( ),
* endpos+1
*
*/
endpos += d[ str[endpos] & 0377 ];
break; /* & 0377 . */
} /* char -> unsigned char */
if( pindx < 0 ) return ( endpos - (plen-1));
/* : */
}
return( -1 ); /* */
}
. , 1992-95 - 318 - UNIX
/* */
void compilePatternBM( ptrn ) char *ptrn; {
register int c;
pattern = ptrn; plen = strlen(ptrn);
/* c - */
for(c = 0; c < 256; c++)
d[c] = plen;
/* */
/* c - */
for(c = 0; c < plen - 1; c++)
d[ pattern[c] & 0377 ] = DISTANCE(c);
/*
* ( )
* .
* , ,
* ( ) .
*/
}
/* */
void pr(s, p, n, nl) char *s, *p;
{
register i;
printf("%4d\t%s\n", nl, s );
printf(" \t");
for(i = 0; i < n; i++ )
putchar( s[i] == '\t' ? '\t' : ' ' );
printf( "%s\n", p );
}
/* fgrep */
#include <stdio.h>
char str[ 1024 ]; /* */
void main(ac, av) char **av;
{
int nline = 0; /* */
int ind;
int retcode = 1;
if(ac != 2){
fprintf(stderr, "Usage: %s 'pattern'\n", av[0] );
exit(33);
}
compilePatternBM( av[1] );
while( gets(str) != NULL ){
nline++;
if((ind = indexBM(str)) >= 0 ){
retcode = 0; /* O'KAY */
pr(str, pattern, ind, nline);
}
}
exit(retcode);
}
. , 1992-95 - 319 - UNIX
/* :
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
peter piper picked a peck of pickled peppers.
peck
*/
7.45. , , -
, main().
match, . grep UNIX (
, ).
7.46. expand(s1, s2),
a-z s1 abcd...xyz s2.
. a-b-c, a-z0-9
-a-g ( , "-", , -
).
7.47. ,
|<1 ><>
|.pp
|<>
( | , a <> - ). - -
, nroff ( UNIX). :
- , ,
\&<, '>
- , ,
.ip <>
<>
- \ \e.
- .,;:!?) ( -
,
. - , ?).
- , nroff :
....xxxx - => ....xxxx
yyyy...... yyyy................
. , 1992-95 - 320 - UNIX
:
$ prep ... | nroff -me > text.lp
7.48. ,
, (-
). . :
<ctype.h>.
:
#include <ctype.h>
#include <stdio.h>
main(){
int c;
while( (c = getchar()) != EOF )
putchar( isalpha( c ) ?
(isupper( c ) ? tolower( c ) : c) : c);
}
...
putchar( isalpha(c) && isupper(c) ? tolower(c) : c );
putchar( isupper(c) ? tolower(c) : c );
isupper islower (,
!).
7.49. , ,
:
char ch;
if( 0300 <= ch && ch < 0340 ) ...;
( -8 ), -
: ch int (
char ). ,
ch (0200),
( ). ! :
char c = '\201'; /* = 129 */
printf( "%d\n", c );
-127. , , .. ch
< 0. :
if( 0300 <= (ch & 0377) && (ch & 0377) < 0340) ...;
(0377 - 8 , 0xFF, ),
unsigned char ch;
, int .
7.50. :
. , 1992-95 - 321 - UNIX
main(){
char ch;
/* 0377 - ASCII */
for (ch = 0100; ch <= 0377; ch++ )
printf( "%03o %s\n",
ch & 0377,
ch >= 0300 && ch < 0340 ? "yes" : "no" );
}
?
- -, 0200 ch , ch -
(.. int ),
"no". ,
unsigned char ch, ch
(ch & 0377) ((unsigned) ch)
- -, . ch =='\377'. ch <= 0377
. ch++. ch - ,
0400 (0377 - ,
- ). ch 0.
0 < 0377 ! ; .. -
. int ch; 0377+1 0400,
0 ( unsigned int, ,
0377).
7.51. , ,
, .
- , - .
. . -->
. .
,
, , .
7.52. , (spell check):
; - .
- , -
- . :
- : =>;
- (): =>;
- : =>;
- : =>;
- : =>;
- - ,
: =>;
. .
: match:
_ = "";
if(strlen(_) <= strlen(_)+1 &&
match(_, "****") ... /* */
*** ? ?
*** ?
*** ?
:
. , 1992-95 - 322 - UNIX
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
typedef unsigned char uchar;
#define ANYCHAR '*'
/* , */
static uchar version[120]; /* */
static uchar vv; /* , ANYCHAR */
/* */
static uchar icase(uchar c){
return isupper(c) ? tolower(c) : c;
}
/* */
static int eqi(uchar *s1, uchar *s2 )
{
while( *s1 && *s2 ){
if( icase( *s1 ) != icase( *s2 ))
break;
s1++; s2++;
}
return ( ! *s1 && ! *s2 ) ? 1 : 0 ;
/* OK : FAIL */
}
/* ANYCHAR */
static strok(register uchar *word, register uchar *pat)
{
while( *word && *pat ){
if( *word == ANYCHAR){
/* , *pat, */
vv= *pat;
} else {
if( icase(*pat) != icase(*word) )
break;
}
word++; pat++;
}
/* ... */
return ( !*word && !*pat) ? 1 : 0;
/* OK : FAIL */
}
. , 1992-95 - 323 - UNIX
/* */
static int superfluous( uchar *word /* */
, uchar *s /* */
){
register int i,j,k;
int reply;
register len = strlen(word);
for(i=0 ; i < len ; i++){
/* , */
k=0;
for(j=0 ; j < i ; j++)
version[k++]=word[j];
for(j=i+1 ; j < len ; j++)
version[k++]=word[j];
version[k]='\0';
if( eqi( version, s )) return 1; /* OK */
}
return 0; /* FAIL */
}
/* */
static int hole; /* , ANYCHAR */
static int lost(uchar *word, uchar *s)
{
register int i,j,k;
register len = strlen(word);
hole= (-1);
for(i=0 ; i < len+1 ; i++){
k=0;
for(j=0 ; j < i ; j++)
version[k++]=word[j];
version[k++]=ANYCHAR;
for(j=i ; j < len ; j++)
version[k++]=word[j];
version[k]='\0';
if( strok( version, s )){
hole=i;
return 1; /* OK */
}
}
return 0; /* FAIL */
}
. , 1992-95 - 324 - UNIX
/* ( ) */
static int changed(uchar *word, uchar *s)
{
register int i,j,k;
register len = strlen(word);
hole = (-1);
for(i=0 ; i < len ; i++){
k=0;
for( j=0 ; j < i ; j++)
version[k++]=word[j];
version[k++]=ANYCHAR;
for( j=i+1 ; j < len ; j++)
version[k++]=word[j];
version[k]='\0';
if( strok( version,s)){
hole=i;
return 1; /* OK */
}
}
return 0; /* FAIL */
}
/* */
static int duplicates(uchar *word, uchar *s, int leng)
{
register int i,j,k;
uchar tmp[80];
if( eqi( word, s )) return 1; /* OK */
for(i=0;i < leng - 1; i++)
/* */
if( word[i]==word[i+1]){
k=0;
for(j=0 ; j < i ; j++)
tmp[k++]=word[j];
for(j=i+1 ; j < leng ; j++)
tmp[k++]=word[j];
tmp[k]='\0';
if( duplicates( tmp, s, leng-1) == 1)
return 1; /* OK */
}
return 0; /* FAIL */
}
. , 1992-95 - 325 - UNIX
/* */
static int swapped(uchar *word, uchar *s)
{
register int i,j,k;
register len = strlen(word);
for(i=0;i < len-1;i++){
k=0;
for(j=0 ; j < i ; j++)
version[k++]=word[j];
version[k++]=word[i+1];
version[k++]=word[i];
for(j=i+2 ; j < len ; j++)
version[k++]=word[j];
version[k]='\0';
if( eqi( version, s))
return 1; /* OK */
}
return 0; /* FAIL */
}
uchar *words[] = {
(uchar *) "bag",
(uchar *) "bags",
(uchar *) "cook",
(uchar *) "cool",
(uchar *) "bug",
(uchar *) "buy",
(uchar *) "cock",
NULL
};
#define Bcase(x, operators) case x: { operators; } break;
char *cname[5] = {
" ",
" ",
" ",
" ",
" "
};
. , 1992-95 - 326 - UNIX
static int spellmatch( uchar *word /* IN */
, uchar *words[] /* IN */
, uchar **indx /* OUT */
){
int i, code, total = (-1);
uchar **ptr;
if(!*word) return -1;
for(ptr = words; *ptr; ++ptr)
if(eqi(word, *ptr)){
if(indx) *indx = *ptr;
return 0;
}
/* , */
for(ptr = words; *ptr; ++ptr){
uchar *s = *ptr;
int max = 5;
for(i=0; i < max; i++){
switch( i ){
Bcase(0,code = swapped(word, s) )
Bcase(1,code = duplicates(word, s, strlen(word)) )
Bcase(2,code = lost(word, s) )
Bcase(3,code = changed(word, s) )
Bcase(4,code = superfluous(word, s) )
}
if(code){
total++;
printf("?\t%s\t%s\n", cname[i], s);
if(indx) *indx = s;
/*
*
*/
if(i==1) max = 4;
}
}
}
return total;
}
. , 1992-95 - 327 - UNIX
void main(){
uchar inpbuf[BUFSIZ];
int n;
uchar *reply, **ptr;
setlocale(LC_ALL, "");
for(ptr = words; *ptr; ptr++)
printf("#\t%s\n", *ptr);
do{
printf("> "); fflush(stdout);
if(gets((char *)inpbuf) == NULL) break;
switch(spellmatch(inpbuf, words, &reply)){
case -1:
printf(" \n"); break;
case 0:
printf(" '%s'\n", reply); break;
default:
printf("\n");
}
} while(1);
}
7.53. , ,
. ,
, . : -
?
#include <stdio.h>
char *strings[] = {
" "
" "
" ",
" ",
NULL
};
void main(){
char **p;
for(p=strings;*p;++p)
printf("%s\n", *p);
}
:
, ANSI :
" " " "
isspace, .
strings