C语言入门3-逻辑控制

If-Else

语法

if (expression)
 statement1
else
 statement2

Else-If

语法

if (expression1) {
    // 条件expression1为真时执行的语句
} else if (expression2) {
    // 条件expression1为假,且expression2为真时执行的语句
} else if (expression3) {
    // 条件expression1和expression2为假,且expression3为真时执行的语句
    // 可以有更多else if分支
} else {
    // 所有条件expression1, expression2, expression3等都为假时执行的语句
}

举例
二分法查找。(注意:数组必须有序)

#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:在已排序的数组v中使用二分查找算法查找元素x
int binsearch(int x, int v[], int n);

int main() {
    int v[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // 定义一个已排序的数组v

    // 调用binsearch函数,查找元素7在数组v中的位置,并打印返回的索引
    printf("%d\n", binsearch(7, v, 9));
}

// 函数定义:在已排序的数组v中使用二分查找算法查找元素x
int binsearch(int x, int v[], int n) {
    int mid, low, high; // 定义中间索引mid,以及搜索范围的low和high

    low = 0; // 初始化low为0,指向数组的开始
    high = n - 1; // 初始化high为n-1,指向数组的末尾

    // 循环进行二分查找,直到low大于high
    while (low <= high) {
        mid = (low + high) / 2; // 计算中间索引mid

        // 根据x与数组中间元素v[mid]的比较结果更新搜索范围
        if (x < v[mid])
            high = mid - 1; // 如果x小于v[mid],则更新high为mid-1
        else if (x > v[mid])
            low = mid + 1; // 如果x大于v[mid],则更新low为mid+1
        else
            return mid; // 如果找到x,则返回索引mid
    }
    // 如果未找到x,则返回-1
    return -1;
}

练习

  1. 我们的二分查找在循环内进行了两次测试,但一次测试就足够了(代价是需要进行更多的外部测试)。编写一个循环内只进行一次测试的版本,并测量运行时间的差异。
#include <stdio.h>    // 引入标准输入输出库
#include <time.h>     // 引入时间处理库

// 函数声明:二分查找算法
int binsearch(int x, int v[], int n);

int main() {
    int v[1000]; // 定义一个大小为1000的整型数组
    // 初始化数组v,将每个元素设置为其索引值
    for (int i = 0; i < 1000; i++)
        v[i] = i;

    clock_t start, end; // 定义开始和结束时间变量
    double cpu_time_used; // 定义用于存储CPU时间的变量

    start = clock(); // 记录二分查找开始时间
    // 在循环中重复调用binsearch函数1000000次
    for (int i = 0; i < 1000000; i++)
        binsearch(73, v, 10);
    end = clock(); // 记录二分查找结束时间

    // 计算经过的CPU时间,并转换为秒
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    // 打印经过的时间
    printf("Time used: %f seconds\n", cpu_time_used);
}

// 二分查找算法实现
int binsearch(int x, int v[], int n) {
    int mid, low, high;

    low = 0; // 初始化low为0
    high = n - 1; // 初始化high为数组末尾索引

    // 循环进行二分查找,直到low大于high
    while (low <= high) {
        mid = low + (high - low) / 2; // 计算中间索引,防止溢出
        // 进行查找,根据比较结果更新搜索范围
        if (x < v[mid]) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }
    // 如果未找到x,返回-1
    return -1;
}

Switch

语法

switch (expression) {
    case constant_expression1:
        // 代码块1
        break;
    case constant_expression2:
        // 代码块2
        break;
    ...
    default:
        // 默认代码块,可选
}

注意:

  • switch语句开始于圆括号内的表达式(expression),这个表达式的结果通常是一个整数或枚举类型。

举例

#include <stdio.h>

int main() {
    int month;
    printf("Enter a month (1-12): ");
    scanf("%d", &month);

    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            printf("%d is a month with 31 days.\n", month);
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            printf("%d is a month with 30 days.\n", month);
            break;
        case 2:
            printf("%d is February.\n", month);
            // 没有break,将继续执行下一个case的代码
        default:
            printf("Invalid month.\n");
    }

    return 0;
}

Loops - While, For and Do-While

  1. For循环
  • 语法
for (初始化表达式; 条件表达式; 递增/递减表达式) {
    // 循环体
}
  • 举例
for (int i = 0; i < 10; i++) {
    printf("%d ", i);
}
  1. While循环
  • 语法
while (条件表达式) {
    // 循环体
}
  • 举例
int i = 0;
while (i < 10) {
    printf("%d ", i);
    i++;
}
  1. Do-While循环
  • 语法
do {
    // 循环体
} while (条件表达式);
  • 举例
int i = 0;
do {
    printf("%d ", i);
    i++;
} while (i < 10);

举例
将整数转换为字符串。

void atoi(int n, char s[]) {
    int i, sign;

    // 检查整数n是否为负数,并保存符号
    if ((sign = n) < 0) // 此处存在逻辑错误,应使用'='进行赋值,而非比较
        n = -n;

    i = 0; // 初始化字符串索引
    do {
        // 将数字n的最低位加到字符串s的末尾,并递增索引i
        s[i++] = n % 10 + '0';
    } while ((n /= 10) > 0); // 循环直到n变为0

    // 缺少reverse函数的定义,该函数应该用于反转字符串s
    reverse(s);
}

练习

  1. 关于atoi函数有一个漏洞,当n=-2,147,483,648时,n = -n会溢出。请修改atoi,使其不会出现溢出问题。
void atoi(int n, char s[]) {
    int i, sign;

    // 判断 n 的符号并存储
    if ((sign = n) < 0)  // 如果 n 是负数
        ;  // sign 被赋值为负数

    i = 0;
    do {
        // 取 n 的个位数转换为字符并存储到 s 中
        // 如果 n 是正数,直接取余数
        // 如果 n 是负数,先取余数再取负值
        s[i++] = (sign > 0) ? (n % 10 + '0') : (-1 * (n % 10) + '0');
    } while ((n /= 10) != 0);  // 将 n 除以 10 并更新 n,直到 n 变为 0

    if (sign < 0)
        s[i++] = '-';  // 如果 n 是负数,添加负号到 s 中
    s[i] = '\0';  // 在字符串末尾添加结束符 '\0'

    reverse(s);  // 反转字符串 s
}
  1. 编写一个函数itob(int n, char s[], int b),将整数n转为b进制的字符串。
#include <stdio.h>
#include <string.h>

void itob(int n, char s[], int b);
void reverse(char s[]);

int main() {
    char str[12];  // 声明一个大小为 12 的字符数组,用于存储转换后的字符串
    itob(-235, str, 16);  // 将 -235 转换为十六进制并存储在 str 中
    printf("%s\n", str);  // 打印转换后的字符串
    return 0;
}

// 反转字符串 s 的函数
void reverse(char s[]) {
    int i, j;
    char temp;
    // 使用双指针法进行字符串反转
    for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    }
}

// 将整数 n 转换为指定进制 b 的字符串表示存储在 s 中的函数
void itob(int n, char s[], int b) {
    int i, sign, c;

    if ((sign = n) < 0)
        ;  // 如果 n 是负数,sign 被赋值为负数,但此处没有实际操作

    i = 0;
    do {
        // 取 n 对 b 取模的结果,转换为对应的字符并存储到 s 中
        // 如果 n 是正数,直接取余数
        // 如果 n 是负数,先取余数再取负值
        c = (sign > 0) ? (n % b + '0') : (-1 * (n % b) + '0');
        if (c > '9')
            s[i++] = c - '9' - 1 + 'a';  // 如果超过 9,转换为 a-f 的字母形式
        else
            s[i++] = c;
    } while ((n /= b) != 0);  // 将 n 除以 b 并更新 n,直到 n 变为 0
    
    if (sign < 0)
        s[i++] = '-';  // 如果 n 是负数,添加负号到 s 中
    s[i] = '\0';  // 在字符串末尾添加结束符 '\0'

    reverse(s);  // 反转字符串 s,使得最终结果正确表示 n 的 b 进制数
}

Break and Continue

Break

  • break 用于立即终止包含它的最内层循环的执行。
for (int i = 0; i < 10; i++) {
    if (i == 5) {
        break; // 当i等于5时,退出循环
    }
    printf("%d ", i);
}
// 输出: 0 1 2 3 4

Continue

  • continue 用于跳过当前循环迭代的剩余部分,并立即进入下一次迭代。
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) {
        continue; // 跳过偶数,不执行下面的打印语句
    }
    printf("%d ", i);
}
// 输出: 1 3 5 7 9
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值