• C语言学习笔记(二二)


    C语言学习第二十二天。

    3.5 while循环与for循环
    在while循环语句

        while (表达式)
            语句

    中,首先求表达式的值。如果其值为真非0,则执行语句,并再次求该表达式的值。这一循环过程一直进行下去,直到该表达式的值为假(0)为止,随后继续执行语句后面的部分。

        for循环语句

        for (表达式1; 表达式2; 表达式3)
            语句

        它等价于下列while语句

        表达式1;
        while (表达式1){
            语句
            表达式3;
        }

    从语法角度看,for循环语句的3各组成部分都是表达式。最常见的情况是,表达式1与表达式3是赋值表达式或函数调用,表达式2是关系表达式。这三个组成部分中的任何部分都可以省略,但分号必须保留。如果在for语句值哦改河南省略表达式1与表达式3,它就退化成了while循环语句。如果省略测试条件,即表达式2,则认为其值永远是真值,因此,下列for循环语句:

        for (; ;) {
            ...
        }

    是一个“无限”循环语句,这种语句需要借助其他手段(如break语句或return语句)才能终止。

    如何选择主要取决于个人偏好。例如,在下列语句中:

        while ((c = getchar()) == ' ' || c == '\n' || c == '\t')
            ; /* 跳过空白符*/

    因为其中没有初始化或重新初始化的操作,所以使用while循环语句更自然一些。
    如果语句中需要执行简单的初始化和变量递增,使用for语句更合适一些,它将循环控制语句集中放在循环的开头,结构更紧凑、更清晰。 例如:

        for (i = 0; i < n; i++)
            ...

    这是C语言处理数组前n各元素的一种习惯性用法。

    下面是将字符串转换为对应数值的函数atoi。它可以处理可选的前导空白符以及一个可选的加(+)或减(-)号。
    下面是程序结构,从中可以看出输入的格式:

        如果有空白符的话,则跳过
        如果有符号的话,则读取符号
        取整数部分,并执行转换

    其中每一步都对输入数据进行相应的处理,并为下一步的执行做好准备。当遇到第一个不能转换为数字的字符是,整个处理过程终止。

    #include
    #include

    int main() {
        printf("%d", atoi("     -123xf2"));
    }

    /* atoi函数:将s转换为整数型;*/
    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;
    }

    标准库中提供了一个更完善的函数strol, 它将字符串转换为长整型。

    把循环控制部分集中在一起,对与多重嵌套循环,优势更为明显。下面的函数是对整型数组进行排序的shell排序算法。shell排序算法是D.L.Shell于1959年发明的,其基本思想是:先比较距离远的元素,而不是向简单交换排序算法那样先比较相邻的元素。这样可以快速减少大量的无序情况,从而减轻后续的工作。被比较的元素之间的距离逐步减少,直到减少为1,这是排序变换成了相邻元素的互换。

    #include

    void shellsort(int v[], int n);

    int main() {
        int a[] = {3, 5, 62, 4, 6, 32 , 6};
        int i = 0;
        shellsort(a, 7);
        for (; i < 7; i++)
            printf("%d ", a[i]);
    }

    /* shellsort函数:按递增顺序对v[0]...v[n-1]进行排序 */
    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;
                }
    }

    该函数中包含一个三重嵌套的for循环语句。最外层的for语句控制两个被比较奥元素之间的距离,从n/2开始,逐步进行对这,直到距离为0.中间层的for循环语句用于在元素间移动位置。最内层for语句用于比较各相对gap个位置的元素,当这两个元素逆序时,把他们互换过来。由于gap的值最终要递减到1,因此所有元素最终都会位于正确的排序位置上。注意,即是最外层for循环的控制变量不是算术级,for语句的书写形式仍然没有变,这就说明for语句具有很强的通用性。
    逗号运算符“,”也是C语言优先级最低的运算符,在for语句中经常会用到它。被逗号分隔的一对表达式将按照从左到右的顺序进行求值,各表达式右边的操作数的类型和值即为其结果的类型和值。这样,在for循环语句中,可以将多个表达式放在各个语句成分中,比如同时处理两个循环控制变量。下面以函数reverse(s)来举例。该函数用于倒置字符串s中各个字符的位置。

    #include
    #include

    void reverse(char s[]) ;
    int main() {
        char a[] = "warning!";
        reverse(a);
        printf("%s", a);
    }

    /* reverse函数:倒置字符串s中各个字符的位置 */
    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;
        }
    }

    某些情况下的逗号并不是逗号运算符,比如分隔函数参数的逗号,分隔声明中变量的逗号等,这些逗号并不保证各表达式按照从左往右的顺序求值。
    应该慎用逗号运算符。逗号运算符最适用于关系紧密的结构中,比如上面的reverse函数的for语句,对于需要在单个表达式中进行多步计算的宏来说也很合适。逗号表达式还适用于reverse函数中的元素的交换,这样,元素的交换过程便可以看成是一个单步操作。

        for (i = 0, j = strlen(s)-1; i < j; i++, j--)
            c = s[i], s[i] = s[j], s[j] = c;

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

    #include

    void expand(char s1[], char s2[]);

    int main() {
        char s1[] = "-a-z0-9a-b-c";
        char s2[100];

        expand(s1, s2);
        printf("%s", s2);
    }


    void expand(char s1[], char s2[]) {
        int i, j, k;

        i = j = k = 0;
        while(s1[i] != '\0') {
            if (i > 0 && s1[i] == '-') {
                for (k = 0; k < s1[i+1] - s1[i-1]; k++)
                    s2[j++] = s1[i-1] + k + 1;
                i++;
            } else {
                s2[j++] = s1[i];
            }
            i++;
        }
        s2[j] = '\0';
    }

  • 相关阅读:
    免费开源圈子社交交友社区系统 可打包小程序 支持二开 源码交付!
    202、弱电工程十大无线视频监控系统应用场景
    SpringBoot 项目实战 ~ 5.菜品管理
    【数据结构】链表OJ题(建议收藏!!!)
    Dansyl-TiO2 NPs丹磺酰荧光素标记纳米二氧化钛Dansyl-PEG-TiO2(荧光修饰无机纳米粒)
    保存PyTorch模型为ONNX
    在el-table表头上引入组件不能实时传参bug
    HTML5的学习
    1、强化学习基础知识点
    大数据之LibrA数据库常见术语(七)
  • 原文地址:https://blog.csdn.net/u014360189/article/details/128212572