C程序设计语言(第2版)

这儿有一篇写的很好的读后感:http://www.cnblogs.com/xkfz007/articles/2566424.html

第1章 导言

1. 单词计数

#include <stdio.h>                     
int main(){
     int c,nl,nw,nc,flag;
    flag= 0;
    nl=nw=nc= 0;
     while((c=getchar())!=EOF){
        ++nc;
         if(c== ' \n ')
            nl++;
         if(c== '   '||c== ' \n '||c== ' \t ')
            flag= 0;
         else  if(!flag){
            flag= 1;
            ++nw;
        }
    }
    printf( " %3d %3d %3d\n ",nl,nw,nc);
     return  0;
}

2. 函数参数——传值调用

在C语言中,所有函数参数都是通过"值"传递的。也就是说,传递给被调用函数的参数值存放在临时变量中,而不是存放在原来的变量中。这与其他某些语言是不同的。比如,Fortran等语言是通过"引用"调用,Pascal则采用var参数方式,在这些语言中,被调用的函数必须访问原始参数,而不是访问参数的本地副本。

最主要的区别在于,在C语言中,被调用函数不能直接修改主调函数中变量的值,而只能修改其私有临时副本的值。

传值调用的利大于弊。在被调用该函数中,参数可以看作是便于初始化的局部变量,因此额外使用的变量更少。这样程序可以更紧凑简洁。

3. 读入一组文本,打印出最长文本

#include <stdio.h>
int getline_( char s[], int lim){
     int c,i;
    i= 0;
     while(i<lim- 1&&(c=getchar())!=EOF&&c!= ' \n '){
        s[i++]=c;
    }
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        s[i++]=c;
    s[i++]= ' \0 ';
     return i;
}
void copy( char str1[], char str2[]){
     while((*str1++=*str2++)!= ' \0 ');

}
int main(){
     char line[ 256];
     char longest[ 256];
     char shortest[ 256];
     int len;
     int max= 0,min= 256;
     while((len=getline_(line, 256))>- 1){
         if(len>=max)
        {
            max=len;
            copy(longest,line);
        }
         else  if(len<=min)
        {
            min=len;
            copy(shortest,line);
        }
    }
     if(max> 0)
        printf( " %d:%s ",max,longest);
     if(min< 256)
        printf( " %d:%s ",min,shortest);
     return  0;
}

下面是输出结果,输入是上面的源代码:

课后题程序:

习题1-8 编写一个统计空格、制表符和换行符个数的程序。

#include <stdio.h>
  int main(){
      int c,nb,nt,nl;
     nb= 0;
     nt= 0;
     nl= 0;
      while((c=getchar())!=EOF){
          if(c== '   ')
             nb++;
          else  if(c== ' \t ')
             nt++;
          else  if(c== ' \n ')
             nl++;
     }
     printf( " %2d %2d %2d\n ",nb,nt,nl);  
 }

习题1-9 编写一个将输入复制到输出的程序,并将其中连续的多个空格使用一个空格代替

#include <stdio.h>
int main(){
     int c;
     int nb;
     int prec=- 1;
     while((c=getchar())!=EOF){
         if(c== '   '&&prec== '   ')
             continue;
         else                         
        {
            putchar(c);
            prec=c;
        }
    }
}  

习题1-12 编写一个程序,以每行一个单词的形式打印其输入

int main(){
     int c;
     int flag;
    flag= 0;
     while((c=getchar())!=EOF){
         if(c== '   '||c== ' \n '||c== ' \t '){
             if(flag){
                putchar( ' \n ');
                flag= 0;
            }
        }
         else  if(!flag){
            flag= 1;
            putchar(c);
        }
         else{
            putchar(c);
        }
    }
}

习题1-13 编写一个程序,打印输入中单词长度的直方图。水平方向的直方图比较容易绘制,垂直方向的直方图则要困难写。

#include <stdio.h>
#define MAXHIST 15
#define MAXWORD 11
int word_stats( int wl[]){
     int flag;
     int c,nc,i,ovflow;
    flag= 0;
    nc= 0;
    ovflow= 0;
     for(i= 0;i<MAXWORD;i++)
        wl[i]= 0;
     while((c=getchar())!=EOF){
         if(c== '   '||c== ' \n '||c== ' \t '){
             if(flag){
                flag= 0;
//                 if(nc>0)
                 if(nc<MAXWORD)
                    wl[nc]++;
                 else
                    ovflow++;
                nc= 0;
            }
        }
         else  if(!flag){
            flag= 1;
            nc= 1;
        }
         else
            nc++;
    }
     return ovflow;
}
void hist_h( int wl[]){
     int i;
     int maxvlaue= 0;
     int len;
     for(i= 1;i<MAXWORD;i++)
         if(wl[i]>maxvlaue)
            maxvlaue=wl[i];
     for(i= 1;i<MAXWORD;++i){
        printf( " %5d - %5d : ",i,wl[i]);
         if(wl[i]> 0){
             if((len=wl[i]*MAXHIST/maxvlaue)<= 0)
                len= 1;
        }
         else
            len= 0;
         while(len> 0){
            putchar( ' * ');
            len--;
        }
        putchar( ' \n ');
    }
}
void hist_v( int wl[]){
     int i,j;
     int maxvlaue= 0;
     int len;
     for(i= 1;i<MAXWORD;i++)
         if(wl[i]>maxvlaue)
            maxvlaue=wl[i];
     for(i=MAXHIST;i> 0;i--){
         for(j= 1;j<MAXWORD;j++)
             if(wl[j]*MAXHIST/maxvlaue>=i)
                printf( "    *  ");
             else
                printf( "       ");
        putchar( ' \n ');
    }
     for(i= 1;i<MAXWORD;i++)
        printf( " %4d  ",i);
    putchar( ' \n ');
     for(i= 1;i<MAXWORD;i++)
        printf( " %4d  ",wl[i]);
    putchar( ' \n ');
}
int main(){
     int wl[MAXWORD];
     int ovflow;
    ovflow=word_stats(wl);
    hist_h(wl);
    hist_v(wl);
     if(ovflow)
        printf( " Overflow: %d\n ",ovflow);
}

下面是以上面的源文件为输入得到的运行结果:

习题1-18 编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行

#include <stdio.h>
int getline_( char s[], int lim){
     int c;
     int i;
    i= 0;
     while(i<lim- 1&&(c=getchar())!=EOF&&c!= ' \n '){
        s[i++]=c;
    }
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        s[i++]=c;
    s[i++]= ' \0 ';
     return i;
}
int remove_( char s[]){
     int i;
    i= 0;
     while(s[i]!= ' \n ')
        ++i;
    --i;
     while(i>= 0&&(s[i]== '   '||s[i]== ' \t '))
        --i;
     if(i>= 0){
        s[++i]= ' \n ';
        s[++i]= ' \0 ';
    }
     return i;
}
int main(){
     char line[ 256];
     while(getline_(line, 256)> 0){                  
         if(remove_(line)> 0)
            printf( " %s ",line);
    }
}

习题1-19 编写函数rverse(s)将字符串s中的字符顺序颠倒过来。使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序。

#include <stdio.h>
int getline_( char s[], int lim){
     int c;
     int i;
    i= 0;
     while(i<lim- 1&&(c=getchar())!=EOF&&c!= ' \n '){
        s[i++]=c;
    }   
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        s[i++]=c;
    s[i++]= ' \0 ';
     return i;
}   
void reverse_( char s[]){
     int i,j;
     char c;
    i= 0;
     while(s[i]!= ' \0 ')
        i++;
    i--;
     if(s[i]== ' \n ')
        i--;
    j= 0;
     while(j<i){
        c=s[i];
        s[i]=s[j];
        s[j]=c;
        j++;
        i--;
    }
}
int main(){
     char line[ 256];
     while(getline_(line, 256)> 0){
        reverse_(line);
        printf( " %s ",line);                             
    }
}

习题1-20

请编写程序detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止的地方。假设制表符终止的位置是固定的,比如每隔n列就会出现一个制表符终止位。n应该作为变量还是常量呢?

#include <stdio.h>
  #define TABINC 8
  int main(){
      int c,nb,pos;
     nb= 0;
     pos= 1;
      while((c=getchar())!=EOF){
          if(c== ' \t '){
             nb=TABINC-(pos- 1)%TABINC;
              while(nb> 0){
                 putchar( '   ');
                 pos++;
                 nb--;
             }
         }  
          else  if(c== ' \n '){
             putchar(c);
             pos= 1;
         }  
          else{
             putchar(c);
             pos++;
         }
     }
 }

习题1-21 编写程序entab,将空格串替换为最少数量的制表符和空格,但要保持单词之间的间隔不变。假设制表符终止位的位置与练习1-20的detab程序的情况相同。当使用一个制表符或者一个空格都可以到达下一个制表符终止位时,选用那种替换字符比较好?

#include <stdio.h>
#define TABINC 8
int main(){
     int c,nb,nt,pos;
    nb= 0;
    nt= 0;
    pos= 1;
     while((c=getchar())!=EOF){
         if(c== '   '){
             if(pos%TABINC!= 0)
                ++nb;
             else{
                nb= 0;
                nt++;
            }   
        }   
         else{
             while(nt> 0){
                putchar( ' \t ');
                nt--;
            }  
             if(c== ' \t ')
                nb= 0;
             else
                 while(nb> 0){
                    putchar( '   ');
                    nb--;
                }
            putchar(c);
             if(c== ' \n ')
                pos= 0;
             else  if(c== ' \t ')
                pos=pos+(TABINC-(pos- 1)%TABINC)- 1;     
        }
        
        pos++;
    }
}

习题1-22

#include <stdio.h>
#define MAXCOL 10
#define TABINC 8
char line[MAXCOL];
int exptab( int pos);
int findblnk( int pos);
int newpos( int pos);
void printl( int pos);
int main(){
     int c,pos;
    pos= 0;
     while((c=getchar())!=EOF){
        line[pos]=c;
         if(c== ' \t ')
            pos=exptab(pos);
         else  if(c== ' \n ') {
            printl(pos);
            pos= 0;
        }
         else  if(++pos>=MAXCOL){
            pos=findblnk(pos);
            printl(pos);
            pos=newpos(pos);
        }
    }
}
void printl( int pos){
     int i;
     for(i= 0;i<pos;i++)
        putchar(line[i]);
     if(pos> 0)
        putchar( ' \n ');
}
int exptab( int pos){
    line[pos]= '   ';
     for(++pos;pos<MAXCOL&&pos%TABINC!= 0;++pos)
        line[pos]= '   ';
     if(pos<MAXCOL)
         return pos;
     else{
        printl(pos);
         return  0;
    }
}
int findblnk( int pos){
     while(pos> 0&&line[pos]!= '   ')
        pos--;
     if(pos== 0)
         return MAXCOL;
     else
         return pos+ 1;
}
int newpos( int pos){
     int i,j;
     if(pos<= 0||pos>=MAXCOL)
         return  0;
     else{
        i= 0;
         for(j=pos;j<MAXCOL;++j){
            line[i]=line[j];
            ++i;
        }
         return i;
    }
}

习题1-23 编写一个删除C语言程序中所有的注释语句。要正确处理带银行的字符串与字符常量。在C语言中,注释不允许嵌套。

#include <stdio.h>
void rcomment( int c);
void in_comment( void);
void echo_quote( int c);
int main(){
     int c;
     while((c=getchar())!=EOF)
        rcomment(c);
     return  0;
}
void rcomment( int c){
     int d;
     if(c== ' / ')
         if((d=getchar())== ' * ')
            in_comment();
         else  if(d== ' / '){
            putchar(c);
            rcomment(d);
        }
         else{
            putchar(c);
            putchar(d);
        }
     else  if(c== ' \' '||c== ' " ')
        echo_quote(c);
     else
        putchar(c);
}
void in_comment( void){
     int c,d;
    c=getchar();
    d=getchar();
     while(c!= ' * '||d!= ' / '){
        c=d;
        d=getchar();
    }
}
void echo_quote( int c){
     int d;
    putchar(c);
     while((d=getchar())!=c){
        putchar(d);
         if(d== ' \\ ')
            putchar(getchar());
    }
    putchar(d);
}

习题1-24 编写一个程序,检查C语言程序中的基本语法错误

#include <stdio.h>
int brace,brack,paren;
void in_quote( int c);
void in_comment( void);
void search( int c);
int main(){
     int c;
     while((c=getchar())!=EOF){
         if(c== ' / '){
             if((c=getchar())== ' * ')
                in_comment();
             else
                search(c);
        }
         else  if(c== ' \' '||c== ' " ')
            in_quote(c);
         else
            search(c);
         if(brace< 0){
            printf( " Unbalanced braces\n ");
            brace= 0;
        }
         else  if(brack< 0){
            printf( " Unbalanced brackets\n ");
            brack= 0;
        }
         else  if(paren< 0){
            printf( " Unbalanced parentheses\n ");
            paren= 0;
        }
    }
     if(brace> 0)
        printf( " Unbalanced braces\n ");
     if(brack> 0)
        printf( " Unbalanced brackets\n ");
     if(paren> 0)
        printf( " Unbalanced parentheses\n ");

}
void search( int c){
     if(c== ' { ')
        ++brace;
     else  if(c== ' } ')
        --brace;
     else  if(c== ' [ ')
        ++brack;
     else  if(c== ' ] ')
        --brack;
     else  if(c== ' ( ')
        ++paren;
     else  if(c== ' ) ')
        --paren;
}
void in_comment( void){
     int c,d;
    c=getchar();
    d=getchar();
     while(c!= ' * '||d!= ' / '){
        c=d;
        d=getchar();
    }
}
void in_quote( int c){
     int d;
     while((d=getchar())!=c)
             if(d== ' \\ ')
            getchar();
}

第2章 类型,运算符与表达式

1. const限定符

任何变量的声明都可以使用const限定符限定。该限定符指定变量的值不能被修改。对于数组而言,const限定符指定数组所有元素的值都不能被修改。

const char msg[]="warning:";

const限定符也可以配合数组参数使用,它表明函数不能修改该数组元素的值。

2. char类型

char类型是小整型

3. 算术中的隐式类型转换

一般情况下,如果不含有unsigned类型,可以采用下面的方式:

注意float类型的特殊性:

当表达式中含有unsigned类型时:

函数参数中的类型转换:

4. 标准库中的伪随机数发生器函数:rand和srand

标准库中包含一个可移植的实现伪随机数发生器的函数rand以及一个初始化种子数的函数srand。rand函数中使用了强制类型转换:

unsigned  long  int next= 1;
/* rand:return pseudo-random integer on 0..32767 */
int rand( void)
{
next=next* 1103515245+ 12345;
return (unsigned  int)(next/ 65536)% 32768;
}
/* srand:set seed for rand() */
void srand(unsigned  int seed){
 next=seed;
}

习题2-3 编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型数。字符串中允许包含的数字包括:0~9,a~f以及A-F

#include <stdio.h>
#include <stdlib.h>
#define YES 1
#define NO 0
int htoi( char s[]){
     int hexd,i,inhex,n;
    i= 0;
     if(s[i]== ' 0 '){
        ++i;
         if(s[i]== ' x '||s[i]== ' X ')
            ++i;
    }
    n= 0;
    inhex=YES;
     while(inhex){
         if(s[i]>= ' 0 '&&s[i]<= ' 9 ')
            hexd=s[i]- ' 0 ';
         else  if(s[i]>= ' a '&&s[i]<= ' f ')
            hexd=s[i]- ' a '+ 10;
         else  if(s[i]>= ' A '&&s[i]<= ' F ')
            hexd=s[i]- ' A '+ 10;
         else
            inhex=NO;
         if(inhex==YES)
            n= 16*n+hexd;
        i++;
    }
     return n;
}
int main(){
     int count= 10;
     int i;
     char s[ 100];
     for(i= 0;i< 10;i++){
         int num=rand()% 10000;
         int n;
        sprintf(s, " %#0x ",num);
        n=htoi(s);                                     
        printf( " %#0x %s %d %d \n ",num,s,num,n);
        
    }
    
}

一个运行结果展示:

习题2-4 重写函数squeeze(s1,s2),将字符串s1中任何与字符串s2中字符匹配的字符都删除

void squeeze( char s1[], char s2[]){
     int i,j,k;
     for(i=k= 0;s1[i]!= ' \0 ';i++){
         for(j= 0;s2[j]!= ' \0 '&&s2[j]!=s1[i];j++);
         if(s2[j]== ' \0 ')
            s1[k++]=s1[i];
    }
    s1[k]= ' \0 ';                                     
}

习题2-5

void any( char s1[], char s2[]){
     int i,j;
     for(i= 0;s1[i]!= ' \0 ';i++)
         for(j= 0;s2[j]!= ' \0 ';j++)
             if(s1[i]==s2[j])
                 return i;
     return - 1;                         
}

5. C语言中的位操作

getbits函数:返回x中从右边数第p位开始向右数n位的字段。这里假定最右边的一位是第0位,n与p都是合理的正值。

unsigned getbits(unsigned x, int p, int n){
      return (x>>(p+ 1-n))&~(~ 0<<n);
 }

unsigned sebits(unsgined x, int p, int n,unsigned y){
     unsigned x1=x&(~ 0<<(p+ 1)); // 获取x的高32-(p+1)位
     unsigned x2=x&(( 1<<(p-n+ 1))- 1); // 获取x的低p-n+1位
     unsigned y1=(y&~(~ 0<<n))<<(p+ 1-n); // 获得y的最低n位,并且移动到合适的位置
      return x1|x2|y1;
 }

可以换一种方式写:

unsigned sebits(unsgined x, int p, int n,unsigned y){
     unsigned m1= (~ 0<<(p+ 1))| (( 1<<(p-n+ 1))- 1); // 得到屏蔽码
unsigned x1=x&m1;
     unsigned y1=(y&~(~ 0<<n))<<(p+ 1-n); // 获得y的最低n位,并且移动到合适的位置
      return x1|y1;
 }

下面是一个标准答案:

这儿比较难写是就是x的屏蔽码,下面的程序是对比两种方法产生的屏蔽码:

#include <stdio.h>
#include <stdlib.h>
int main(){
     int i;
     for(i= 0;i< 10;i++){
         int p=rand()% 32;
         int n=rand()%p+ 1;
        unsigned m1=(~ 0<<(p+ 1))|(( 1<<(p-n+ 1))- 1);
        unsigned m2=~(~(~ 0<<n)<<(p+ 1-n));
        printf( " p=%d n=%d: %#0x %#0x  ",p,n,m1,m2);      
         if(m1==m2)
            printf( " OK\n ");
         else
            printf( " NO\n ");    
    }
}

一个输出结果如下:

unsigned invert(unsigned x, int p, int n){
     unsigned x1=x&(~ 0<<(p+ 1)); // 获取x的高32-(p+1)位
     unsigned x2=x&(( 1<<(p-n+ 1))- 1); // 获取x的低p-n+1位
     unsigned x3=~x&(~(~ 0<<n)<<(p-n+ 1)); // 获取x的中间n位
      return x1|x2|x3;
 }

下面是一个标准答案

下面是一个测试:

#include <stdio.h>
#include <stdlib.h>
unsigned invert(unsigned x, int p, int n){
    unsigned m1=(~ 0<<(p+ 1)); // 获取x的高32-(p+1)位
    unsigned x1=x&m1;
    unsigned m2=(( 1<<(p-n+ 1))- 1); // 获取x的低p-n+1位
    unsigned x2=x&m2;
    unsigned m3=(~(~ 0<<n)<<(p-n+ 1)); // 获取x的中间n位
    unsigned x3=(~x)&m3;
    printf( " %#0x %#0x %#0x\n ",m1,m2,m3);
     return x1|x2|x3;
}
unsigned invert2(unsigned x, int p, int n){
     return x^(~(~ 0<<n)<<(p+ 1-n));
}
int main(){
     int i;
    unsigned x=rand();
     for(i= 0;i< 25;i++){                                                  
         int p=rand()% 32;
         int n=rand()%p+ 1;
         int y1=invert(x,p,n);
         int y2=invert2(x,p,n);
        printf( " %#0x %2d %2d %#0x %#0x  ",x,p,n,y1,y2);
         if(y1==y2)
            printf( " OK\n ");
         else
            printf( " NO\n ");

}
}

输出如下:

可以看到当p=31时,第一种方法就出错了。主要是将一个无符号数进行右移32位(移出所有位)时,编译器会给出一个【 warning: right shift count >= width of type】的警告。然后返回原始值,而不是0

unsigned rightrot(unsigned x, int n){
     unsigned x1=x>>n; // 左移得到高32-n位
     unsigned x2=x<<( sizeof(x)* 8-n); // 右移得到低n位
      return x1|x2;                                      
 }

下面标准答案给出的解释:

#include <stdio.h>
int wordlength()
{                                         
     int i;
    unsigned v=(unsigned)~ 0;
     for(i= 1;(v=v>> 1)> 0;i++)
        ;
     return  1;
}       
unsigned rightrot(unsigned x, int n){
     int rbit;
     while(n--> 0){
        rbit=(x& 1)<<(wordlength()- 1);
        x=x>> 1;
        x=x|rbit;
    }   
     return x;
}       

unsigned rightrot2(unsigned x, int n){
    unsigned rbits;
     if((n-n%wordlength())> 0){
        rbits=~(~ 0<<n)&x;
        rbits=rbits<<(wordlength()-n);
        x=x>>n;
        x=x|rbits;
    }
     return x;
}

6. 统计整型数中二进制位1的个数:

int bitcount(unsigned x){
     int n= 0;
     while(x!= 0){
         if(x& 0x1)
            n++;
        x>> 1;
    }
     return n;                  
}

习题 2-9 在求对二的补码时,表达式x&(x-1)可以删除x中最右边为1的一个二进制位。请解释这样做的道理。用这一方法重写bitcount函数, 以加快其执行速度。

重写的代码如下:

int bitcount(unsigned x){
     int b;
    b= 0;
     while(x!= 0){
        b++;
        x&=x- 1;
    }
     return b;
}   

第3章 程序流控制

1. 折半查找

int bin_search( int x, int v[], int n){
     int low,high,mid;
    low= 0;
    high=n- 1;
     while(low<=high){
        mid=(low+high)>> 1;
         if(x<v[mid])
            high=mid- 1;
         else  if(x>v[mid])
            low=mid+ 1;
         else
             return mid;
    }
     return - 1;
}

int bin_search( int x, int v[], int n){
     int low,high,mid;
    low= 0;
    high=n- 1;
    mid=(low+high)/ 2;
     while(low<=high&&x!=v[mid]){
         if(x<v[mid])
            high=mid- 1;
         else
            low=mid+ 1;
        mid=(low+high)/ 2;
    }
     if(x==v[mid])
         return mid;
     else
         return - 1;                            
}

2. atoi函数

字符串转换为对应数值的函数atoi

View Code

测试输出如下:

希尔排序shell

shell算法是D.L. Shell于1959年发明的,基本思想是:先比较近距离的元素,而不是像简单交换排序算法那样先比较相邻的元素。这样可以快速减少大量的无序情况,从而减轻后序的工作。被比较的元素之间的距离逐步减少,直到减少为1,这时编程了相邻元素的互换。

#include <stdio.h>
#include <stdlib.h>
void shellsort( int v[], int n){
     int gap,i,j,temp;
     for(gap=n/ 2;gap> 0;gap/= 2)
         for(i=gap;i<n;i++)
             for(j=i-gap;j>= 0&&v[j]>v[j+gap];j-=gap){
                temp=v[j];
                v[j]=v[j+gap];
                v[j+gap]=temp;
            }
}
void print_arr( int v[], int n){
     int i;
     for(i= 0;i<n;i++)
        printf( " %4d ",v[i]);
    printf( " \n ");
}                                                          
int main(){
     int i;
     for(i= 0;i< 10;i++){
         int arr[ 20],j,b[ 20];
         for(j= 0;j< 20;j++)
        {
             int val=rand()% 1000;
            arr[j]=val;
            b[j]=val;
        }
        printf( " before: ");
        print_arr(b, 20);
        shellsort(arr, 20);
        printf( " after : ");
        print_arr(arr, 20);
    }
}

测试输出如下:

习题 3-3 讲些函数expand(s1,s2),将字符串s1中类似于a-z一类的速记符号在字符串s2中扩展为等价的完整列表abc...xyz。该函数可以处理大小写字母和数字,并且可以处理a-b-c,a-z0-9与a-z等类似的情况。作为前导和尾随的字符原样复制。

#include <stdio.h>
void expand( char s1[], char s2[]){
     char c;
     int i,j;
    i= 0;
    j= 0; 
     while((c=s1[i++])!= ' \0 '){
         if(s1[i]== ' - '&&s1[i+ 1]>=c){
            i++;
             while(c<s1[i])
                s2[j++]=c++;
        }
         else
            s2[j++]=c;
    }
    s2[j]= ' \0 ';                          
}

函数itoa:将整型数转化为字符串

#include <stdio.h>
void itoa( int n, char s[]){
     int i,sign;
     int x,y;
     if((sign=n)< 0)
        n=-n;
    i= 0;                                          
     do{
        s[i++]=n% 10+ ' 0 ';
    }
     while((n/= 10)> 0);
     if(sign< 0)
        s[i++]= ' - ';
    s[i]= ' \0 ';
    
     for(x= 0,y=i- 1;x<y;x++,y--) {
         char c=s[x];
        s[x]=s[y];
        s[y]=c;
    }
}
int atoi_( char s[]){
     int i,n,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(n= 0;isdigit(s[i]);i++)
        n= 10*n+(s[i]- ' 0 ');
     return sign*n;
}
int main(){
     int i;
     char s[ 20];
     for(i= 0;i< 10;i++){
         int val=rand();
         int d;
        itoa(val,s);
        d=atoi_(s);

printf( " %12d %12s %12d  ",val,s,d);
         if(val==d)
            printf( " OK\n ");
         else
            printf( " NO\n ");
    }
}

测试结果如下:

习题3-4

void itoa2( int n, char s[]){
      int i,sign;
      int x,y;
     sign=n;
     i= 0;
      do{
         s[i++]= ABS(n% 10)+ ' 0 ';
     }
      while((n/= 10)!= 0);
      if(sign< 0)
         s[i++]= ' - ';
     s[i]= ' \0 ';
     
      for(x= 0,y=i- 1;x<y;x++,y--) {
          char c=s[x];
         s[x]=s[y];
         s[y]=c;
     }
 }

习题 3-5 编写函数itob(n,s,b),将整数n转换为以b为底的数,并将结果以字符的形式保存到字符串s中。例如,itob(n,s,16)把整数n格式化为十六进制整数保存在s中。

#include <stdio.h>
#define ABS(x) ((x)<0?-(x):(x))
void itob( int n, char s[], int b){
     int i,j,sign;
     int x,y;
    sign=n;
    i= 0;
     do{
        j=ABS(n%b);
        s[i++]=(j< 10)?j+ ' 0 ':j+ ' a '- 10;
    }
     while((n/=b)!= 0);
     if(sign< 0)
        s[i++]= ' - ';
    s[i]= ' \0 ';
     for(x= 0,y=i- 1;x<y;x++,y--) {
         char c=s[x];
        s[x]=s[y];
        s[y]=c;
    }
}
void test_10(){
     int i;
     char s[ 20];
     for(i= 0;i< 10;i++){
         int val=rand();
         int d;
         if(val& 0x1)
            val=-val;
        itob(val,s, 10);
        sscanf(s, " %d ",&d);

printf( " %12d %12s %12d  ",val,s,d);
         if(val==d)
            printf( " OK\n ");
         else
            printf( " NO\n ");
    }
}
void test_8(){
     int i;
     char s[ 20];
     for(i= 0;i< 10;i++){
         int val=rand();
         int d;
         if(val& 0x1)
            val=-val;
        itob(val,s, 8);
//         d=atoi_(s);
        sscanf(s, " %o ",&d);
        printf( " %#14o %14s %#14o  ",val,s,d);
         if(val==d)
            printf( " OK\n ");
         else
            printf( " NO\n ");
    }
}
void test_16(){
     int i;
     char s[ 40];
     for(i= 0;i< 10;i++){
         int val=rand();
         int d;
         if(val& 0x1)
            val=-val;
        itob(val,s, 16);
        sscanf(s, " %x ",&d);
        printf( " %#14x %14s %#14x  ",val,s,d);
         if(val==d)
            printf( " OK\n ");
         else
            printf( " NO\n ");
    }
}
int main(){
    printf( " base-10\n ");
    test_10();
    printf( " =========================\n ");
    printf( " base-8\n ");
    test_8();
    printf( " =========================\n ");
    printf( " base-16\n ");
    test_16();
}

我们在测试程序中进行8,10和16三种进制的测试。主要是C语言提供到这三种进制的转换,这样便于我们的测试。

测试结果如下:

函数trim:用于删除字符串尾部的空格、制表符与换行符。当发现最右边的字符为非空格符、非制表符、非换行符时,就使用break语句从循环中退出。

#include <stdio.h>
int trim( char s[]){
     int i;
     for(i=strlen(s)- 1;i>= 0;i--)
         if(s[i]!= '   '&&s[i]!= ' \t '&&s[i]!= ' \n ')
             break;
    s[i+ 1]= ' \0 ';
     return i;
}

第4章 函数与程序结构

1. 实现类似UNIX系统上的grep类似的功能:strindex

#include <stdio.h>
  #define MAXLINE 1000
  char pattern[]= " line ";                                       
  int getline_( char line[], int lim){
      int i,c;
     i= 0;
      while(i<lim- 1&&((c=getchar())!=EOF)&&c!= ' \n ')
         line[i++]=c;
      if(c==EOF&&i== 0)
          return - 1;
      if(c== ' \n ')
         line[i++]=c;
     line[i]= ' \0 ';
      return i;
 }
  int strindex( char src[], char itm[]){
      int i,j;
  //     int len1=strlen(src);
  //     int len2=strlen(itm);
      for(i= 0;src[i]!= ' \0 ';i++){
          int k;
 
          for(j= 0,k=i;itm[j]!= ' \0 '&&itm[j]==src[k];j++,k++);
          if(itm[j]== ' \0 ')
              return i;
     }
      return - 1;
 }
  int main(){
      char line[MAXLINE];
      int found= 0;
      while(getline_(line,MAXLINE)> 0)
          if(strindex(line,pattern)>= 0){
             printf( " %s ",line);
             found++;
         }
 
 }

习题 4-1 编写函数strrindex(s,t),它返回字符串t在s中最右边出现的位置。如果s中不包含t,则返回-1

int strrindex( char s[], char t[]){
     int i,j;
     int pos=- 1;
     for(i= 0;s[i]!= ' \0 ';i++){
         int k;

for(j= 0,k=i;t[j]!= ' \0 '&&t[j]==s[k];j++,k++);
         if(t[j]== ' \0 ')
            pos=i;
    }
     return pos;
}

int strrindex2( char s[], char t[]){
     int i,j;
     int ls=strlen(s);
     int lt=strlen(t);
     for(i=ls-lt;i>= 0;i--){
         int k;
         for(j= 0,k=i;t[j]!= ' \0 '&&t[j]==s[k];j++,k++);
         if(t[j]== ' \0 ')
             return i;
    }
     return - 1;
}

函数atof:将字符串转换为浮点数

#include <stdio.h>
#include <ctype.h>
double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }  
     return sign*val/power;
}   
int main(){
     int i;
     for(i= 0;i< 25;i++){
         double val=rand()% 100000/ 100.0;
         char s[ 20];
         double val2;
        sprintf(s, " %f ",val);
        val2=atof_(s);
        printf( " %10.5f %12s %10.5f\n ",val,s,val2);      
    }
}   

习题4-2 对atof函数进行扩充,使他可以处理形如:

123.45e-6

的科学表示法,其中浮点数后面可能会紧跟一个e或E以及一个指数(可能有正负号)。

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

4.3 外部变量

一个简单的计算器程序

#if 1
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

#define MAXVAL 1000
int sp= 0;
double val[MAXVAL];
void push( double f){
     if(sp<MAXVAL)
        val[sp++]=f;
     else
        printf( " error:stack full\n ");
}
double pop( void){
     if(sp> 0)
         return val[--sp];
     else
        printf( " error:stack empty\n ");
     return  0.0;
}

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}

#define MAXOP 1000
#define NUMBER '0'
int getop( char s[]){
     int i,c;
     while((s[ 0]=c=getch())== '   '||c== ' \t ')
        ;
    s[ 1]= ' \0 ';
     if(!isdigit(c)&&c!= ' . ')
         return c;
    i= 0;
     if(isdigit(c))
         while(isdigit(s[++i]=c=getch()))
            ;
     if(c== ' . ')
         while(isdigit(s[++i]=c=getch()))
            ;
    s[i]= ' \0 ';
     if(c!=EOF)
        ungetch(c);
     return NUMBER;
}

int main(){
     int type;
     double op2;
     char s[MAXOP];
     while((type=getop(s))!=EOF){
         switch(type){
             case NUMBER:
                push(atof_(s));
                 break;
             case  ' + ':
                push(pop()+pop());
                 break;
             case  ' - ':
                op2=pop();
                push(pop()-op2);
                 break;
             case  ' * ':
                push(pop()*pop());
                 break;
             case  ' / ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(pop()/op2);
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' \n ':
                printf( " \t%.8g\n ",pop());
                 break;
             default:
                printf( " error: unknown command %s\n ",s);
                 break;
        }
    }
}

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

#define MAXVAL 1000
int sp= 0;
double val[MAXVAL];
void push( double f){
     if(sp<MAXVAL)
        val[sp++]=f;
     else
        printf( " error:stack full\n ");
}
double pop( void){
     if(sp> 0)
         return val[--sp];
     else
        printf( " error:stack empty\n ");
     return  0.0;
}

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}

#define MAXOP 1000
#define NUMBER '0'
int getop( char s[]){
     int i,c;
     while((s[ 0]=c=getch())== '   '||c== ' \t ')
        ;
    s[ 1]= ' \0 ';
     if(!isdigit(c)&&c!= ' . '&&c!= ' - ')
         return c;
    i= 0;
     if(c== ' - ')
         if(isdigit(c=getch())||c== ' . ')
            s[++i]=c;
         else
        {
             if(c!=EOF)
                ungetch(c);
             return  ' - ';
        }
     if(isdigit(c))
         while(isdigit(s[++i]=c=getch()))
            ;
     if(c== ' . ')
         while(isdigit(s[++i]=c=getch()))
            ;
    s[i]= ' \0 ';
     if(c!=EOF)
        ungetch(c);
     return NUMBER;
}

int main(){
     int type;
     double op2;
     char s[MAXOP];
     while((type=getop(s))!=EOF){
         switch(type){
             case NUMBER:
                push(atof_(s));
                 break;
             case  ' + ':
                push(pop()+pop());
                 break;
             case  ' - ':
                op2=pop();
                push(pop()-op2);
                 break;
             case  ' * ':
                push(pop()*pop());
                 break;
             case  ' / ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(pop()/op2);
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' % ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(fmod(pop(),op2));
                 else
                    printf( " error:zero divisor\n ");
                 break;

case  ' \n ':
                printf( " \t%.8g\n ",pop());
                 break;
             default:
                printf( " error: unknown command %s\n ",s);
                 break;
        }
    }
}

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

#define MAXVAL 1000
int sp= 0;
double val[MAXVAL];
void push( double f){
     if(sp<MAXVAL)
        val[sp++]=f;
     else
        printf( " error:stack full\n ");
}
double pop( void){
     if(sp> 0)
         return val[--sp];
     else
        printf( " error:stack empty\n ");
     return  0.0;
}
void clear( void){
    sp= 0;
}

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}

#define MAXOP 1000
#define NUMBER '0'
int getop( char s[]){
     int i,c;
     while((s[ 0]=c=getch())== '   '||c== ' \t ')
        ;
    s[ 1]= ' \0 ';
     if(!isdigit(c)&&c!= ' . '&&c!= ' - ')
         return c;
    i= 0;
     if(c== ' - ')
         if(isdigit(c=getch())||c== ' . ')
            s[++i]=c;
         else
        {
             if(c!=EOF)
                ungetch(c);
             return  ' - ';
        }
     if(isdigit(c))
         while(isdigit(s[++i]=c=getch()))
            ;
     if(c== ' . ')
         while(isdigit(s[++i]=c=getch()))
            ;
    s[i]= ' \0 ';
     if(c!=EOF)
        ungetch(c);
     return NUMBER;
}

int main(){
     int type;
     double op1,op2;
     char s[MAXOP];
     while((type=getop(s))!=EOF){
         switch(type){
             case NUMBER:
                push(atof_(s));
                 break;
             case  ' + ':
                push(pop()+pop());
                 break;
             case  ' - ':
                op2=pop();
                push(pop()-op2);
                 break;
             case  ' * ':
                push(pop()*pop());
                 break;
             case  ' / ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(pop()/op2);
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' % ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(fmod(pop(),op2));
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' ? ':
                op2=pop();
                printf( " \t%.8g\n ",op2);
                push(op2);
                 break;
             case  ' c ':
                clear();
                 break;
             case  ' d ':
                op2=pop();
                push(op2);
                push(op2);
                 break;
             case  ' s ':
                op1=pop();
                op2=pop();
                push(op1);
                push(op2);
             case  ' \n ':
                printf( " \t%.8g\n ",pop());
                 break;
             default:
                printf( " error: unknown command %s\n ",s);
                 break;
        }
    }
}

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include < string.h>
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

#define MAXVAL 1000
int sp= 0;
double val[MAXVAL];
void push( double f){
     if(sp<MAXVAL)
        val[sp++]=f;
     else
        printf( " error:stack full\n ");
}
double pop( void){
     if(sp> 0)
         return val[--sp];
     else
        printf( " error:stack empty\n ");
     return  0.0;
}

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}

void mathfnc( char s[]){
     double op2;
     if(strcmp(s, " sin ")== 0)
        push(sin(pop()));
     else  if(strcmp(s, " cos ")== 0)
        push(cos(pop()));
     else  if(strcmp(s, " exp ")== 0)
        push(exp(pop()));
     else  if(strcmp(s, " pow ")== 0) {
        op2=pop();
        push(pow(pop(),op2));
    }
     else
        printf( " error: %s not supported\n ",s);
}

#define MAXOP 1000
#define NUMBER '0'
#define NAME 'n'
int getop( char s[]){
     int i,c;
     while((s[ 0]=c=getch())== '   '||c== ' \t ')
        ;
    s[ 1]= ' \0 ';
    i= 0;
     if(islower(c)){
         while(islower(s[++i]=c=getch()))
            ;
        s[i]= ' \0 ';
         if(c!=EOF)
            ungetch(c);
         if(strlen(s)> 1)
             return NAME;
         else 
             return c;
    }
     if(!isdigit(c)&&c!= ' . '&&c!= ' - ')
         return c;
     if(c== ' - ')
         if(isdigit(c=getch())||c== ' . ')
            s[++i]=c;
         else
        {
             if(c!=EOF)
                ungetch(c);
             return  ' - ';
        }
     if(isdigit(c))
         while(isdigit(s[++i]=c=getch()))
            ;
     if(c== ' . ')
         while(isdigit(s[++i]=c=getch()))
            ;
    s[i]= ' \0 ';
     if(c!=EOF)
        ungetch(c);
     return NUMBER;
}

int main(){
     int type;
     double op1,op2;
     char s[MAXOP];
     while((type=getop(s))!=EOF){
         switch(type){
             case NUMBER:
                push(atof_(s));
                 break;
             case NAME:
                mathfnc(s);
                 break;
             case  ' + ':
                push(pop()+pop());
                 break;
             case  ' - ':
                op2=pop();
                push(pop()-op2);
                 break;
             case  ' * ':
                push(pop()*pop());
                 break;
             case  ' / ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(pop()/op2);
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' % ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(fmod(pop(),op2));
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' \n ':
                printf( " \t%.8g\n ",pop());
                 break;
             default:
                printf( " error: unknown command %s\n ",s);
                 break;
        }
    }
}

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

#define MAXVAL 1000
int sp= 0;
double val[MAXVAL];
void push( double f){
     if(sp<MAXVAL)
        val[sp++]=f;
     else
        printf( " error:stack full\n ");
}
double pop( void){
     if(sp> 0)
         return val[--sp];
     else
        printf( " error:stack empty\n ");
     return  0.0;
}

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}

#define MAXOP 1000
#define NUMBER '0'
int getop( char s[]){
     int i,c;
     while((s[ 0]=c=getch())== '   '||c== ' \t ')
        ;
    s[ 1]= ' \0 ';
     if(!isdigit(c)&&c!= ' . '&&c!= ' - ')
         return c;
    i= 0;
     if(c== ' - ')
         if(isdigit(c=getch())||c== ' . ')
            s[++i]=c;
         else
        {
             if(c!=EOF)
                ungetch(c);
             return  ' - ';
        }
     if(isdigit(c))
         while(isdigit(s[++i]=c=getch()))
            ;
     if(c== ' . ')
         while(isdigit(s[++i]=c=getch()))
            ;
    s[i]= ' \0 ';
     if(c!=EOF)
        ungetch(c);
     return NUMBER;
}

int main(){
     int type,i, var= 0;
     double op2, v;
     char s[MAXOP];
     double variable[ 26];
     for(i= 0;i< 26;i++)
        variable[i]= 0.0;
    
     while((type=getop(s))!=EOF){
         switch(type){
             case NUMBER:
                push(atof_(s));
                 break;
             case  ' + ':
                push(pop()+pop());
                 break;
             case  ' - ':
                op2=pop();
                push(pop()-op2);
                 break;
             case  ' * ':
                push(pop()*pop());
                 break;
             case  ' / ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(pop()/op2);
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' % ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(fmod(pop(),op2));
                 else
                    printf( " error:zero divisor\n ");
                 break;

case  ' \n ':
                v=pop();
                printf( " \t%.8g\n ",v);
                 break;
             case  ' = ':
                pop();
                 if( var>= ' A '&& var<= ' Z ')
                    variable[ var- ' A ']=pop();
                 else
                    printf( " error: no variable name\n ");
                 break;
             default:
                 if(type>= ' A '&&type<= ' Z ')
                    push(variable[type- ' A ']);
                 else  if(type == ' v ')
                    push(v);
                 else
                    printf( " error: unknown command %s\n ",s);
                 break;
        }
         var=type;
    }
}

#include <stdio.h>
#include < string.h>
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}
void ungets( char s[]){
     int len=strlen(s);
     while(len> 0)
        ungetch(s[--len]);
}

char buf= 0;
int getch( void){
     int c;
     if(buf!= 0)
        c=buf;
     else
        c=getchar();
    buf= 0;
     return c;
}  
void ungetch( int c){
     if(buf!= 0)
        printf( " ungetch:too many characters\n ");
     else
        buf=c;                                    
}

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}

#define MAXVAL 1000
int sp= 0;
double val[MAXVAL];
void push( double f){
     if(sp<MAXVAL)
        val[sp++]=f;
     else
        printf( " error:stack full\n ");
}
double pop( void){
     if(sp> 0)
         return val[--sp];
     else
        printf( " error:stack empty\n ");
     return  0.0;
}

// #define BUFSIZE 100
// char buf[BUFSIZE];
// int bufp=0;
// int getch(void){
//     return bufp>0?buf[--bufp]:getchar();
// }
// void ungetch(int c){
//     if(bufp>=BUFSIZE)
//         printf("ungetch: too many characters\n");
//     else
//         buf[bufp++]=c;
// }

#define MAXLINE 100
char line[MAXLINE];
int li= 0;
int getline_( char line[], int lim){
     int i,c;
    i= 0;
     while(i<lim- 1&&((c=getchar())!=EOF)&&c!= ' \n ')
        line[i++]=c;
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        line[i++]=c;
    line[i]= ' \0 ';
     return i;
}
#define MAXOP 1000
#define NUMBER '0'
int getop( char s[]){
     int i,c;
     if(line[li]== ' \0 ')
         if(getline_(line,MAXLINE)==- 1)
             return EOF;
         else
            li= 0;
     while((s[ 0]=c=line[li++])== '   '||c== ' \t ')
        ;
    s[ 1]= ' \0 ';
     if(!isdigit(c)&&c!= ' . '&&c!= ' - ')
         return c;
    i= 0;
     if(c== ' - ')
         if(isdigit(c=line[li++])||c== ' . ')
            s[++i]=c;
         else
        {
             if(c!=EOF)
                li--;
             return  ' - ';
        }
     if(isdigit(c))
         while(isdigit(s[++i]=c=line[li++]))
            ;
     if(c== ' . ')
         while(isdigit(s[++i]=c=line[li++]))
            ;
    s[i]= ' \0 ';
    li--;
     return NUMBER;
}

int main(){
     int type;
     double op2;
     char s[MAXOP];
     while((type=getop(s))!=EOF){
         switch(type){
             case NUMBER:
                push(atof_(s));
                 break;
             case  ' + ':
                push(pop()+pop());
                 break;
             case  ' - ':
                op2=pop();
                push(pop()-op2);
                 break;
             case  ' * ':
                push(pop()*pop());
                 break;
             case  ' / ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(pop()/op2);
                 else
                    printf( " error:zero divisor\n ");
                 break;
             case  ' % ':
                op2=pop();
                 if(ABS(op2)>1e- 10)
                    push(fmod(pop(),op2));
                 else
                    printf( " error:zero divisor\n ");
                 break;

case  ' \n ':
                printf( " \t%.8g\n ",pop());
                 break;
             default:
                printf( " error: unknown command %s\n ",s);
                 break;
        }
    }
}

快速排序

#include <stdio.h>
// #include <stdlib.h>
void swap( int *x, int *y){
     int temp=*x;
    *x=*y;
    *y=temp;
}
void qsort( int v[], int left, int right){
     int i,last;
     if(left>=right)
         return;
    swap(v+left,v+(left+right)/ 2);
    last=left;
     for(i=left+ 1;i<=right;i++)
         if(v[i]<v[left]) {
            last++;
            swap(v+last,v+i);
        }
    swap(v+left,v+last);
    qsort(v,left,last- 1);
    qsort(v,last+ 1,right);
}
void Qsort( int v[], int n){
    qsort(v, 0,n- 1);
}

void print_arr( int v[], int n){
     int i;
     for(i= 0;i<n;i++)
        printf( " %4d ",v[i]);
    printf( " \n ");
}
int main(){
     int i;
     for(i= 0;i< 10;i++){
         int arr[ 20],j,b[ 20];
         for(j= 0;j< 20;j++)
        {
             int val=rand()% 1000;
            arr[j]=val;
            b[j]=val;
        }
        printf( " before: ");
        print_arr(b, 20);
        Qsort(arr, 20);
        printf( " after : ");
        print_arr(arr, 20);
    }
}

测试结果如下:

swap宏

第5章 指针与数组

int strend( char *s, char*t){
     char *bs=s;
     char *bt=t;
     while(*s++);
     while(*t++);
     while(*--s==*--t){
         if(t==bt||s==st)
             break;
    }
     if(*s==*t&&t==bt&&*s!= ' \0 ')
         return  1;
     else                              
         return  0;
}


void strncpy( char* s, char *t, int n){
     while(*t&&n--> 0)
        *s++=*t++;
     while(n--> 0)
        *s++= ' \0 ';
}
void strncat( char *s, char *t, int n){
    strncpy(s+strlen(s),t,n);
}
int strncmp( char* s, char* t, int n){
     for(;*s==*t;s++,t++)
         if(*s== ' \0 '||--n<= 0)
             return  0;
     return *s-*t;
}

UNIX系统中sort程序的一个简单版本,实现对输入文本的排序。

#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#define MAXLINES 5000
char *lineptr[MAXLINES];

#define MAXLEN 1000

int getline_( char line[], int lim){
     int i,c;
    i= 0;
     while(i<lim- 1&&((c=getchar())!=EOF)&&c!= ' \n ')
        line[i++]=c;
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        line[i++]=c;
    line[i]= ' \0 ';
     return i;
}
char* alloc( int len){
     char *p=( char*)malloc(len* sizeof( char));
     return p;
}
int readlines( char* lineptr[], int maxlines){
     int len,nlines;
     char *p,line[MAXLEN];
    nlines= 0;
     while((len=getline_(line,MAXLEN))> 0)
         if(nlines>=maxlines||(p=alloc(len))==NULL)
             return - 1;
     else{
        line[len- 1]= ' \0 ';
        strcpy(p,line);
        lineptr[nlines++]=p;
    }
     return nlines;
}
void writelines( char *lineptr[], int nlines){
     int i;
     for(i= 0;i<nlines;i++)
        printf( " %s\n ",lineptr[i]);
}
void swap( char **x, char **y){
     char*tmp;
    tmp=*x;
    *x=*y;
    *y=tmp;
}
void qsort_( char *v[], int left, int right){
     int i,last;
     if(left>=right)
         return ;
    swap(v+left,v+(left+right)/ 2);
    last=left;
     for(i=left+ 1;i<=right;i++)
         if(strcmp(v[i],v[left])< 0)
        {
            last++;
            swap(v+last,v+i);
        }
    swap(v+left,v+last);
    qsort_(v,left,last- 1);
    qsort_(v,last+ 1,right);
}
int main(){
     int nlines;
     int i;
     if((nlines=readlines(lineptr,MAXLINES))> 0){
        qsort_(lineptr, 0,nlines- 1);
        writelines(lineptr,nlines);
         for(i= 0;i<nlines;i++)
            free(lineptr[i]);

return  0;
    }
     else{
        printf( " error: input too big to sort\n ");
         return  1;
    }
}

根据日期计算是一年的第几天:

static  int daytab[][ 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}};
int day_of_year( int year, int month, int day){
     int i,leap;
    leap=year% 4== 0&&year% 100!= 0||year% 400== 0;
     if(month< 1||month> 12)
         return - 1;
     if(day< 1||day>daytab[leap][month])
         return - 1;
     for(i= 1;i<month;i++)
        day+=daytab[leap][i];
     return day;
}
void month_day( int year, int yearday, int *pmonth, int *pday){
     int i,leap;
     if(year< 1){
        *pmonth=- 1;
        *pday=- 1;
         return ;
    }
    leap=year% 4== 0&&year% 100!= 0||year% 400== 0;
     for(i= 1;i<= 12&&yearday>daytab[leap][i];i++)
        yearday-=daytab[leap][i];
     if(i> 12&&yearday>daytab[leap][ 12]){                         
        *pmonth=- 1;
        *pday=- 1;
    }
     else{
        *pmonth=i;
        *pday=yearday;
    }
}   

习题5-13

#include <stdio.h>
#include <stdlib.h>
#include < string.h>
#define DEFLINES 10
#define MAXLINES 10
#define MAXLEN 100
int getline_( char line[], int lim){
     int i,c;
    i= 0;
     while(i<lim- 1&&((c=getchar())!=EOF)&&c!= ' \n ')
        line[i++]=c;
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        line[i++]=c;
    line[i]= ' \0 ';
     return i;
}
void error( char *s){
    printf( " %s\n ",s);
    exit( 1);
}
int main( int argc, char* argv[]){
     char *p,*buf,*bufend;
     char line[MAXLEN];
     char *lineptr[MAXLINES];
     int first,i,last,len,n,nlines;
     if(argc== 1)
        n=DEFLINES;
     else  if(argc== 2&&(*++argv)[ 0]== ' - ')
        n=atoi(argv[ 0]+ 1);
     if(n< 1||n>MAXLINES)
        n=MAXLINES;
     for(i= 0;i<MAXLINES;i++)
        lineptr[i]=NULL;
     if((p=buf=malloc(MAXLINES*MAXLEN))==NULL)
        error( " tail:cannot allocate buf ");
    bufend=buf+MAXLINES*MAXLEN;
    last= 0;
    nlines= 0;
     while((len=getline_(line,MAXLEN))> 0){
         if(p+len+ 1>=bufend)
            p=buf;
        lineptr[last]=p;
        strcpy(lineptr[last],line);
         if(++last>=MAXLINES)
            last= 0;
        p+=len+ 1;
        nlines++;
    }
     if(n>nlines)
        n=nlines;
    first=last-n;
     if(first< 0)
        first+=MAXLINES;
     for(i=first;n--> 0;i=(i+ 1)%MAXLINES)
        printf( " %s ",lineptr[i]);
    free(buf);

return  0;
}

#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#include <ctype.h>

#define NUMERIC 1
#define DECR 2
#define FOLD 4
#define DIR 8
// #define LINES 100
#define MAXLINES 100

#define MAXLEN 1000
char option= 0;
int pos1= 0;
int pos2= 0;

int getline_( char line[], int lim){
     int i,c;
    i= 0;
     while(i<lim- 1&&((c=getchar())!=EOF)&&c!= ' \n ')
        line[i++]=c;
     if(c==EOF&&i== 0)
         return - 1;
     if(c== ' \n ')
        line[i++]=c;
    line[i]= ' \0 ';
     return i;
}
void error( char *s){
    printf( " %s\n ",s);
    exit( 1);
}
char* alloc( int len){
     char *p=( char*)malloc(len* sizeof( char));
     return p;
}
int readlines( char* lineptr[], int maxlines){
     int len,nlines;
     char *p,line[MAXLEN];
    nlines= 0;
     while((len=getline_(line,MAXLEN))> 0)
         if(nlines>=maxlines||(p=alloc(len))==NULL)
             return - 1;
     else{
        line[len- 1]= ' \0 ';
        strcpy(p,line);
        lineptr[nlines++]=p;
    }
     return nlines;
}
void writelines( char *lineptr[], int nlines, int decr){
     int i;
     if(decr)
         for(i=nlines- 1;i>= 0;i--)
            printf( " %s\n ",lineptr[i]);
     else
         for(i= 0;i<nlines;i++)
            printf( " %s\n ",lineptr[i]);
}
void swap( void**x, void**y){
     void*tmp;
    tmp=*x;
    *x=*y;
    *y=tmp;
}
void qsort_( void*v[], int left, int right,
         int(*comp)( void*, void*)){
     int i,last;
     if(left>=right)
         return ;
    swap(v+left,v+(left+right)/ 2);
    last=left;
     for(i=left+ 1;i<=right;i++)
         if(strcmp(v[i],v[left])< 0)
        {
            last++;
            swap(v+last,v+i);
        }
    swap(v+left,v+last);
    qsort_(v,left,last- 1,comp);
    qsort_(v,last+ 1,right,comp);
}
void readargs( int argc, char*argv[]){
     int c;
     while(--argc> 0&&(c=(*++argv)[ 0])== ' - '||c== ' + '){
         if(c== ' - '&&!isdigit(*(argv[ 0]+ 1)))
             while(c=*++argv[ 0])
                 switch(c){
                     case  ' d ':
                        option|=DIR;
                         break;
                     case  ' f ':
                        option|=FOLD;
                         break;
                     case  ' n ':
                        option|=NUMERIC;
                         break;
                     case  ' r ':
                        option|=DECR;
                         break;
                     default:
                        printf( " sort: illegal option %c\n ",c);
                        error( " usage: sort -dfnr [+pos1] [-pos2] ");
                         break;
                }
         else  if(c== ' - ')
            pos2=atoi(argv[ 0]+ 1);
         else  if((pos1=atoi(argv[ 0]+ 1))< 0)
            error( " usage: sort -dfnr [+pos1] [-pos2] ");
    }
     if(argc||pos1>pos2)
            error( " usage: sort -dfnr [+pos1] [-pos2] ");
}
#define MAXSTR 100
void substr( char *s, char *str){
     int i,j,len;
    len=strlen(s);
     if(pos2> 0&&len>pos2)
        len=pos2;
     else  if(pos2> 0&&len<pos2)
        error( " substr:string too short ");
     for(j= 0,i=pos1;i<len;i++,j++)
        str[j]=s[i];
    str[j]= ' \0 ';
}
#define ABS(x) ((x)<0?-(x):(x))

double atof_( char s[]){
     double val,power;
     int i,sign;
     for(i= 0;isspace(s[i]);i++);
    sign=(s[i]== ' - ')?- 1: 1;
     if(s[i]== ' + '||s[i]== ' - ')
        i++;
     for(val= 0.0;isdigit(s[i]);i++)
        val= 10.0*val+(s[i]- ' 0 ');
     if(s[i]== ' . ')
        i++;
     for(power= 1.0;isdigit(s[i]);i++){
        val= 10.0*val+(s[i]- ' 0 ');
        power*= 10;
    }
    val= sign*val/power;
     if(s[i]== ' e '||s[i]== ' E '){
         int exp;
        sign=(s[++i]== ' - ')?- 1: 1;
         if(s[i]== ' + '||s[i]== ' - ')
            i++;
         for(exp= 0;isdigit(s[i]);i++)
            exp= 10*exp+(s[i]- ' 0 ');
         if(sign)
             while(exp--> 0)
                val*= 10;
         else
             while(exp--> 0)
                val/= 10;
    }
     return val;
}
int numcmp( char *s1, char *s2){
     double v1,v2;
     char str[MAXSTR];
    substr(s1,str);
    v1=atof_(str);
    substr(s2,str);
    v2=atof_(str);
     if(v1<v2)
         return - 1;
     else  if(v1>v2)
         return  1;
     else 
         return  0;
}
// #define FOLD 4
// #define DIR 8
int charcmp( char *s, char *t){
     char a,b;
     int i,j,endpos;
     int fold=(option&FOLD)? 1: 0;
     int dir=(option&DIR)? 1: 0;
    i=j=pos1;
     if(pos2> 0)
        endpos=pos2;
     else  if((endpos-strlen(s))>strlen(t))
        endpos=strlen(t);
     do{
         if(dir){
             while(i<endpos&&!isalnum(s[i])&&
                    s[i]!= '   '&&s[i]!= ' \0 ')
                i++;
             while(j<endpos&&!isalnum(t[j])&&
                    t[j]!= '   '&&t[j]!= ' \0 ')
                j++;
        }
         if(i<endpos&&j<endpos){
            a=fold?tolower(s[i]):s[i];
            i++;
            b=fold?tolower(t[j]):t[j];
            j++;
             if(a==b&&a== ' \0 ')
                 return  0;
        }
    }
     while(a==b&&i<endpos&&j<endpos);
     return a-b;
}
int main( int argc, char*argv[]){
     char *lineptr[MAXLINES];
     int nlines;
     int i;
    readargs(argc,argv);
     if((nlines=readlines(lineptr,MAXLINES))> 0){
         if(option&NUMERIC)
            qsort_(( void**)lineptr, 0,nlines- 1,
                    ( int(*)( void*, void*))numcmp);
         else
            qsort_(( void**)lineptr, 0,nlines- 1,
                    ( int(*)( void*, void*))charcmp);
        writelines(lineptr,nlines,option&DECR);
         for(i= 0;i<nlines;i++)
            free(lineptr[i]);

return  0;
    }
     else{
        printf( " error: input too big to sort\n ");
         return  1;
    }
}

dcl一个比较不错的程序:将声明转化为文字描述或将文字描述转化为声明

#include <stdio.h>
#include < string.h>
#include <ctype.h>
#define MAXTOKEN 100

enum{NAME,PARENS,BRACKETS};

int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char  out[ 1000];

#define BUFSIZE 10
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}

int gettoken(){
     char *p=token;
     int c;
     while((c=getch())== '   '||c== ' \t ')
        ;
     if(c== ' ( '){
         if((c=getch())== ' ) '){
            strcpy(token, " () ");
             return tokentype=PARENS;
        }
         else{
            ungetch(c);
             return tokentype= ' ( ';
        }
    }
     else  if(c== ' [ '){
         for(*p++=c;(*p++=getch())!= ' ] ';)
            ;
        *p= ' \0 ';
         return tokentype=BRACKETS;
    }
     else  if(isalpha(c)){
         for(*p++=c;isalnum(c=getch());)
            *p++=c;
        *p= ' \0 ';
        ungetch(c);
         return tokentype=NAME;
    }
     else
         return tokentype=c;
}

void dcl( void);
void dirdcl( void){
     int type;
     if(tokentype== ' ( '){
        dcl();
         if(tokentype!= ' ) ')
            printf( " error:missing )\n ");
    }
     else  if(tokentype==NAME)
        strcpy(name,token);
     else
        printf( " error:expected name or (dcl)\n ");
     while((type=gettoken())==PARENS||type==BRACKETS)
         if(type==PARENS)
            strcat( out, "  function returning ");
     else{
        strcat( out,  "  array ");
        strcat( out,token);
        strcat( out, "  of ");
    }
}
void dcl( void){
     int ns;
     for(ns= 0;gettoken()== ' * ';)
        ns++;
    dirdcl();
     while(ns--> 0)
        strcat( out, "  pointer to ");
}

int main(){
     while(gettoken()!=EOF){
        strcpy(datatype,token);
         out[ 0]= ' \0 ';
        dcl();
         if(tokentype!= ' \n ')
            printf( " syntax error\n ");
        printf( " %s: %s %s\n ",name, out,datatype);
    }
     return  0;
}

int main(){
     int type;
     char temp[MAXTOKEN];
     while(gettoken()!=EOF){
        strcpy( out,token);
         while((type=gettoken())!= ' \n ')
             if(type==PARENS||type==BRACKETS)
                strcat( out,token);
         else  if(type== ' * '){
            sprintf(temp, " (*%s) ", out);
            strcpy( out,temp);
        }
         else  if(type==NAME){
            sprintf(temp, " %s %s ",token, out);
            strcpy( out,temp);
        }
         else {
            printf( " invalid input at %s\n ",token);
        }
    }

printf( " %s\n ", out);                             
     return  0;
}

#include <stdio.h>
#include < string.h>
#include <ctype.h>
#define MAXTOKEN 100

enum{NAME,PARENS,BRACKETS};
enum{NO,YES};

int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char  out[ 1000];
int prevtoken=NO;

#define BUFSIZE 10
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}
void errmsg( char *msg){
    printf( " %s ",msg);
    prevtoken=YES;
}

int gettoken(){
     char *p=token;
     int c;
     if(prevtoken==YES){
        prevtoken=NO;
         return tokentype;
    }
     while((c=getch())== '   '||c== ' \t ')
        ;
     if(c== ' ( '){
         if((c=getch())== ' ) '){
            strcpy(token, " () ");
             return tokentype=PARENS;
        }
         else{
            ungetch(c);
             return tokentype= ' ( ';
        }
    }
     else  if(c== ' [ '){
         for(*p++=c;(*p++=getch())!= ' ] ';)
            ;
        *p= ' \0 ';
         return tokentype=BRACKETS;
    }
     else  if(isalpha(c)){
         for(*p++=c;isalnum(c=getch());)
            *p++=c;
        *p= ' \0 ';
        ungetch(c);
         return tokentype=NAME;
    }
     else
         return tokentype=c;
}
void dcl( void);
void dirdcl( void){
     int type;
     if(tokentype== ' ( '){
        dcl();
         if(tokentype!= ' ) ')
            printf( " error:missing )\n ");
    }
     else  if(tokentype==NAME)
        strcpy(name,token);
     else
        errmsg( " error:expected name or (dcl)\n ");
     while((type=gettoken())==PARENS||type==BRACKETS)
         if(type==PARENS)
            strcat( out, "  function returning ");
     else{
        strcat( out,  "  array ");
        strcat( out,token);
        strcat( out, "  of ");
    }
}
void dcl( void){
     int ns;
     for(ns= 0;gettoken()== ' * ';)
        ns++;
    dirdcl();
     while(ns--> 0)
        strcat( out, "  pointer to ");
}

int main(){
     while(gettoken()!=EOF){
        strcpy(datatype,token);
         out[ 0]= ' \0 ';
        dcl();
         if(tokentype!= ' \n ')
            printf( " syntax error\n ");
        printf( " %s: %s %s\n ",name, out,datatype);
    }
     return  0;
}

int nexttoken(){
     int type;
    type=gettoken();
    prevtoken=YES;
     return type;
}
int main(){
     int type;
     char temp[MAXTOKEN];
     while(gettoken()!=EOF){
        strcpy( out,token);
         while((type=gettoken())!= ' \n ')
             if(type==PARENS||type==BRACKETS)
                strcat( out,token);
         else  if(type== ' * '){
             if((type=nexttoken())==PARENS||             
                    type==BRACKETS)
            sprintf(temp, " (*%s) ", out);
             else
                sprintf(temp, " *%s ", out);
            strcpy( out,temp);
        }
         else  if(type==NAME){
            sprintf(temp, " %s %s ",token, out);
            strcpy( out,temp);
        }
         else {
            printf( " invalid input at %s\n ",token);
        }
    }

printf( " %s\n ", out);
     return  0;
}

#include <stdio.h>
#include < string.h>
#include <ctype.h>
#define MAXTOKEN 100

enum{NAME,PARENS,BRACKETS};
enum{NO,YES};

int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char  out[ 1000];
int prevtoken=NO;

#define BUFSIZE 10
char buf[BUFSIZE];
int bufp= 0;
int getch( void){
     return bufp> 0?buf[--bufp]:getchar();
}
void ungetch( int c){
     if(bufp>=BUFSIZE)
        printf( " ungetch: too many characters\n ");
     else
        buf[bufp++]=c;
}
void errmsg( char *msg){
    printf( " %s ",msg);
    prevtoken=YES;
}

int gettoken(){
     char *p=token;
     int c;
     if(prevtoken==YES){
        prevtoken=NO;
         return tokentype;
    }
     while((c=getch())== '   '||c== ' \t ')
        ;
     if(c== ' ( '){
         if((c=getch())== ' ) '){
            strcpy(token, " () ");
             return tokentype=PARENS;
        }
         else{
            ungetch(c);
             return tokentype= ' ( ';
        }
    }
     else  if(c== ' [ '){
         for(*p++=c;(*p++=getch())!= ' ] ';)
            ;
        *p= ' \0 ';
         return tokentype=BRACKETS;
    }
     else  if(isalpha(c)){
         for(*p++=c;isalnum(c=getch());)
            *p++=c;
        *p= ' \0 ';
        ungetch(c);
         return tokentype=NAME;
    }
     else
         return tokentype=c;
}

int compare( char **s, char **t){
     return strcmp(*s,*t);
}

int typespec( void){
     static  char *types[]={
         " char ", " int ", " void "
    };
     char *pt=token;
     if(bsearch(&pt,types, sizeof(types)/ sizeof( char*), sizeof( char*),compare)==NULL)
         return NO;
     else
         return YES;
}
int typequal( void){
     static  char *typeq[]={
         " const ", " volatile "
    };
     char *pt=token;
     if(bsearch(&pt,typeq, sizeof(typeq)/ sizeof( char*), sizeof( char*),compare)==NULL)
         return NO;
     else
         return YES;
}
void dcl( void);
void dclspec( void){
     char temp[MAXTOKEN];
    temp[ 0]= ' \0 ';
    gettoken();
     do{
         if(tokentype!=NAME){
            prevtoken=YES;
            dcl();
        }
         else  if(typespec()==YES){
            strcat(temp, "   ");
            strcat(temp,token);
            gettoken();
        }
         else  if(typequal()==YES){
            strcat(temp, "   ");
            strcat(temp,token);
            gettoken();
        }
         else
            errmsg( " unknown type in parameter list\n ");
    }
     while(tokentype!= ' , '&&tokentype!= ' ) ');
    strcat( out,temp);
     if(tokentype== ' , ')
        strcat( out, " , ");
}
void parmdcl( void){
     do{
        dclspec();
    } while(tokentype== ' , ');
     if(tokentype!= ' ) ')
        errmsg( " missing ) in parameter declaration\n ");
}
void dirdcl( void){
     int type;
     if(tokentype== ' ( '){
        dcl();
         if(tokentype!= ' ) ')
            printf( " error:missing )\n ");
    }
     else  if(tokentype==NAME) {
         if(name[ 0]== ' \0 ')
            strcpy(name,token);
    }
     else
        prevtoken=YES;
     while((type=gettoken())==PARENS||type==BRACKETS||type== ' ( ')
         if(type==PARENS)
            strcat( out, "  function returning ");
     else  if(type== ' ( '){
        strcat( out, "  function expecting ");
        parmdcl();
        strcat( out, "  and returning ");
    }
         else{
        strcat( out,  "  array ");
        strcat( out,token);
        strcat( out, "  of ");
    }
}
void dcl( void){
     int ns;
     for(ns= 0;gettoken()== ' * ';)
        ns++;
    dirdcl();
     while(ns--> 0)
        strcat( out, "  pointer to ");
}

int main(){
     while(gettoken()!=EOF){
        strcpy(datatype,token);
         out[ 0]= ' \0 ';
        dcl();
         if(tokentype!= ' \n ')
            printf( " syntax error\n ");
        printf( " %s: %s %s\n ",name, out,datatype);
    }
     return  0;
}

这个网站很不错的:http://cdecl.org/

第6章 结构体

统计关键字出现的次数

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include < string.h>

#define MAXWORD 1000
struct key {
     char *word;
     int count;
}
keytab[]={
     " auto ", 0,
     " break ", 0,
     " case ", 0,
     " char ", 0,
     " const ", 0,
     " continue ", 0,
     " default ", 0,
     " do ", 0,
     " double ", 0,
     " else ", 0,
     " enum ", 0,
     " extern ", 0,
     " float ", 0,
     " for ", 0,
     " goto ", 0,
     " if ", 0,
     " int ", 0,
     " long ", 0,
     " register ", 0,
     " return ", 0,
     " short ", 0,
     " signed ", 0,
     " sizeof ", 0,
     " static ", 0,
     " struct ", 0,
     " switch ", 0,
     " typedef ", 0,
     " union ", 0,
     " unsigned ", 0,
     " void ", 0,
     " volatile ", 0,
     " while ", 0,
};
#define NKEYS (sizeof keytab/sizeof(keytab[0]))
#define BUFSIZE 10                                 
char buf[BUFSIZE];                                 
int bufp= 0;                                        
int getch( void){                                   
     return bufp> 0?buf[--bufp]:getchar();           
}                                                  
void ungetch( int c){                               
     if(bufp>=BUFSIZE)                              
        printf( " ungetch: too many characters\n ");  
     else                                           
        buf[bufp++]=c;                             
}                                                  
int binsearch( char *word, struct key tab[], int n){
     int cond;
     int low,high,mid;
    low= 0;
    high=n- 1;
     while(low<=high){
        mid=(low+high)/ 2;
         if((cond=strcmp(word,tab[mid].word))< 0)
            high=mid- 1;
         else  if(cond> 0)
            low=mid+ 1;
         else
             return mid;
    }
     return - 1;
}
int comment( void){
     int c;
     while((c=getch())!=EOF)
         if(c== ' * ')
             if((c=getch())== ' / ')
                 break;
             else
                ungetch(c);
     return c;
}
int getword( char *word, int lim){
     char *w=word;
     int c,d;
     while(isspace(c=getch()))
        ;
     if(c!=EOF)
        *w++=c;
     if(isalpha(c)||c== ' - '||c== ' # '){
         for(;--lim> 0;w++)
             if(!isalnum(*w=getch())&&*w!= ' - '){
                ungetch(*w);
                 break;
            }
    }
     else  if(c== ' \' '||c== ' " '){
         for(;--lim> 0;w++)
             if((*w=getch())== ' \\ ')
                *++w=getch();
         else  if(*w==c){
            w++;
             break;
        }
         else  if(*w==EOF)
             break;
            
    }
     else  if(c== ' / ')
         if((d=getch())== ' * ')
            c=comment();
     else
        ungetch(d);
    *w= ' \0 ';
     return c;
}
int main(){
     int n;
     char word[MAXWORD];
     while(getword(word,MAXWORD)!=EOF)
         if(isalpha(word[ 0]))
             if((n=binsearch(word,keytab,NKEYS))>= 0)
                keytab[n].count++;
     for(n= 0;n<NKEYS;n++)
         if(keytab[n].count> 0)
            printf( " %4d %s\n ",
                    keytab[n].count,keytab[n].word);
     return  0;
}

#include <stdio.h>
#include <ctype.h>
#include < string.h>
#include <stdlib.h>
#define BUFSIZE 10                                 
char buf[BUFSIZE];                                 
int bufp= 0;                                        
int getch( void){                                   
     return bufp> 0?buf[--bufp]:getchar();           
}                                                  
void ungetch( int c){                               
     if(bufp>=BUFSIZE)                              
        printf( " ungetch: too many characters\n ");  
     else                                           
        buf[bufp++]=c;                             
}                                                  
int comment( void){
     int c;
     while((c=getch())!=EOF)
         if(c== ' * ')
             if((c=getch())== ' / ')
                 break;
             else
                ungetch(c);
     return c;
}
int getword( char *word, int lim){
     char *w=word;
     int c,d;
     while(isspace(c=getch()))
        ;
     if(c!=EOF)
        *w++=c;
     if(isalpha(c)||c== ' - '||c== ' # '){
         for(;--lim> 0;w++)
             if(!isalnum(*w=getch())&&*w!= ' - '){
                ungetch(*w);
                 break;
            }
    }
     else  if(c== ' \' '||c== ' " '){
         for(;--lim> 0;w++)
             if((*w=getch())== ' \\ ')
                *++w=getch();
         else  if(*w==c){
            w++;
             break;
        }
         else  if(*w==EOF)
             break;
            
    }
     else  if(c== ' / ')
         if((d=getch())== ' * ')
            c=comment();
     else
        ungetch(d);
    *w= ' \0 ';
     return c;
}
struct tnode{
     char *word;
     int match;
     struct tnode *left;
     struct tnode *right;
};
#define MAXWORD 100
#define YES 1
#define NO 0

int compare( char *s, struct tnode *p, int num, int *found){
     int i;
     char *t=p->word;
     for(i= 0;*s==*t;i++,s++,t++)
         if(*s== ' \0 ')
             return  0;
     if(i>=num){
        *found=YES;
        p->match=YES;
    }
     return *s-*t;
}
struct tnode* talloc( void){
     return ( struct tnode*)malloc( sizeof( struct tnode));
}
char *strdup_( char *s){
     char *p;
    p=( char*)malloc(strlen(s)+ 1);
     if(p!=NULL)
        strcpy(p,s);
     return p;
}

struct tnode* addtreex( struct tnode*p, char *w, int num, int *found){
     int cond;
     if(p==NULL){
        p=talloc();
        p->word=strdup_(w);
        p->match=*found;
        p->left=p->right=NULL;
    }
     else  if((cond=compare(w,p,num,found))< 0)
        p->left=addtreex(p->left,w,num,found);
     else  if(cond> 0)
        p->right=addtreex(p->right,w,num,found);
     return p;
}
void treeprint( struct tnode* p){
     if(p!=NULL){
        treeprint(p->left);
         if(p->match)
            printf( " %s]n ",p->word);
        treeprint(p->right);
    }
}
void freetree( struct tnode*p){
     if(p!=NULL){
        freetree(p->left);
        freetree(p->right);
        free(p->word);
    }
}

int main( int argc, char *argv[]){
     struct tnode *root;
     char word[MAXWORD];
     int found=NO;
     int num;
    num=(--argc&&(*++argv)[ 0]== ' - ')?atoi(argv[ 0]+ 1): 6;
    root=NULL;
     while(getword(word,MAXWORD)!=EOF){
         if(isalpha(word[ 0])&&strlen(word)>=num)
            root=addtreex(root,word,num,&found);
        found=NO;
    }
    treeprint(root);
    freetree(root);
     return  0;
}

#include <stdio.h>
#include <ctype.h>
#include < string.h>
#include <stdlib.h>
#define BUFSIZE 10                                 
char buf[BUFSIZE];                                 
int bufp= 0;                                        
int getch( void){                                   
     return bufp> 0?buf[--bufp]:getchar();           
}                                                  
void ungetch( int c){                               
     if(bufp>=BUFSIZE)                              
        printf( " ungetch: too many characters\n ");  
     else                                           
        buf[bufp++]=c;                             
}                                                  
int comment( void){
     int c;
     while((c=getch())!=EOF)
         if(c== ' * ')
             if((c=getch())== ' / ')
                 break;
             else
                ungetch(c);
     return c;
}
int getword( char *word, int lim){
     char *w=word;
     int c,d;
     while(isspace(c=getch()))
        ;
     if(c!=EOF)
        *w++=c;
     if(isalpha(c)||c== ' - '||c== ' # '){
         for(;--lim> 0;w++)
             if(!isalnum(*w=getch())&&*w!= ' - '){
                ungetch(*w);
                 break;
            }
    }
     else  if(c== ' \' '||c== ' " '){
         for(;--lim> 0;w++)
             if((*w=getch())== ' \\ ')
                *++w=getch();
         else  if(*w==c){
            w++;
             break;
        }
         else  if(*w==EOF)
             break;
            
    }
     else  if(c== ' / ')
         if((d=getch())== ' * ')
            c=comment();
     else
        ungetch(d);
    *w= ' \0 ';
     return c;
}
struct linklist{
     int lnum;
     struct linklist *ptr;
};
struct tnode{
     char *word;
     struct linklist *lines;
     struct tnode *left;
     struct tnode *right;
};
#define MAXWORD 100
#define YES 1
#define NO 0

struct tnode* talloc( void){
     return ( struct tnode*)malloc( sizeof( struct tnode));
}
struct linklist *lalloc( void){
     return ( struct linklist*)malloc( sizeof( struct linklist));
}
char *strdup_( char *s){
     char *p;
    p=( char*)malloc(strlen(s)+ 1);
     if(p!=NULL)
        strcpy(p,s);
     return p;
}
void addln( struct tnode *p, int linenum){
     struct linklist *temp;
    temp=p->lines;
     while(temp->ptr!=NULL&&temp->lnum!=linenum)
        temp=temp->ptr;
     if(temp->lnum==linenum){
        temp->ptr=lalloc();
        temp->ptr->lnum=linenum;
        temp->ptr->ptr=NULL;
    }
}

struct tnode* addtreex( struct tnode*p, char *w, int linenum){
     int cond;
     if(p==NULL){
        p=talloc();
        p->word=strdup_(w);
        p->lines=lalloc();
        p->lines->lnum=linenum;
        p->lines->ptr=NULL;
        p->left=p->right=NULL;
    }
     else  if((cond=strcmp(w,p->word))< 0)
        p->left=addtreex(p->left,w,linenum);
     else  if(cond> 0)
        p->right=addtreex(p->right,w,linenum);
     else
        addln(p,linenum);
     return p;
}
void treeprint( struct tnode* p){
     struct linklist *temp;
     if(p!=NULL){
        treeprint(p->left);
        printf( " %10s:  ",p->word);
         for(temp=p->lines;temp!=NULL;temp=temp->ptr)
            printf( " %4d  ",temp->lnum);
        printf( " \n ");
        treeprint(p->right);
    }
}
void freetree( struct tnode*p){
     if(p!=NULL){
        freetree(p->left);
        freetree(p->right);
        free(p->word);
        free(p->lines);
    }
}
int noiseword( char *w){
     static  char *nw[]={
         " a ", " an ", " and ", " are ", " in ", " is ", " of ", " or ", " that ", " the ", " this ", " to "
    };
     int cond,mid;
     int low= 0;
     int high= sizeof(nw)/ sizeof( char*)- 1;
     while(low<=high){
        mid=(low+high)/ 2;
         if((cond=strcmp(w,nw[mid]))< 0)
            high=mid- 1;
         else  if(cond> 0)
            low=mid+ 1;
         else 
             return mid;
    }
     return - 1;
}

int main( int argc, char *argv[]){
     struct tnode *root;
     char word[MAXWORD];
     int linenum= 1;
    root=NULL;
     while(getword(word,MAXWORD)!=EOF){
         if(isalpha(word[ 0])&&noiseword(word)==- 1)
            root=addtreex(root,word,linenum);
         else  if(word[ 0]== ' \n ')
            linenum++;
    }
    treeprint(root);
    freetree(root);
     return  0;
}

表查找程序核心代码:

#include <stdio.h>
#include < string.h>
#include <stdlib.h>
struct nlist{
     struct nlist *next;
     char *name;
     char *defn;
};
#define HASHSIZE 101
static  struct nlist *hashtab[HASHSIZE];
unsigned hash( char *s)
{
    unsigned hashval;
     for(hashval= 0;*s!= ' \0 ';s++)
        hashval=*s+ 32*hashval;
     return hashval%HASHSIZE;
}
struct nlist *lookup( char *s){
     struct nlist *np;
     for(np=hashtab[hash(s)];np!=NULL;np=np->next)
         if(strcmp(s,np->name)== 0)
             return np;
     return NULL;
}
struct nlist *install( char *name, char*defn){
     struct nlist *np;
    unsigned hashval;
     if((np=lookup(name))==NULL){
        np=( struct nlist *)malloc( sizeof( struct nlist));
         if(np==NULL||(np->name=strdup(name))==NULL)
             return NULL;
        hashval=hash(name);
        np->next=hashtab[hashval];
        hashtab[hashval]=np;
    }
     else
        free(( void*)np->defn);
     if((np->defn=strdup(defn))==NULL)
         return NULL;
     return np;
}
void undef( char*s){
     int h;
     struct nlist *prev,*np;
    prev=NULL;
    h=hash(s);
     for(np=hashtab[h];np!=NULL;np=np->next){
         if(strcmp(s,np->name)== 0)
             break;
        prev=np;
    }
     if(np!=NULL){
         if(prev==NULL)
            hashtab[h]=np->next;
         else
            prev->next=np->next;
        free(np->name);
        free(np->defn);
        free(np);
    }
}

#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFSIZE 10                                 
char buf[BUFSIZE];                                 
int bufp= 0;                                        
int getch( void){                                   
     return bufp> 0?buf[--bufp]:getchar();           
}                                                  
void ungetch( int c){                               
     if(bufp>=BUFSIZE)                              
        printf( " ungetch: too many characters\n ");  
     else                                           
        buf[bufp++]=c;                             
}                                                  
void ungets( char *s){
     int len=strlen(s);
     while(len> 0)
        ungetch(s[--len]);
}
char *strdup_( char *s){
     char *p;
    p=( char*)malloc(strlen(s)+ 1);
     if(p!=NULL)
        strcpy(p,s);
     return p;
}

int comment( void){
     int c;
     while((c=getch())!=EOF)
         if(c== ' * ')
             if((c=getch())== ' / ')
                 break;
             else
                ungetch(c);
     return c;
}
int getword( char *word, int lim){
     char *w=word;
     int c,d;
     while(isspace(c=getch()))
        ;
     if(c!=EOF)
        *w++=c;
     if(isalpha(c)||c== ' - '||c== ' # '){
         for(;--lim> 0;w++)
             if(!isalnum(*w=getch())&&*w!= ' - '){
                ungetch(*w);
                 break;
            }
    }
     else  if(c== ' \' '||c== ' " '){
         for(;--lim> 0;w++)
             if((*w=getch())== ' \\ ')
                *++w=getch();
         else  if(*w==c){
            w++;
             break;
        }
         else  if(*w==EOF)
             break;
            
    }
     else  if(c== ' / ')
         if((d=getch())== ' * ')
            c=comment();
     else
        ungetch(d);
    *w= ' \0 ';
     return c;
}
struct nlist{
     struct nlist *next;
     char *name;
     char *defn;
};
#define HASHSIZE 101
static  struct nlist *hashtab[HASHSIZE];
unsigned hash( char *s)
{
    unsigned hashval;
     for(hashval= 0;*s!= ' \0 ';s++)
        hashval=*s+ 32*hashval;
     return hashval%HASHSIZE;
}
struct nlist *lookup( char *s){
     struct nlist *np;
     for(np=hashtab[hash(s)];np!=NULL;np=np->next)
         if(strcmp(s,np->name)== 0)
             return np;
     return NULL;
}
struct nlist *install( char *name, char*defn){
     struct nlist *np;
    unsigned hashval;
     if((np=lookup(name))==NULL){
        np=( struct nlist *)malloc( sizeof( struct nlist));
         if(np==NULL||(np->name=strdup_(name))==NULL)
             return NULL;
        hashval=hash(name);
        np->next=hashtab[hashval];
        hashtab[hashval]=np;
    }
     else
        free(( void*)np->defn);
     if((np->defn=strdup_(defn))==NULL)
         return NULL;
     return np;
}
void undef( char*s){
     int h;
     struct nlist *prev,*np;
    prev=NULL;
    h=hash(s);
     for(np=hashtab[h];np!=NULL;np=np->next){
         if(strcmp(s,np->name)== 0)
             break;
        prev=np;
    }
     if(np!=NULL){
         if(prev==NULL)
            hashtab[h]=np->next;
         else
            prev->next=np->next;
        free(np->name);
        free(np->defn);
        free(np);
    }
}

void error( int c, char *s){
    printf( " error:%s\n ",s);
     while(c!=EOF&&c!= ' \n ')
        c=getch();
}
void skipblanks(){
     int c;
     while((c=getch())== '   '||c== ' \t ')
        ;
    ungetch(c);
}
#define MAXWORD 100
void getdef(){
     int c,i;
     char def[MAXWORD],dir[MAXWORD],name[MAXWORD];
    skipblanks();
     if(!isalpha(getword(dir,MAXWORD)))
        error(dir[ 0], " getdef:expecting a directive after # ");
     else  if(strcmp(dir, " define ")== 0){
        skipblanks();
         if(!isalpha(getword(name,MAXWORD)))
            error(name[ 0], " getdef:non-alpha -name expected ");
         else{
            skipblanks();
             for(i= 0;i<MAXWORD- 1;i++)
                 if((def[i]=getch())==EOF||
                        def[i]== ' \n ')
                     break;
            def[i]= ' \0 ';
             if(i<= 0)
                error( ' \n ', " getdef:incomplete define ");
             else
                install(name,def);
        }
    }
     else  if(strcmp(dir, " undef ")== 0){
        skipblanks();
         if(!isalpha(getword(name,MAXWORD)))
            error(name[ 0], " getdef:non-alpha in undef ");
         else
            undef(name);
    }
     else
        error(dir[ 0], " getdef:expecting a directive after # ");
}

int main(){
     char w[MAXWORD];
     struct nlist *p;
     while(getword(w,MAXWORD)!=EOF){
         if(strcmp(w, " # ")== 0)
            getdef();
         else  if(!isalpha(w[ 0]))
            printf( " %s ",w);
         else  if((p=lookup(w))==NULL)
            printf( " %s ",w);
         else 
            ungets(p->defn);
    }
     return  0;
}

第7章 输入与输出

变长参数列表

#include <stdio.h>
#include <stdarg.h>

void minprintf( char *fmt,...){
    va_list ap;
     char *p,*sval;
     int ival;
     double dval;
    va_start(ap,fmt);
     for(p=fmt;*p;p++){
         if(*p!= ' % '){
            putchar(*p);
             continue;
        }
         switch(*++p){
             case  ' d ':
                ival=va_arg(ap, int);
                printf( " %d ",ival);
                 break;
             case  ' f ':
                dval=va_arg(ap, double);
                printf( " %f ",dval);
                 break;
             case  ' s ':
                 for(sval=va_arg(ap, char*);*sval;sval++) 
                    putchar(*sval);
                 break;
             default:
                putchar(*p);
                 break;
        }
    }
    va_end(ap);
}
int main(){
     int a= 3;
     double d= 8.7;
    minprintf( " %d %f\n ",a,d);

}

#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#define LOCALFMT 100

void minprintf( char *fmt,...){
    va_list ap;
     char *p,*sval;
     char localfmt[LOCALFMT];
     int ival,i;
    unsigned uval;
     double dval;
    va_start(ap,fmt);
     for(p=fmt;*p;p++){
         if(*p!= ' % '){
            putchar(*p);
             continue;
        }
        i= 0;
        localfmt[i++]= ' % ';
         while(*(p+ 1)&&!isalpha(*(p+ 1)))
            localfmt[i++]=*++p;
        localfmt[i++]=*(p+ 1);
        localfmt[i]= ' \0 ';
         switch(*++p){
             case  ' d ':
             case  ' i ':
                ival=va_arg(ap, int);
                printf(localfmt,ival);
                 break;
             case  ' x ':
             case  ' X ':
             case  ' u ':
             case  ' o ':
                uval=va_arg(ap,unsigned);
                printf(localfmt,uval);
             case  ' f ':
                dval=va_arg(ap, double);
                printf(localfmt,dval);
                 break;
             case  ' s ':
                sval=va_arg(ap, char*);
                printf(localfmt,sval);
                 break;
             default:
                putchar(*p);
                 break;
        }
    }
    va_end(ap);
}
int main(){
     int a= 3;
     double d= 8.7;
    minprintf( " %d %f\n ",a,d);

}

#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#define LOCALFMT 100
void minscanf( char *fmt,...){
    va_list ap;
     char *p,*sval;
     char localfmt[LOCALFMT];
     int c,i,*ival;
    unsigned *uval;
     double *dval;
    va_start(ap,fmt);
     for(p=fmt;*p;p++){
         if(*p!= ' % '){
            localfmt[i++]=*p;
             continue;
        }
        i= 0;
        localfmt[i++]= ' % ';
         while(*(p+ 1)&&!isalpha(*(p+ 1)))
            localfmt[i++]=*++p;
        localfmt[i++]=*(p+ 1);
        localfmt[i]= ' \0 ';
         switch(*++p){
             case  ' d ':
             case  ' i ':
                ival=va_arg(ap, int*);
                scanf(localfmt,ival);
                 break;
             case  ' x ':
             case  ' X ':
             case  ' u ':
             case  ' o ':
                uval=va_arg(ap,unsigned*);
                scanf(localfmt,uval);
                 break;
             case  ' f ':
                dval=va_arg(ap, double*);
                scanf(localfmt,dval);
                 break;
             case  ' s ':
                sval=va_arg(ap, char*);
                scanf(localfmt,sval);
                 break;
             default:
                scanf(localfmt);
                 break;
        }
    }
}

下面是标准库中对fgets和fputs函数的实现:

char *fgets( char *s, int n,FILE*iop){
    register  int c;
    register  char *cs;
    cs=s;
     while(--n> 0&&(c=getc(iop))!=EOF)
         if((*cs++=c)== ' \n ')
             break;
    *cs= ' \0 ';
     return (c==EOF&&cs==s)?NULL:s;
}  
int fputs( char*s ,FILE*iop){
     int c;
     while(c=*s++)
        putc(c,iop);
     return ferror(ip)?EOF: 0;               
}

#include <stdio.h>
#include <stdlib.h>
#include < string.h>
#define MAXLINE 100
void filecomp(FILE*fp1,FILE*fp2){
     char line1[MAXLINE],line2[MAXLINE];
     char*lp1,*lp2;
     do{
        lp1=fgets(line1,MAXLINE,fp1);
        lp2=fgets(line2,MAXLINE,fp2);
         if(lp1==line1&&lp2==line2){
             if(strcmp(line1,line2)!= 0){
                printf( " first difference in line\n %s\n ",line1);
                lp1=lp2=NULL;
            }
        }
         else  if(lp1!=line1&&lp2==line2)
            printf( " end of first at line\n%s\n ",line2);
         else  if(lp1==line1&&lp2!=line2)
            printf( " end of first at line\n%s\n ",line1);
    }
     while(lp1==line1&&lp2==line2);
}
int main( int argc, char *argv[]){
    FILE *fp1,*fp2;
     if(argc!= 3){
        fprintf(stderr, " comp:need two file names\n ");
        exit( 1);
    }
     else{
         if((fp1=fopen(*++argv, " r "))==NULL){
            fprintf(stderr, " comp:can't open %s\n ",*argv);
            exit( 1);
        }
         else  if((fp2=fopen(*++argv, " r "))==NULL){
            fprintf(stderr, " comp:can't open %s\n ",*argv);
            exit( 1);
        }
         else{
            filecomp(fp1,fp2);
            fclose(fp1);
            fclose(fp2);
            exit( 0);
        }
    }
}

#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#define MAXLINE 1000
void fpat(FILE *fp, char *fname, char *pattern, int except, int number);
int main( int argc, char*argv[]){
     char pattern[MAXLINE];
     int c,except= 0,number= 0;
    FILE *fp;
     while(--argc> 0&&(*++argv)[ 0]== ' - ')
         while(c=*++argv[ 0])
             switch(c){
                 case  ' x ':
                    except= 1;
                     break;
                 case  ' n ':
                    number= 1;
                     break;
                 default:
                    printf( " find:illegal option %c\n ",c);
                    argc= 0;
                     break;
            }
     if(argc>= 1)
        strcpy(pattern,*argv);
     else{
        printf( " Usage:find [-x] [-n] pattern [file ..]\n ");
        exit( 1);
    }
     if(argc== 1)
        fpat(stdin, "",pattern,except,number);
     else
         while(--argc> 0)
             if((fp=fopen(*++argv, " r "))==NULL){
                fprintf(stderr, " find: can't open %s\n ",*argv);
                exit( 1);
            } else{
                fpat(fp,*argv,pattern,except,number);
                fclose(fp);
            }
     return  0;
}
void fpat(FILE *fp, char *fname, char *pattern, int except, int number){
     char line[MAXLINE];
     long lineno= 0;
     while(fgets(line,MAXLINE,fp)!=NULL){
        ++lineno;
         if((strstr(line,pattern)!=NULL)!=except){
             if(*fname)
                printf( " %s -  ",fname);
             if(number)
                printf( " %ld:  ",lineno);
            printf( " %s ",line);
        }
    }
}

#include <stdio.h>
#include <stdlib.h>

#define MAXBOT 3
#define MAXHDR 5
#define MAXLINE 100
#define MAXPAGE 66
int heading( char *fname, int pageno){
     int ln= 3;
    fprintf(stdout, " \n\n ");
    fprintf(stdout, " %s   page %d\n ",fname,pageno);
     while(ln++<MAXHDR)
        fprintf(stdout, " \n ");
     return ln;
}
void fileprint(FILE*fp, char *fname){
     int lineno,pageno= 1;
     char line[MAXLINE];
    lineno=heading(fname,pageno++);
     while(fgets(line,MAXLINE,fp)!=NULL){
         if(lineno== 1){
            fprintf(stdout, " \f ");
            lineno=heading(fname,pageno++);
        }
        fputs(line,stdout);
         if(++lineno>MAXPAGE-MAXBOT)
            lineno= 1;
    }
    fprintf(stdout, " \f ");
}
int main( int argc, char *argv[]){
    FILE *fp;
     if(argc== 1)
        fileprint(stdin, "   ");
     else
         while(--argc> 0)
             if((fp=fopen(*++argv, " r "))==NULL){
                fprintf(stderr, " print:can't open %s\n ",*argv);
                exit( 1);
            }
             else{
                fileprint(fp,*argv);
                fclose(fp);
            }
     return  0;
}

随机数发生器,生成浮点数的方法

第8章 UNIX系统接口

利用低级的read和write函数来构造高级函数getchar,putchar等。

int getchar_( void){
     char c;
     return (read( 0,&c, 1)== 1)?(unsigned  char)c:EOF;
}  
int getchar__( void){
     static  char buf[BUFSIZ];
     static  char *bufp=buf;
     static  int n= 0;
     if(n== 0){
        n=read( 0,buf, sizeof buf);
        bufp=buf;
    }
     return (--n> 0)?(unsigned  char )*bufp++:EOF;

}

#include <unistd.h>
#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20
typedef  struct _iobuf{
     int cnt;
     char *ptr;
     char * base;
     int flag;
     int fd;
}FILE;
extern FILE _iob[OPEN_MAX];
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
enum _flags{
    _READ = 01,
    _WRITE = 02,
    _UNBUF= 04,
    _EOF = 010,
    _ERR= 020
};
int _fillbuf(FILE*);
int _flushbuf( int ,FILE *);
#define feof(p) (((p)->flag&_EOF)!=0)
#define ferror(p) (((p)->flag&_ERR)!=0)
#define fileno(p) ((p)->fd)

#define getc(p) (--(p)->cnt>=0\
        ?(unsigned  char)*(p)->ptr++:_fillbuf(p))

#define putc(x,p) (--(p)->cnt>=0\
        ?*(p)->ptar++=(x):_flushbuf((x),p))

#define getchar() getc(stdin)
#define putchar(x) putc(x,stdout)

#include <fcntl.h>
#define PERMS 0666
FILE *fopen( char *name, char *mode)
{
     int fd;
    FILE *fp;
     if(*mode!= ' r '&&*mode!= ' w '&&*mode!= ' a ')
         return NULL;
     for(fp=_iob;fp<_iob+OPEN_MAX;fp++)
         if((fp->flag&(_READ|_WRITE))== 0)
             break;
     if(fp>=_iob+OPEN_MAX)
         return NULL;
     if(*mode== ' w ')
        fd=creat(name,PERMS);
     else  if(*mode== ' a '){
         if((fd=open(name,O_WRONLY, 0))==- 1)
            fd=creat(name,PERMS);
        lseek(fd, 0L, 2);
    }
     else
        fd=open(name,O_RDONLY, 0);
     if(fd==- 1)
         return NULL;
    fp->fd=fd;
    fp->cnt= 0;
    fp-> base=NULL;
    fp->flag=(*mode== ' r ')?_READ:_WRITE;
     return fp;
}

int _fillbuf(FILE*fp){
     int bufsize;
     if((fp->flag&(_READ|_EOF|_ERR))!=_READ)
         return EOF;
    bufsize=(fp->flag&_UNBUF)? 1:BUFSIZ;
     if(fp-> base==NULL)
         if((fp-> base=( char*)malloc(bufsize))==NULL)
             return EOF;
    fp->ptr=fp-> base;
    fp->cnt=read(fp->fd,fp->ptr,bufsize);
     if(--fp->cnt< 0){
         if(fp->cnt==- 1)
            fp->flag|=_EOF;
         else
            fp->flag|=_ERR;
        fp->cnt= 0;
         return EOF;
    }
     return (unsigned  char)*fp->ptr++;
}
FILE _iob[OPEN_MAX]={
    { 0,( char*) 0,( char*) 0,_READ, 0 },
    { 0,( char*) 0,( char*) 0,_WRITE, 1 },
    { 0,( char*) 0,( char*) 0,_WRITE|_UNBUF, 2 },
};
int _flushbuf( int x,FILE*fp){
    unsigned nc;
     int bufsize;
     if(fp<_iob||fp>=_iob+OPEN_MAX)
         return EOF;
     if((fp->flag&(_WRITE|_ERR))!=_WRITE)
         return EOF;
    bufsize=(fp->flag&_UNBUF)? 1:BUFSIZ;
     if(fp-> base==NULL){
         if((fp-> base=( char*)malloc(bufsize))==NULL){
            fp->flag|=_ERR;
             return EOF;
        }
    }
     else{
        nc=fp->ptr-fp-> base;
         if(write(fp->fd,fp-> base,nc)!=nc){
            fp->flag|=_ERR;
             return EOF;
        }
    }
    fp->ptr=fp-> base;
    *fp->ptr++=( char)x;
    fp->cnt=bufsize- 1;
     return x;
}
int fclose(FILE *fp){
     int rc;
     if((rc=fflush(fp))!=EOF){
        free(fp-> base);
        fp->ptr=NULL;
        fp->cnt= 0;
        fp-> base=NULL;
        fp->flag&=(_READ|_WRITE);
    }
     return rc;
}
int fflush(FILE*fp){
     int rc= 0;
     if(fp<_iob||fp>=_iob+OPEN_MAX)
         return EOF;
     if(fp->flag&_WRITE)
        rc=_flushbuf( 0,fp);
    fp->ptr=fp-> base;
    fp->cnt=(fp->flag&_UNBUF)? 1:BUFSIZ;
     return rc;
}

int fseek(FILE *fp, long offset, int origin){
    unsigned nc;
     long rc= 0;
     if(fp->flag&_READ){
         if(origin== 1)
            offset-=fp->cnt;
        rc=lseek(fp->fd,offset,origin);
        fp->cnt= 0;
    }
     else  if(fp->flag&_WRITE){
         if((nc=fp->ptr-fp-> base)> 0)
             if(write(fp->fd,fp-> base,nc)!=nc)
                rc=- 1;
         if(rc!=- 1)
            rc=lseek(fp->fd,offset,origin);
    }
     return (rc==- 1)?- 1: 0;
}

#include <stdio.h>
#include < string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

// #define NAME_MAX 14
// typedef struct{
//     long ino;
//     char name[NAME_MAX+1];
// }Dirent;
// typedef struct{
//     int fd;
//     Dirent d;
// }DIR;
// DIR *opendir(char *dirname);
// Dirent* readdir(DIR*dfd);
// void closedir(DIR* dfd);

// char *name;
// struct stat stbuf;
// int stat(char *,struct stat*);
// #define S_IFMT 0160000
// #define S_IFDIR 0040000
// #define S_IFCHR 0020000
// #define S_IFBLK 0060000
// #define S_IFREG 001000
#define MAX_PATH 1024

void dirwalk( char *dir, void(*fcn)( char*)){
     char name[MAX_PATH];
     struct dirent *dp;
    DIR *dfd;
     if((dfd=opendir(dir))==NULL){
        fprintf(stderr, " dirwalk:can't open %s\n ",dir);
         return; 
    }
     while((dp=readdir(dfd))!=NULL){
         if(strcmp(dp->d_name, " . ")== 0||
                strcmp(dp->d_name, " .. ")== 0)
             continue;
         if(strlen(dir)+strlen(dp->d_name)+ 2> sizeof(name))
            fprintf(stderr, " dirwalk:name %s %s too long\n ",
                    dir,dp->d_name);
         else{
            sprintf(name, " %s/%s ",dir,dp->d_name);
            fcn(name);
        }
    }
    closedir(dfd);
}

void fsize( char *name){
     struct stat stbuf;
     if(stat(name,&stbuf)==- 1){
        fprintf(stderr, " fsize:can't access %s\n ",name);
         return ;
    }
     if((stbuf.st_mode&S_IFMT)==S_IFDIR)
        dirwalk(name,fsize);
    printf( " %5u %6o %3u %8ld %s\n ",stbuf.st_ino,
            stbuf.st_mode,stbuf.st_nlink,stbuf.st_size,name);
}
int main( int argc, char **argv){
     if(argc== 1)
        fsize( " . ");
     else
         while(--argc> 0)
            fsize(*++argv);
     return  0;
}

typedef  long Align;
union header{
     struct {
        union header *ptr;
        unsigned size;
    }S;
    Align x;
};
typedef union header Header;
static Header  base;
static Header *freep=NULL;
void *malloc(unsigned nbytes){
    Header *p,*prevp;
    Header *moreroce(unsigned);
    unsigned nuints;
    nuints=(nbytes+ sizeof(Header)- 1)/ sizeof(header)+ 1;
     if((prevp=freep)==NULL){
         base.s.ptr=freeptr=prevptr=& base;
         base.s.size= 0;
    }
     for(p=prevp->s.ptr;;prevp=p,p=p->s.ptr){
         if(p->s.size>=nuints){
             if(p->s.size==nuints)
                prevp->s.ptr=p->s.ptr;
             else{
                p->s.size-=nuints;
                p+=p->s.size;
                p->s.size=nuints;
            }
            freep=prevp;
             return ( void*)(p+ 1);
        }
         if(p==freep)
             if((p=moreroce(nuints))==NULL)
                 return NULL;
    }
}
#define NALLOC 1024
static Header *moreroce(unsigned nu){
     char *cp,*sbrk( int);
    Header *up;
     if(nu<NALLOC)
        nu=NALLOC;
    cp=sbrk(nu* sizeof(Header));
     if(cp==( char*)- 1)
         return NULL;
    up=(Header*)cp;
    up->s.size=nu;
    free(( void*)(up+ 1));
     return freep;
}
void free( void*ap){
    Header *bp,*p;
    bp=(Header*)ap- 1;
     for(p=freep;!(bp>p&&bp<p->s.ptr);p=p->s.ptr)
         if(p>=p->s.ptr&&(bp>p||bp<p->s.ptr))
             break;
     if(bp+bp->size==p->s.ptr){
        bp->s.size+=p->s.ptr->s.size;
        bp->s.ptr=p->s.ptr->s.ptr;
    }
     else
        bp->s.ptr=p->s.ptr;
     if(p+p->size==bp){
        p->s.size+=bp->s.size;
        p->s.ptr=bp->s.ptr;
    }
     else
        p->s.ptr=bp;
    freep=p;
}
void *calloc(unsigned n,unsigned size){
    unsigned i,nb;
     char *p,*q;
    nb=n*size;
     if((p=q=malloc(nb))!=NULL)
         for(i= 0;i<nb;i++)
            *p++= 0;
     return q;
}

C程序设计语言(第2版)相关推荐

  1. C程序设计语言第二版·新版,C程序设计语言(第2版·新版) PDF扫描版[19MB]

    C程序设计语言(第2版·新版) 内容简介: 本书是由C语言的设计者Brian W. Kernighan和Dennis M. Ritchie编写的一部介绍标准C语言及其程序设计方法的权威性经典著作.全面 ...

  2. C程序设计语言(第2版•新版)电子书pdf下载

    C程序设计语言(第2版•新版)下载链接: https://pan.baidu.com/s/1cQBvkOCaABO8ZWr9vWegdA 提取码获取方式:关注下面微信公众号,回复关键字: 1133

  3. c++学习书籍推荐《C++程序设计语言(特别版)》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <C++程序设计语言(特别版•十周年中文纪念版)>编辑推荐:十周年纪念版,体味C++语言的精妙与魅力,享受与大师的心灵对话.1979年,Biarn ...

  4. C程序设计语言(第2版) 中文pdf

    下载地址:网盘下载 内容简介  · · · · · · 本书是由C语言研制者编写的一部介 作者简介  · · · · · · Brian W. Kernighan: 贝尔实验室计算科学研究中心高级研究 ...

  5. c#程序设计语言杜松江版_当前最流行的10款编程语言,你会哪种?

    现在市场上对计算机方面的人才需求量非常大,不过真正需要的是那些有技术的高端人才. 下面就是当前流行的编程语言,来看看都用了那些吧! (PS:排名仅代表作者观点,如有不同观点,请务必坚持自我哦~~~). ...

  6. c#程序设计语言杜松江版_清华大学出版社-图书详情-《C#语言Windows程序设计(第2版)》...

    再 版 序 <C#语言Windows程序设计>(ISBN:978-7-302-23375-6)自2010年9月出版以来,受到了广大读者和众多高校的欢迎和好评,近年来已经重印了4次.尽管如此 ...

  7. 《C++程序设计语言(特别版)》——忠告

    转载于:https://www.cnblogs.com/xkfz007/archive/2012/04/09/2439336.html

  8. 实现《C++程序设计语言(特别版)》第6章 表达式和语句 - 桌面计算器 - Linux

    这个实现只是一个思路,需要容错和优化.表达式语法分析如下: *****************  * program:  *     END  *     expr_list END  * expr_ ...

  9. java程序设计第四版_Java 程序设计语言(第4版) PDF扫描版[29MB]

    Java 程序设计语言(第4版)主要讲授Java程序设计语言,系统地介绍Java的主要包(即java.lang.*.java.util和java.io)中的大多数类,并以内容丰富的示例对这些类如何工作 ...

  10. C++程序设计语言导论

    在第一章致读者的末尾,作者写了这样一段话:"The question ''How does one write good programs in C++?'' is very similar ...

最新文章

  1. 我眼里的几种失败的人生
  2. 云栖大会的最后,阿里巴巴数据安全放了个大招!
  3. Matlab怎么计算信号的能量,用Matlab求离散讯号的能量与功率怎么编程
  4. centos7 安装 mysql rpm_CentOS7使用rpm安装MySQL8
  5. python 函数装饰器学习
  6. python映射类型list_python中标准数据类型:数字 string(字符串) list(列表) tuple(元组) dict(字典) sets(集合)共同点和区别:...
  7. 阿里对大年龄清退的定义
  8. 联想高性能服务器,Lenovo|EMC推出高性能4x4TB服务器级NAS
  9. node.js当中net模块的简单应用(基于控制台的点对点通信)
  10. jquery中prop()方法和attr()方法的区别
  11. Ubuntu环境下sublime3 nodejs安装与插件配置
  12. PLSQL导入导出表的正确步骤
  13. 使用jxls技术导入Excel模版数据(转自其他博客)
  14. jQuery EasyUI简明教程
  15. 海量数据相似度计算之simhash短文本查找
  16. 计算机算log的原理,一位业余爱好者的研究,原本是第一台机械计算器,就这么胎死腹中...
  17. Java常用对象总结
  18. html 360登录自动填写,怎么让360安全浏览器记住以前登陆过的帐号和密码,每次都填很麻烦...
  19. php游戏实例,php实现的简易扫雷游戏实例_PHP
  20. linux系统管理员基础

热门文章

  1. HDU 5761 Rower Bo(物理)
  2. 阻抗匹配四种处理方式
  3. PDF格式分析(一)简介
  4. 2017GDKOI酱油记
  5. UDT(【CVPR2019】Unsupervised Deep Tracking无监督目标跟踪)
  6. LS1046修改寄存器翻转SATA引脚的N/P极性
  7. 在数据库应用系统中数据库的开发
  8. 流媒体技术笔记(视频编码相关)
  9. 成功中标 荣联为中国检科院打造一站式生信服务平台
  10. 英语单词音近形似转化规律研究