• c程序设计语言里提到的例程


    1、getline / copy 1.9节

    int getline(char s[], int lim)
    {
        int c, i;
        
        for(i = 0; i < lim-1 && (c=getchar())!=EOF && c != ''; ++i)
            s[i] = c;
        if (c == '
    ') {
            s[i] = c;
            ++i;
        }
        s[i] = '';
        return i;
    }
    int getline(char s[], int lim)
    void copy(char to[], char from[])
    {
        int i;
        
        i = 0;
        while((to[i] = from[i]) != '')
            ++i; 
    } 
    void copy(char to[], char from[])

    2、reverse 1.9节1.19题

    #include<stdio.h>
    #define MAXLINE 1000
    
    int getline(char line[], int maxline);
    void reverse(cahr s[]);
    
    main()
    {   
        char line[MAXLINE];
    
        while(getline(line, MAXLINE) > 0){
            reverse(line);
            printf("%s", line);
        }
    }
    
    void reverse(char s[])
    {
        int i, j;
        char temp;
        
        i = 0;
        while(s[i] != '')
            ++i;
        --i;
        if (s[i] == '
    ')
            --i;
        j = 0;
        while(j < i){
            temp = s[j];
            s[j] = s[i];
            s[i] = temp;
            --i;
            ++j;
        }
    }
    void reverse(char s[])

    3.atoi 2.7节/3.5节/

    int atoi(char s[])
    {
        int i, n;
        n = 0;
        for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
            n = 10 * n + (s[i] - '0');
        return n;
    }
    int atoi(char s[])
    #include<ctype.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 atoi(char s[])

    4.htoi 2.7节 练习2.3

    #define YES 1
    #define NO 0
    
    //convert hex string s to integer
    int htoi(char s[])
    {
        int hexdigit, i, inhex, n;
        i = 0;
        if(s[i] == '0'){
            ++i;
            if(s[i] == 'x' || s[i] == 'X'){
                ++i;
            }
        }
        n = 0;
        inhex = YES;
        for( ; inhex == YES; ++i){
            if(s[i] >= '0' && s[i] <= '9')
                hexdigit = s[i] - '0';
            else if(s[i] >= 'a' && s[i] <= 'z')
                hexdigit = s[i] - 'a' + 10;
            else if(s[i] >= 'A' && s[i] <= 'Z')
                hexdigit = s[i] - 'A' + 10;
            else
                inhex = NO;
               if(inhex == YES)
                n = 16 * n + hexdigit;
        }
        return n;
    }
    int htoi(char s[])

    5.squeeze 2.8节 练习2.4。将s1中与s2中字符匹配的字符都删除

    void squeeze(char s1[], char s2[])
    {
        int i, j, k;
        
        for(i = k = 0; s1[i] != ''; i++){//k表示待匹配位置。 
            for(j = 0; s2[j] != '' && s2[j] != s1[j]; j++)
                ;
            if(s2[j] == '') // 没匹配,则将s1[i]这个字符复制到k表示的匹配后的位置。 
                s1[k++] = s1[i];
        }
        s1[k] = '';
    }
    void squeeze(char s1[], char s2[])

    6.any 2.8节 练习 2.5。 返回s2中任意字符在s1中第一次出现的位置,不存在则返回-1。标准库中strpbrk函数完成同样功能,但是返回指针

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

    7.getbits 2.9节。 返回x中从右边数第p位开始(包括第p位)向右数共n位的字段

    unsigned getbits(unsigned x, int p, int n)
    {
        return (x >> (p+1-n)) & ~(~0 << n);
    }
     (x >> (p+1-n))将相应字段移动到最右端
    ~0获得一组1,<<n后取反获得一组掩码
    unsigned getbits(unsigned x, int p, int n)

    8.setbits 2.9节 练习2.6。 将x中从右边第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变

    unsigned setbits(unsigned x, int p, int n, unsigned y)
    {
        return x & ~(~(~0 << n)  << (p+1-n)) |
              (y &   ~(~0 << n)) << (p+1-n); 
    }
    原始情况如下 
    xxx...xnnnx...xxx x
    yyy..........ynnn y
    
    我们只要把x中的n清零,把y中除了n的位清零并移动到第p位处,然后或操作
    xxx...x000x...xxx x 
    000...0nnn0...000 y
    -------------------
    xxx...xnnnx...xxx x
    unsigned setbits(unsigned x, int p, int n, unsigned y)

    9.invert 2.9节 练习2.7。 将x中从右边第p位开始的n个位求反,x的其余各位保持不变

    unsigned invert(unsigned x, int p, int n)
    {
        return x ^ (~(~0 << n) << (p+1-n));
    }
    类似之前的技巧,将右边n位设置为1,然后移动到位置p
    unsigned invert(unsigned x, int p, int n)

    10.rightrot 2.9节 练习2.8。 将x向右循环位移n位(即移出的位会到最左端)

    unsigned rightrot(unsigned x, int n)
    {
        int wordlength(void);
        int rbit;
        
        while (n-- > 0){
            rbit = (x & 1) << (wordlength() - 1); //rbit将x的最右位移动到最左端
            x = x >> 1;     
            x = x | rbit; //完成循环位移 
        }
        return x;
    } 
    
    //计算出所使用的平台的字长 
    int wordlength(void)
    {
        int i;
        unsigned v = (unsigned) ~0;
        
        for(i = 1; (v = v >> 1) > 0; i++)
            ;
        return i;
    }
    
    //另一种解法,不使用循环 
    unsigned rightrot(unsigned x, int n)
    {
        int wordlength(void);
        unsigned rbits;
        
        if((n = n % wordlength()) > 0){
            rbits = ~(~0 << n) & x;
            
            rbits = rbits << (wordlength() - n);
            x = x >> n;
            x = x | rbits; 
        }
        return x;
    } 
    unsigned rightrot(unsigned x, int n)

    11.bitcount 2.10节 练习2.9。 统计1的数量

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

    12.binsearch 3.3节

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

    13.escape/unescape 3.4节 练习3.2。 将字符串t复制到字符串s中,并将换行符、制表符等不可见字符换为转义字符;完成功能相反的unescape函数

    void escape(char s[], char t[])
    {
        int i , j;
        for(i = j = 0; t[i] != ''; i++)
        {
            switch(t[i]){
                case '
    ':
                    s[j++] = '\';
                    s[j++] = 'n';
                    break;
                case '	':
                    s[j++] = '\';
                    s[j++] = 't';
                    break;
                default:
                    s[j++] = t[i];
                    break;
            }
        }
        s[j] = '';
    }
    void escape(char s[], char t[])
    void unescape(char s[], char t[])
    {
        int i, j;
        for(i = j = 0; t[i] != ''; i++)
            switch(t[i]){
                case '\':
                    switch(t[++i]){
                        case 'n':
                            s[j++] = '
    ';
                            break;
                        case 't':
                            s[j++] = '	';
                            break;
                           default:
                               s[j++] = '\';
                               s[j++] = t[i];
                               break;
                    }
                    break;
                default:
                    s[j++] = t[i];
                    break;
            }
        s[j] = '';
    }
    void unescape(char s[], char t[])

    14.shellsort 3.5节

    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;
                }
    }
    这种实现很紧凑,但是每次v[j] > v[j+gap]都做一次完整的交换,效率不高,可以参考一般的插入排序实现,使用一个temp保存待排序数,直到最后再将temp放入数组中。
    如下
    void shell_sort(ElementType A[], int N)
    {
        int P, D, i, temp;
        for (D = N/2 ; D>0; D/=2)
        {
            for (P = D; P < N; P++)
            {
                temp = A[P];
                for (i = P; i >= D && A[i-D] > temp; i-=D)
                {
                    A[i] = A[i-D];
                }
                A[i] = temp;
            }
        }
    }
    void shellsort(int v[], int n)

    15.reverse 3.5节

    void reverse(char s[])
    {
        int c, i, j;
        for(i = 0; j = strlen(s) - 1; i < j; i++, j--)
        {
            c = s[i];
            s[i] = s[j];
            s[j] = c;
        }
    }
    void reverse(char s[])

    16.expand 3.5节 练习3.3。 把字符串s1中类似a-z的速记符号拓展为abc...xyz的完整列表,要求拓展顺序为ascii顺序。

    void expand(char s1[], char s2[])
    {
        char c;
        int i, j;
        i = j = 0;
        while((c = s1[i++]) != ''){ //fetch a char from s1[]
            if(s1[i] == '-' && s1[i+1] >= c){
                i++;
                while(c < s1[i])
                    s2[j++] = c++;
            }
            else
                s2[j++] = c;
        }
        s2[j] = '';
    }
    void expand(char s1[], char s2[])

    17.itoa 3.6节/3.6节 练习3.4

    void itoa(int n, char s[])
    {
        int i, sign;
        
        if((sign = n) < 0)
            n = -n;
        i = 0;
        do{
            s[i++] = n % 10 + '0';
        } while((n /= 10) > 0);
        if(sign < 0)
            s[i++] = '-';
        reverse(s);
    }
    取数字的方向和填字符串数组的方向刚好相反。
    因为n = -n,这个实现可能导致溢出。
    解决溢出问题之后的版本:
    #define abs(x) ((x) < 0? -(x) : (x))
    void itoa(int n, char s[])
    {
        int i, sign;
    
        sign = n;
        i = 0;
        do{
            s[i++] = abs(n % 10) + '0';
        } while((n /= 10) != 0);
        if(sign < 0)
            s[i++] = '-';
        s[i] = '';
        reverse(s);
    }
    void itoa(int n, char s[])

    18.itob 3.6节 练习3.5

    void itob(int n, char s[], int b)
    {
        int i, j, sign;
        
        if((sign = n) < 0)
            n = -n;
        i = 0;
        do{
            j = n % b;
            s[i++] = (j <= 9) ? j+'0' : j+'a'-10;
        }while((n /= b) > 0);
        if(sign < 0)
            s[i++] = '-';
        s[i] = '';
        reverse(s);
    }
    void itob(int n, char s[], int b)

    19.strindex 4.1节。 返回字符串t在s中出现位置的索引(类似strstr)

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

    20.strrindex 4.1节 练习4.1。 返回字符串t在s中最右边出现位置的索引

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

    21.qsort 4.10节

    void qsort(int v[], int left, int right)
    {
        int i, last;
        if(left >= right)
            return;
        swap(v, left, left+(right-left)/2);
        last = left;
        for(i = left+1; i <= right; i++)
            if(v[i] < v[left])
                swap(v, ++last, i);
        swap(v, left, last);
        qsort(v, left, last-1);
        qsort(last+1, right);
    }
    void qsort(int v[], int left, int right)
    void qsort(void *v[], int left, int right, int(*comp)(void *, void *))
    {
        int i, last;
        void swap(void *v[], int, int);
        
        if (left >= right)
            return;
        swap(v, left, (left+right)/2);
        last = left;
        for (i = left + 1; i <= right; i++)
            if ((*comp)(v[i], v[left]) < 0)
                swap(v, ++last, i);
        swap(v, left, last);
        qsort(v, left, last-1, comp);
        qsort(v, last+1, right, comp);
    }
    void qsort(void *v[], int left, int right, int(*comp)(void *, void *))

    22.strcpy 5.5节

    void strcpy(char *s, char *t)
    {
        while(*s++ == *t++)
            ;
        return;
    }
    void strcpy(char *s, char *t)
    1 应该使用的完善的版本
    2 char *strcpy(char *strDest, const char *strSrc)
    3 {
    4     assert((strDest!=NULL) && (strSrc !=NULL));   
    5     char *address = strDest;                     
    6     while( (*strDest++ = * strSrc++) != ‘0’ )
    7        ;
    8     return address ;                           
    9 }

    23.strcmp 5.5节

    int strcmp(char *s. char *t)
    {
        for( ; *s == *t; s++, t++)
            if(*s == '')
                return 0;
        return *s - *t;
    }
    int strcmp(char *s. char *t)

    24.strend 5.5节 练习5.3。 如果字符串t出现在字符串s的尾部,函数返回1;否则返回0

    int strend(char *s, char *t)
    {
        char *begin_s = s;
        char *begin_t = t;
        
        for( ; *s; s++)
            ;
        for( ; *t; t++)
            ;
        for( ; *s == *t; s--, t--)
            if(t == begin_t || s == begin_s)
                break;
        if(*s == *t && t == begin_t && *s != '')
            return 1;
        else
            return 0;
    }
    int strend(char *s, char *t)

    25.find 5.10节。 对命令<find -x -n 模式>返回与x不匹配的行,-x表示除此之外,-n表示显示行号

    #include<stdio.h>
    #include<string.h> 
    #define MAXLINE 1000
    int getline(char *line, int max);
    
    int main(int argc, char *argv[])
    {
        char line[MAXLINE];
        long lineno = 0;
        int c, except = 0, number = 0, found = 0;
        
        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
    ", c);
                           argc = 0;
                           found = -1;
                           break;
                }
            if(argc != 1)
                printf("Usage: find -x -n pattern
    ");
            else
                while(getline(line, MAXLINE) > 0){
                    lineno++;
                    if((strstr(line, *argv) != NULL) != except){
                        if(number)
                            printf("%ld:", lineno);
                        printf("%s", line);
                        found++;
                    }
                }
            return found;
    }
    find

    26.tail 5.10节 练习5.13。 使用命令tail -n将输入中的后n行打印出来

    5.11节 练习5.14~5.17 命令行参数解析

    练习5.20 语义解析6.4节 词频统计

    6.6节 表查找核心代码

     tip:

    1:文件描述符0、1、2对应stdin、stdout、stderr

    2:read/write()返回实际传输字节数,在读文件时,函数的返回值可能小于请求的字节数;在写文件时,如果返回值与请求值不同则可能发生了错误。返回0表示到达文件结尾,返回-1表示发生某种错误。

    3:

    1、printf / scanf

    知识点:变长参数函数使用:

    头文件#include<stdarg.h>

    使用va_list ap; 来声明一个变长参数类型的变量ap,即argument pointer。

    使用va_start(ap, fmt); fmt为最后一个有名参数(函数原型void print(char *fmt, ...)),ap将被设置为指向第一个无名参数的指针。

    使用ival = va_arg(ap, int);来获得一个参数,类型由va_arg的第二个参数决定,并且ap指向下一个参数。

    va_end(ap); 在函数返回前调用,完成相关清理工作。

    #include<stdio.h>
    #include<stdarg.h>
    
    int main()
    {
        print("%d %d",1,2);
        return 0;
    }
    
    void print(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);
    }
    void print(char *fmt, ...)

     因为类型提升的问题,未被声明的参数会被提升为int和double,所以var_arg(ap, char)和var_arg(ap,float)错误的。

  • 相关阅读:
    怎样重定向404页面?404页面重定向 PHP如何使404页面重定向
    css选择器(1)——元素选择器、类名和id选择器
    style对象的cssText方法
    css选择器(2)——属性选择器和基于元素结构关系的选择器
    js的闭包中关于执行环境和作用链的理解
    attachEvent和addEventListener
    使用js获取页面的各种高度
    课堂知识
    分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的10个词打印出来。
    每日心情
  • 原文地址:https://www.cnblogs.com/autoria/p/5898261.html
Copyright © 2020-2023  润新知