• 读书笔记之:C程序设计语言(第2版)[+++++]


    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. 读入一组文本,打印出最长文本

    View Code
    #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 编写一个统计空格、制表符和换行符个数的程序。

    View Code
     #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 编写一个程序,以每行一个单词的形式打印其输入

    View Code
    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 编写一个程序,打印输入中单词长度的直方图。水平方向的直方图比较容易绘制,垂直方向的直方图则要困难写。

    View Code
    #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 编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行

    View Code
    #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中的字符顺序颠倒过来。使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序。

    View Code
    #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应该作为变量还是常量呢?

    View Code
     #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程序的情况相同。当使用一个制表符或者一个空格都可以到达下一个制表符终止位时,选用那种替换字符比较好?

    View Code
    #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

    View Code
    #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语言中,注释不允许嵌套。

    View Code
    #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语言程序中的基本语法错误

    View Code
    #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

    View Code
    #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;
     }

    下面是一个标准答案

    下面是一个测试:

    View Code
    #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;                                      
     }

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

    View Code
    #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. 折半查找

    View Code
    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
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    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 value=rand();
            int d;
            if(value&0x1)
                value=-value;
            sprintf(s,"%d",value);
            d=atoi_(s);                          
            printf("%12d %12s %12d ",value,s,d);
            if(value==d)
                printf("OK\n");
            else
                printf("NO\n");
        }
    }

    测试输出如下:

    希尔排序shell

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

    View Code
    #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等类似的情况。作为前导和尾随的字符原样复制。

    View Code
    #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:将整型数转化为字符串

    View Code
    #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

    View Code
    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中。

    View Code
    #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

    View Code
    #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

    View Code
    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:将字符串转换为浮点数

    View Code
    #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以及一个指数(可能有正负号)。

    View Code
    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 外部变量

    一个简单的计算器程序

    View Code
    #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;
            }
        }
    }

    View Code
    #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;
            }
        }
    }

    View Code
    #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;
            }
        }
    }

    View Code
    #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;
            }
        }
    }

    View Code
    #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]);
    }

     

    View Code
    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;                                    
    }

    View Code
    #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;
            }
        }
    }

    快速排序

    View Code
    #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章 指针与数组

    View Code
    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;
    }



    View Code
    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程序的一个简单版本,实现对输入文本的排序。

    View Code
    #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;
        }
    }


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

    View Code
    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

    View Code
    #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;
    }

    View Code
    #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一个比较不错的程序:将声明转化为文字描述或将文字描述转化为声明

    View Code
    #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;
    }

    View Code
    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;
    }

    View Code
    #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;
    }

    View Code
    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;
    }

     

    View Code
    #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章 结构体

    统计关键字出现的次数

    View Code
    #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;
    }

     

    View Code
    #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;
    }

    View Code
    #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;
    }

     

    表查找程序核心代码:

    View Code
    #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);
        }
    }

     

    View Code
    #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章 输入与输出

    变长参数列表

    View Code
    #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);

    }

     

    View Code
    #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);

    }

    View Code
    #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函数的实现:

    View Code
    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;               
    }

     

    View Code
    #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);
            }
        }
    }

    View Code
    #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);
            }
        }
    }

     

    View Code
    #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;     

    }


    View Code
    #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;
    }

     

    View Code
    #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;
    }

    View Code
    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;
    }
  • 相关阅读:
    注意事项 软件连接的数据库是设置输出的数据库,弄错会造成数据库不一致
    归并排序
    快速排序
    冒泡排序
    插入排序
    上次遗留下来的XMLUtil的问题
    关于子网掩码
    java.lang.InstantiationException
    java.lang.ExceptionInInitializerError
    关于HashMap中的负载因子
  • 原文地址:https://www.cnblogs.com/xkfz007/p/2623702.html
Copyright © 2020-2023  润新知