C语言学习笔记20260609-字符串反转两种实现方法
一、知识点概述
总共分为两种主流写法:
-
原地反转:直接修改原字符串,不占用额外内存
-
备份反转(不修改原串):结果存入新数组,保留原始数据
统一输入规范:使用 fgets 安全读取,淘汰 gets 函数。
二、方法一:原地反转(修改原字符串)
1. 原理
使用左右双指针法:
-
左指针从头部开始,右指针从尾部开始
-
两两交换字符,指针向中间靠拢
-
直接在原数组操作,不开辟新空间
2. 优缺点
优点:节省内存、代码高效
缺点:原始字符串会被覆盖丢失
3. 完整可运行代码(超详细注释)
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
// 方法:原地反转字符串
// 直接操作原数组,原字符串会被修改
void reverseString(char* str, int len)
{
int left = 0; // 左指针:起始位置
int right = len - 1; // 右指针:末尾位置
// 双指针向中间遍历交换
while (left < right)
{
// 三步交换字符
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++; // 左指针右移
right--; // 右指针左移
}
}
int main()
{
char str[100001] = { 0 };
// 安全读取整行字符串(支持空格)
fgets(str, 100001, stdin);
// 获取有效长度
int len = strlen(str);
// 处理fgets自带的换行符\n(关键步骤)
if (len > 0 && str[len - 1] == '\n')
{
str[len - 1] = '\0';
len--;
}
// 调用反转函数(修改原串)
reverseString(str, len);
// 输出反转结果
printf("反转后字符串:%s\n", str);
return 0;
}
三、方法二:备份反转(不修改原字符串)
1. 原理
额外定义一个新数组 dest:
-
从原字符串末尾往前取值
-
从新数组头部往后存放
-
原字符串 str 完全不变
2. 优缺点
优点:保留原始数据,后续可复用原字符串
缺点:需要额外开辟数组,占用更多内存
3. 完整可运行代码
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
// 方法:字符串反转(不修改原串)
// str:原字符串(只读,加const保护)
// dest:存储反转结果的新数组
void reverseString(char* dest, const char* str, int len)
{
int i = 0; // 新数组下标(从头写入)
int j = len - 1; // 原数组下标(从尾读取)
// 倒序赋值,实现反转
while (i < len)
{
dest[i] = str[j];
i++;
j--;
}
// 手动补字符串结束符(必须!否则乱码)
dest[len] = '\0';
}
int main()
{
char str[100001] = { 0 }; // 原始字符串
char dest[100001] = { 0 }; // 存放反转结果
// 读取输入
fgets(str, 100001, stdin);
int len = strlen(str);
// 去除fgets读取的换行符
if (len > 0 && str[len - 1] == '\n')
{
str[len - 1] = '\0';
len--;
}
// 反转:原串不变,结果存入dest
reverseString(dest, str, len);
// 同时输出原串和反转串
printf("原字符串:%s\n", str);
printf("反转字符串:%s\n", dest);
return 0;
}
四、两种方法核心对比总结
| 实现方式 | 是否修改原串 | 额外内存开销 | 适用场景 |
|---|---|---|---|
| 原地反转 | 是 | 无 | 无需保留原数据、追求高效省内存 |
| 备份反转 | 否 | 需要新数组 | 需要保留原始字符串、二次处理数据 |
五、总结
-
禁止使用 gets:存在缓冲区溢出漏洞,C11标准已废弃
-
fgets 必处理 \n:否则换行符会参与反转,导致结果错误
-
非原地反转必须补 \0:新数组手动添加结束符,防止乱码
-
只读参数加 const :原字符串不修改时,形参写
const char*,代码更规范 -
交换变量必须用临时变量 temp,不能直接覆盖赋值