C语言实例1002,实例内容是什么?

99ANYc3cd6
预计阅读时长 17 分钟
位置: 首页 C语言 正文

这个实例非常适合作为第1002个例子,因为它巧妙地结合了C语言中几个核心且重要的概念:指针、数组、循环和字符串处理,理解了它,你对C语言的指针操作能力将会有一个质的飞跃。

c语言实例1002c语言实例
(图片来源网络,侵删)

C语言实例 1002:使用指针反转字符串

实例目标

编写一个C语言程序,实现一个自定义函数 str_rev,该函数接收一个字符串作为参数,并使用指针操作原地(in-place,即不创建新的字符串)反转这个字符串,在 main 函数中调用该函数并打印反转前后的结果。

核心知识点解析

要实现这个功能,我们需要深入理解以下几个C语言概念:

  • 字符串在C语言中的表示:在C语言中,字符串本质上是一个以空字符 '\0' 结尾的字符数组。char str[] = "hello"; 实际上在内存中存储的是 'h', 'e', 'l', 'l', 'o', '\0'
  • 指针与数组的关系:数组名 str 会“衰变”为其首元素的地址。char *p = str;char *p = &str[0]; 是等价的,我们可以通过指针来遍历和访问数组中的元素。
  • 指针的算术运算:对指针进行加减运算,会使指针移动到相应类型大小的内存位置。p++ 会让 char 类型的指针 p 向后移动1个字节,指向下一个字符。
  • 原地反转算法
    1. 使用两个指针,一个指向字符串的开头(left),一个指向字符串的末尾(right)。
    2. 交换 leftright 指针所指向的字符。
    3. left 指针向后移动一位 (left++),right 指针向前移动一位 (right--)。
    4. 重复步骤2和3,直到 left 指针不再小于 right 指针,此时反转完成。

代码实现

下面是完整的、带有详细注释的C语言代码。

#include <stdio.h>
/**
 * @brief 使用指针原地反转字符串
 * @param str 要反转的字符数组(字符串)
 *        注意:这里使用 char* 类型,因为我们要修改字符串内容。
 *        如果不想修改原字符串,应该传递 const char*,但本例需要修改。
 */
void str_rev(char *str) {
    // 1. 边界条件检查
    // str 是 NULL 指针,或者 str 指向的字符串为空(第一个字符就是 '\0'),则无需操作。
    if (str == NULL || *str == '\0') {
        return;
    }
    // 2. 初始化两个指针
    // left_ptr 指向字符串的开头
    char *left_ptr = str;
    // right_ptr 指向字符串的末尾(即 '\0' 的前一个字符)
    // 我们需要先找到字符串的末尾
    char *right_ptr = str;
    while (*right_ptr != '\0') {
        right_ptr++;
    }
    // 循环结束后,right_ptr 指向 '\0',所以要回退一步
    right_ptr--;
    // 3. 交换字符,直到指针相遇或交叉
    while (left_ptr < right_ptr) {
        // 交换 left_ptr 和 right_ptr 所指向的字符
        // 使用一个临时变量 temp 来完成交换
        char temp = *left_ptr;
        *left_ptr = *right_ptr;
        *right_ptr = temp;
        // 移动指针,准备下一次交换
        left_ptr++;
        right_ptr--;
    }
}
/**
 * @brief 辅助函数:打印字符串
 * @param str 要打印的字符串
 */
void print_str(const char *str) {
    // 使用 const char* 表示函数不会修改传入的字符串内容,这是一种良好的编程习惯
    if (str == NULL) {
        printf("(NULL)\n");
        return;
    }
    while (*str != '\0') {
        putchar(*str);
        str++;
    }
    printf("\n");
}
int main() {
    // 定义一个字符数组来存储字符串
    char my_string[] = "Hello, C Pointers!";
    printf("--- C语言实例 1002: 使用指针反转字符串 ---\n\n");
    // 打印反转前的字符串
    printf("反转前的字符串是: ");
    print_str(my_string);
    // 调用自定义的反转函数
    str_rev(my_string);
    // 打印反转后的字符串
    // 注意:my_string 数组中的内容已经被修改
    printf("反转后的字符串是: ");
    print_str(my_string);
    // --- 更多测试用例 ---
    printf("\n--- 更多测试用例 ---\n");
    // 测试空字符串
    char empty_str[] = "";
    printf("测试空字符串 \"\": ");
    str_rev(empty_str);
    print_str(empty_str);
    // 测试单字符字符串
    char single_char_str[] = "A";
    printf("测试单字符 \"A\": ");
    str_rev(single_char_str);
    print_str(single_char_str);
    // 测试回文字符串
    char palindrome_str[] = "madam";
    printf("测试回文字符串 \"madam\": ");
    str_rev(palindrome_str);
    print_str(palindrome_str);
    return 0;
}

代码步骤详解

  1. #include <stdio.h>:包含标准输入输出库,以便使用 printfputchar 等函数。
  2. *`str_rev(char str)` 函数**:
    • 参数char *str 是一个字符指针,它接收 main 函数中字符数组 my_string 的首地址。
    • 边界检查if (str == NULL || *str == '\0') 是一个健壮性考虑,如果传入空指针或空字符串,函数直接返回,避免无效操作。
    • 寻找末尾指针while (*right_ptr != '\0') { right_ptr++; } 循环会一直执行,直到 right_ptr 指向字符串的结束符 '\0'right_ptr-- 让它指向最后一个有效字符。
    • 核心交换循环while (left_ptr < right_ptr) 是循环的条件,当左指针在右指针的左边时,继续交换。
    • 交换操作
      • char temp = *left_ptr;:取出左指针指向的字符存入临时变量。
      • *left_ptr = *right_ptr;:将右指针指向的字符赋值给左指针指向的位置。
      • *right_ptr = temp;:将临时变量中的字符(原来的左字符)赋值给右指针指向的位置。
    • 指针移动left_ptr++;right_ptr--; 让两个指针向中间靠拢。
  3. *`print_str(const char str)` 函数**:
    • 这是一个辅助函数,用于打印字符串,使用 const char * 是一个好的实践,它告诉调用者和编译器这个函数承诺不会修改字符串内容,增加了代码的安全性。
  4. main() 函数
    • char my_string[] = "Hello, C Pointers!";:定义并初始化一个字符数组。
    • 调用和打印:清晰地展示了在调用 str_rev 前后字符串的变化。
    • 测试用例:提供了空字符串、单字符字符串和回文字符串的测试,验证了函数的鲁棒性。

运行结果

将以上代码编译并运行,你将得到如下输出:

c语言实例1002c语言实例
(图片来源网络,侵删)
--- C语言实例 1002: 使用指针反转字符串 ---
反转前的字符串是: Hello, C Pointers!
反转后的字符串是: !sretniP ,C olleH
--- 更多测试用例 ---
测试空字符串 "": 
测试单字符 "A": A
测试回文字符串 "madam": madam

总结与扩展

这个实例完美地展示了C语言指针的强大和灵活,通过直接操作内存地址,我们高效地完成了字符串反转任务。

可以思考的扩展问题:

  1. str_rev 函数能接受字符串字面量(如 str_rev("hello");)作为参数吗?

    • 不能,在大多数C实现中,字符串字面量存储在只读的内存区域(如常量区/代码段),尝试修改它会导致未定义行为,通常是程序崩溃(段错误),这就是为什么我们的 main 函数中使用的是 char my_string[],它被分配在可读写的栈内存上。
  2. 如何实现一个不区分大小写的字符串比较函数?

    • 这也是一个经典的指针应用,可以创建两个指针分别遍历两个字符串,在比较每个字符时,使用 tolower()toupper() 函数将字符转换为统一的大小写后再比较。

通过掌握这类实例,你将能够更自信地使用C语言去解决更复杂的底层问题。

-- 展开阅读全文 --
头像
C语言与C程序的核心特点有何关键差异?
« 上一篇 01-28
Error C1083错误,如何解决C语言编译失败?
下一篇 » 01-28

相关文章

取消
微信二维码
支付宝二维码

目录[+]