C语言逻辑流程

1 概论

不论哪种编程语言,都提供了三种基本的程序流程控制语句,分别是顺序,选择和循环,这三种程序结构可以解决生活中的一切单线程的问题,各种算法的基础也是由这三种程序流程结构组成的。

其中顺序流程控制语句意味着程序是从main方法的第一行代码开始执行,如果main函数中有调用到其他函数,则会进入到被调用函数的代码块,执行完该函数的代码块返回后,再接着执行main函数的代码块,直到程序结束,不过很多事不会是预料的那么顺利,在软件开发过程中间,调试修改错误的时间远远超过编码的时间

而C语言正是通过函数(Java中称为方法)将现实中复杂的业务逻辑逐步分解成多个函数实现了自顶向下,逐步细化,结构化,模块化编程的。

下面以浏览器实现自动搜索的功能为例来说明结构化和函数调用的案例:

第一步:实现打开和浏览器的关闭函数

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

/*
    打开浏览器
    @param str 指定的URL地址
    @author Tony 18601767221@163.com
    @since 20160606 09:03
*/
void open_broswer(char *str) {
    ShellExecuteA(0,"open",str,0,0,3);
}
/*
    关闭浏览器,默认是谷歌
    @author Tony 18601767221@163.com
    @since 20160606 09:04
*/
void close_broswer() {

    system("taskkill /f /im Chrome.exe");
}

第二步:使用键盘的按键实现模拟用户输入关键字搜索网页

#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
/*
    搜索关键字
    @param keywords 关键字参数
    @author Tony 18601767221@163.com
    @since 20160606 09:012
*/
void search_key(char keywords[50]) {

    //遍历输入的字符参数
    for (int i = 0; i < 50;i++) {
        //非空校验

    if (keywords[i]!='\0') {

        char key_words = keywords[i];
        keybd_event(key_words, 0, 0, 0);//按下键盘
        keybd_event(key_words, 0, 2, 0);//松开键盘
    }       
}
    //关键字输入完成之后再回车
    enter();

}

第三步:将程序的执行流程以及函数的调用写入到main方法中

#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
void main() {
    open_broswer("www.baidu.com");
    Sleep(3000);
    char search_keywords[100] = "TAOBAO";
    search_key(search_keywords);
    //close_broswer();
    system("pause");
}

选择结构映射到生活中就是条件判断,例如相亲时需要判断年龄,身高,体重以及财富是否符指定的条件,高考时的录取总分是否符合指定大学的录取分数线等等。

循环结构映射到生活中就是满足某个条件下一直重复的做着某件事情,想想那个两点一线的生活,每天都在重复的做着 起床,上班,回家,睡觉……

2 选择结构

C语言中的选择结构通过if/else语句和switch语句来实现,其中if/else适合做区间判断,switch适合做等值判断。

2.1 if/else

if/else有四种表现形式如下:通常开发中都是嵌套或者多分支

分支结构表现方式
单分支()if(表达式){代码块}
双分支(二选一)if(表达式){代码块}else{代码块}
多分支(多选一)if(表达式){代码块}else if(表达式){代码块}else{代码块}
嵌套分支if(表达式){if(表达式){代码块}}else{}

它们的计算流程都是判断表达式的计算结果如果为非0,这执行代码块的语句们。
如果代码的{}不写,则执行第一个分号结束之前的语句不过建议每个代码块的{}必须加上,增加程序的可读性。
else不能单独存在,与最近的if语句相互匹配

使用if语句求整数的绝对值

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*
    计算输入的整数的绝对值
    @author Tony 18601767221@163.com
    @since 20160605 12:09
*/
void calc_abs() {

    printf("请输入一个整数\n");
    int input_num = 0;
    scanf("%d",&input_num);

    if (input_num<0) {
        input_num *= -1; //负负得正
    }

    printf("你输入的整数是%d,该数值得绝对值是%d\n",input_num,input_num);
}

if语句结合_Bool类型的使用案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
    if的单分支结构一般形式
    @author Tony 18601767221@163.com
    @since 20160605 11:03
*/
void if_sample() {

    //布尔表达式
    _Bool flag = 3 > 2;

    printf("flag =%d\n",flag);
    if (flag) {//变量的值或者是表达式运算的结果为1(也就是_Bool的true)时执行if语句的代码块的内容

        printf("当flag==1时执行了这段语句\n");
    }
}

使用if和变量交换的三种方式实现将输入的三个整数按照从大到小输出

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
*       
    使用if和变量交换的三种方式实现将输入的三个整数按照从大到小输出
    @author Tony 18601767221@163.com
    @since 20160605 11:09
*/

void sort() {

    printf("请输入三个整数,以英文的逗号分隔!!!,输入完成后回车结束\n");
    int one = 0, two = 0, three = 0;
    scanf("%d,%d,%d", &one, &two, &three);
    printf("你输入的三个整数分别为%d\t%d\t%d\n", one, two, three);


    if (one<two) {//one和two互换之后one>two

        //使用中间变量实现交换两个变量的值
        int temp = one;
        one = two;
        two = temp;
    }

    printf("互换之后的结果: one =%d\ttwo=%d\n\n",one,two);

    if (one<three) {//one和three互换之后one>three 此时获取到最大值

        //使用算术运算实现交换两个变量的值(使用乘除法也可以实现)
        one = one + three;
        three = one - three;
        one = one - three;
    }

    printf("互换之后的结果: one =%d\tthree=%d\n\n", one, three);


    if (two<three) {//two和three互换之后two>three

        //使用异或运算符实现交换两个变量的值
        two = two^three;
        three = two^three;
        two = two^three;

    }
    printf("互换之后的结果: two =%d\tthree=%d\n\n", two, three);

    printf("三个整数按照从大到小输出的结果为one=%d\ttwo=%d\tthree=%d\n",one,two,three);

}

多分支并且嵌套的if/esle if /else和嵌套的三目运算符作用是相同的,这里以求输入三个整数的最小数为例说明。

使用if/esle的多分支和嵌套实现求输入三个整数的最小数

/*
    使用if else实现获取三个整数中的最小数
    @author Tony 18601767221@163.com
    @since 20160605 08:45
*/

void if_else_get_min() {


    printf("请输入三个整数,以英文的逗号分隔!!!,输入完成后回车结束\n");
    int one=0, two=0, three=0;
    scanf("%d,%d,%d",&one,&two,&three);

    printf("你输入的三个整数分别为%d\t%d\t%d",one,two,three);
    if (one>two) {//one不是最小的数字 此时只需要比较two和thre

        if (two>three) {

            printf("最小的整数为%d\n",three);
        }
        else {
            printf("最小的整数为%d\n", two);
        }
    }

    else if (one<two) {//two不是最小的数字,只需要比较one和three


        if (one>three) {

            printf("最小的整数为%d\n", three);
        }
        else {
            printf("最小的整数为%d\n", one);
        }
    }

}

使用三目运算符的嵌套实现求输入三个整数的最小数

/*
    使用三目运算符实现求三个整数的最小值
    @author Tony 18601767221@163.com
    @since 20160605 08:58
*/
void ternary_operator_get_min() {

    printf("请输入三个整数,以英文的逗号分隔!!!,输入完成后回车结束\n");
    int one = 0, two = 0, three = 0;
    scanf("%d,%d,%d", &one, &two, &three);
    printf("你输入的三个整数分别为%d\t%d\t%d", one, two, three);

    one > two ? (two>three?printf("最小的值为%d\n",three):printf("最小的值为%d\n",two)):one<three?printf("最小的值为%d\n",one):printf("最小的值为%d",three) ;

}

当使用多分支if/else if/else时,当匹配第一个if(表达式),余下的表达式都不会再执行!!!

#include <stdio.h>

/*
    多重if/ ele if /else 判断
    @author Tony 18601767221@163.com
    @since 20160605 16:57
*/
void get_result_str() {

    int age = 45;//根据年龄判断是青年人 中年人或者老年人
    if (age>24) {

        printf("青年人\n");
    }
    else if (age>=40) {

        printf("中年人\n");
    }
    else {

        printf("老年人\n");
    }
}

//程序主入口
void main() {
    get_result_str();
    getchar();

}

计算一组(输入的三个分数)平均成绩,计算不及格成绩(72)的个数

#include <stdio.h>
/*
    计算三门功课的平均成绩,并统计不及格的科目数量
    @author Tony 18601767221@163.com
    @since 20160605 17:26
*/
void calc_avg(){
    printf("请输入三门科目成绩,以英文的逗号分隔!!!,输入完成后回车结束\n");
    double chinese = 0, math = 0, english = 0;
    scanf("%lf,%lf,%lf", &chinese, &math, &english);
    printf("你输入的三门科目的成绩分别为%.1f\t%.1f\t%.1f\n", chinese, math, english);

    int failureCount = 0; //定义变量保存不及格的分数
    if (chinese<72) {

        failureCount++;
    }
    if (math<72) {

         failureCount++;
     }
     if (english<72) {
         failureCount++;
     }

     double avg_score = (chinese + math + english) / 3;

     printf("不及格的科目数量为%d,平均分为%.1f \n",failureCount,avg_score);
}
2.2 switch

switch出现的目的就是取代多重if/else if/else(嵌套太多之后代码容易出现Bug),switch只能用做整数等值判断,其基本表现形式如下:

switch(expression){
    case  constants_value:
        break;
    case constants_value:
        break;
    default:
        break;
}

其中或者表达式运算的结果只能是整数或者和整数兼容类型的数据(例如字符,枚举),case中的常量值不能相等,case不能处理实数,变量表达式以及关系表达式,break也是必须添加(如果不添加,每个case语句都会执行),直到遇到break(这就实现了多分支就选择执行多分支),表示跳出当前的switch语句,如果所有的case不匹配的话,那么将会执行default语句,相当于多重if/else if/else的else语句。

根据输入的身高计算穿衣服的尺码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*
    根据传入的身高判断穿衣服的大小
    @author Tony 18601767221@163.com
    @since 20160606 10:44
*/
void get_size_by_height() {

    //定义一个男装尺寸的枚举
    enum ClothesSize
    {
        XS = 160,
        M = 170,
        L = 175,
        XL = 180,
        XXML = 185,
        XXXL = 190
    };

    int height=0 ;
    printf("请输入你的身高 例如 160 170 175 180 185\n");
    scanf("%d",&height);

    switch ( height)
    {
    case XS:
        printf("你穿衣服的尺码是XS,身高是%d",XS);
        break;

    case M:
        printf("你穿衣服的尺码是M,身高是%d", M);
        break;
    case L:
        printf("你穿衣服的尺码是L,身高是%d", L);
        break;
    case XL:
        printf("你穿衣服的尺码是XL,身高是%d", XL);
        break;
    case XXML:
        printf("你穿衣服的尺码是XXML,身高是%d", XXML);
        break; 
    case XXXL:
        printf("你穿衣服的尺码是XXXL,身高是%d", XXXL);
        break;
    default:
        printf("你穿衣服的尺寸超出正常人的范围");
        break;
    }
}

根据输入的月份计算所在的季节

/*
    根据输入的数字判断所在的季节
    @author Tony 18601767221@163.com
    @since 20160606 23:05
*/
void get_reason_by_number() {

    int number = 0;
    printf("请输入数字\n");
    scanf("%d",&number);

    switch (number) {

    case 12:
    case 1:
    case 2:
        printf("现在是冬天\n");
        break; //遇到break才会跳出switch的代码块
    case 3:
    case 4:
    case 5:
        printf("现在是春天\n");
        break; 
    case 6:
    case 7:
    case 8:
        printf("现在是夏天\n");
        break;
    case 9:
    case 10:
    case 11:
        printf("现在是冬天\n");
        break;
    default:
        printf("你输入的数字有误\n");
        break;
    }

3 循环结构

C语言(后来的C++,Java,C#等编程语言)都提供了三种循环结构:分别是while,do/while和for循环,其中开发中常用的是while和for循环。同时还提供了循环中断的语句break,continue和goto。循环结构主要包含两个部分:循环条件和循环体,循环条件通常是控制循环执行的次数,而 循环体通常都是结合if/else语句以及之前学习过的运算符和表达式混合使用。

3.1 while循环

while循环常用来判断某个表达式是否成立(计算结果为0时结束循环,非0就会重复执行循环体的内容),在使用while循环时需要注意程序的逻辑,防止死循环的情况出现。

使用while循环吃内存

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


/*
    死循环吃内存
        32位系统当个进程只能占据2G以内的内存空间
    @author Tony 18601767221@163.com
    @since 20160606 20:18
*/
void eat_memory() {

    while (1) //循环的判断条件 : 0表示false,非0表示true 
    {
        //循环体
        malloc(10*1024*1024); //字节为最小的单位 这里是10M
        Sleep(1000);
    }

}

使用while循环异步打开5个记事本

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
/*
    循环打开记事本
    @author Tony 18601767221@163.com
    @since 20160607 20:24
*/
void open_notepad() {

    int i = 0;

    while (i++ < 5) {

        system("start notepad"); //异步打开5个记事本
    }
}

使用while循环计算1-100之间的整数和

#inlcude <stdio.h>
/*
    求1-100之内的整数和
    @author Tony 18601767221@163.com
    @since 20160607 20:30
*/
void get_sum() {

    int sum = 0;
    int i = 1;
    while (i<=100)
    {
        sum += i;
        i++;
    }

    printf("1-100之内的整数和为%d\n",sum);
}

使用while循环计算2的N次方的结果

#include <stdio.h>
/*
    计算2的N次方的结果
    @author Tony 18601767221@163.com
    @since 20160607 20:35
*/
void calc_2n() {
    int num = 0;//循环中断条件
    scanf("%d", &num);
    int result = 1;
    int i = 0; //循环初始条件
    while (i<num) {
        result *= 2;//每次都乘以2 知道次数达到输入的次数为止
        i++;
    }

    printf("2的%d次方的结果是%d\n",num,result);
}

使用while循环结合Windows函数实现调戏QQ
1.使用spy工具获取QQ窗口信息:
使用spy工具获取QQ窗口信息

2 编程实现移动QQ窗口

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

/*
    关闭qq
    @author Tony 18601767221@163.com
    @since 20160607 21:04
*/
void close_qq() {

    system("taskkill /f /im QQ.exe");
    Sleep(1000);
}

/*
    开启QQ
    @author Tony 18601767221@163.com
    @since 20160607 21:08
*/
void open_qq() {

    ShellExecuteA(0,"open","\"C:/Program Files (x86)/Tencent/QQ/Bin/QQScLauncher.exe\"",0,0,0);
}

/*
    移动QQ窗口
    @author Tony 1860187221@163.com
    @since 20160607 21:17
*/
void move_qq() {

    HWND win = FindWindowA("TXGuiFoundation", "QQ"); //获取QQ窗口对象

    if (win == NULL) {

        printf("QQ窗口在玩失踪");
    }

    //获取屏幕分辨率  可以在cmd中输入desk.cpl获取  我的电脑分辨率是1440*900
    int i = 0; //纵坐标
    while (i<900) {
        SetWindowPos(win, NULL, i * 14 / 9, i, 400, 400, 0);//设置窗口大小以及窗口位置
        Sleep(50);
        i += 10;
    }
}

void main() {
    close_qq();
    Sleep(2000);
    open_qq();
    Sleep(2000);
    move_qq();
    system("pause");
}

改进一下move_qq的函数,加个if/else判断实现QQ移动并若影若现

/*
    QQ若隐若现
    @author Tony 18601767221@163.com
    @since 20160607 21:22
*/
void move_qq() {

    HWND win = FindWindowA("TXGuiFoundation", "QQ"); //获取QQ窗口对象

    if (win == NULL) {

        printf("QQ窗口在玩失踪");
    }

    //获取屏幕分辨率  可以在cmd中输入desk.cpl获取  我的电脑分辨率是1440*900

    int i = 0; //纵坐标

    while (i<900) {

        SetWindowPos(win, NULL, i * 14 / 9, i, 400, 400, 0);//设置窗口大小以及窗口为止
        Sleep(50);
        i += 10;


        if (i/10%2==0) { //偶数 显示窗口

            ShowWindow(win, SW_HIDE);
        }
        else {//奇数 隐藏窗口

            ShowWindow(win,SW_SHOW);
        }
    }
}
3.2 do while 循环

do while循环就是不管三七二十一,先执行一遍循环体的内容,再判断循环条件,相比while循环,如果循环条件不成立的话,会比while循环多执行一次。潜台词就是至少会执行一次

当表达式的运算结果为0时,do/while循环也会执行一次

#include <stdio.h>
#include <stdlib.h>
/*
    do/while循环的特点
    @author Tony 18601767221@163.com
    @since 20160607 21:30
*/
void do_while_sample() {

    do {

        system("calc");
    } while (0);//表达式的结果为0也会执行一次循环体

}

所有的while循环都可以替换成do while

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

    @author Tony 18601767221@163.com
    @since 20160607 21:57
*/
void do_while_warning() {

    int i = 5;
    do {
        system("calc");
        i--;
    } while (i>0);
}

do/while循环的使用场景:

#include <stdio.h>
#include <stdlib.h>
/*
    先循环获取用户的数据,再执行判断循环条件
    @author Tony 18601767221@163.com
    @since 20160607 22:03
*/
void uppper() {

    char input = '\0';
    do {
        input =getchar(); //获取屏幕输入的字符
        if (input>='a'&&input<='z') {
            input -= 0x20;

        }
        putchar(input);//输出转换为大写后的字符
        getchar();
        printf("\n");

    } while (input!='\t'); //tab键盘结束输入
}
3.3 for循环

for循环是使用频率最高的循环结构,相对于while循环而言,for的结构更加清晰;

/*
    for循环的基本结构
    @author Tony 18601767221@163.com
    @since 20160608 22:35
*/
void for_sample() {

    for (int i = 0; i < 5;i++) { //i表示初始化条件  i<5就是终止条件 i++ 改变循环变量的值
        system("calc"); //循环体
    }
}

for循环的一般形式都是for(初始化表达式;判断循环条件;改变循环条件){循环体},其中初始化表达式以及判断循环条件以及改变循环条件都可以为空语句,这样就构成了for的死循环,需要注意的是在开发中的绝大多数场景都不应该出现死循环,可能的原因就是程序的逻辑出现了问题,要么就是出在循环的判断条件,要么就是出在没有改变循环条件

#include <stdio.h>

/*
    for实现死循环的两种方式
    @author Tony 18601767221@163.com
    @since 20160607 22:21
*/

void for_dead_loop() {

    for (;;) { //中间的语句起到判断的作用,为空为真,不为空的情况下 非0循环,0终止循环

        printf("死循环1!!!");
    }

    for (; 1;) { //这里的循环条件为1 会一直循环执行循环体的代码

        printf("死循环2!!!");
    }
}

使用for循环计算2的N次方

*
    计算2的n次方,本质上就是N个2相乘的结果
    @author Tony 18601767221@163.com
    @since 20160609
*/
void square(int num) {
    double result = 1.0;
    for (int i = 0; i < num;i++) {
        result *= 2;
    }
    printf("2的%d次方的结果是%.0f\n",num,result);
}

使用for循环实现计算1-100之间的奇数和偶数乘积之和

在遇到这样的问题应该首先要联想到有没有数学公式,再用循环的办法解决

计算相邻的奇数和偶数的乘积数学公式:(2*n)*(2*n-1)

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

/*
    使用for循环实现计算1-100之间 相邻两个奇偶数之和 例如 1*2+3*4....
    计算两个相邻奇数和偶数成绩的公式: (2*n)*(2*n-1)
    @author Tony 18601767221@163.com
    @since 20160608 22:36
*/
void get_sum_result() {

    int sum = 0;//定义变量保存每次相邻基数和偶数的乘积

    for (int i = 1; i < 50;i++) {

        //每次对计算相邻的奇数偶数累加
        sum += (2 * i)*(2 * i - 1);

        printf("循环体中sum=%d\n",sum);
    }
    printf("计算结果为%d\n",sum);

}

使用for循环实现QQ窗体的反方向对称移动

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
*
开启QQ
@author Tony 18601767221@163.com
@since 20160608 23:08
*/
void open_qq_with_for() {

    ShellExecuteA(0, "open", "\"C:/Program Files (x86)/Tencent/QQ/Bin/QQScLauncher.exe\"", 0, 0, 0);
}

/*
QQ若隐若现
@author Tony 18601767221@163.com
@since 20160608 23:22
*/
void move_qq_with_for() {

    HWND win = FindWindowA("TXGuiFoundation", "QQ"); //获取QQ窗口对象

    if (win == NULL) {

        printf("QQ窗口在玩失踪");
    }

    //获取屏幕分辨率  可以在cmd中输入desk.cpl获取  我的电脑分辨率是1440*900

    for (int i = 0; i < 900;i++) {

        SetWindowPos(win, NULL, 1000-i, i * 900 / 1400, 400, 400, 1);

        if (i / 10 % 2 == 0) {

            ShowWindow(win, SW_HIDE);
        }
        else {

            ShowWindow(win, SW_SHOW);
        }
    }

}
void main() {
    open_qq_with_for();
    Sleep(2000);
    move_qq_with_for();
    system("pause");

}
3.4 三种循环的选择

本质上while,do/while和for循环都可以实现相同的功能,但是日常开发中使用频率最高的还是for和while循环,在使用do/while循环时需要排除非0的场景。

以获取输入整数的位数为例:

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

//使用三种循环获取输入的整数位数

/*

    @author Tony 18601767221@163.com
    @since 20160611 17:50
*/
void get_digit_while_sample() {

    int num = 0;
    printf("请输入一个整数\n");

    scanf("%d",&num);

    int i = 0;
    while (num!=0) {

        num /= 10; // 1234 123 12 1 0
        i++;
    }

    printf("你输入的整数位数是%d\n",i);

}
/*

    @author Tony 18601767221@163.com
    @since 20160611 17:56
*/
void get_digit_for_sample() {

    int num = 0;
    printf("请输入一个整数\n");

    scanf("%d", &num);

    int i = 0;

    for (;num!=0;) {

        num /= 10;
        i++;
    }
    printf("你输入的整数位数是%d\n", i);

}


/*

    @author Tony 18601767221@163.com
    @since 20160611 17:59
*/
void get_digit_do_while_sample() {

    int num = 0;
    printf("请输入一个整数\n");
    scanf("%d",&num);
    int i = 0;


    //do while循环条件的异常情况判断
    if (num == 0 ) {
        i = 0;
    }
    else {

        do {
            num /= 10;
            i++;
        } while (num != 0);
    }


    printf("你输入的整数位数是%d\n", i);
}

void main() {

    //get_digit_while_sample();
//  get_digit_for_sample();
    get_digit_do_while_sample();
    system("pause");
}

欢迎扫描下方的二维码,关注微信公众服务号-艺无止境,分享IT技术干货。
艺无止境

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值