C语言字符串与指针的高效操作技巧

💡 学习目标:掌握指针操作C语言字符串的核心方法,熟练实现字符串的遍历、拷贝、拼接、比较等常用功能;学习重点:字符串的本质、指针操作字符串的优势、常见字符串处理函数的手写实现。
39.1 字符串的本质与指针表示
C语言中并没有专门的字符串类型,字符串的存储和操作都和字符数组、指针紧密相关。
39.1.1 字符串的存储形式
💡 C语言的字符串是以字符数组的形式存储,并且以 '\\0' 作为结束标志的一组字符序列。
我们可以通过两种方式定义字符串:
#include <stdio.h>
int main() {
// 方式1:字符数组初始化
char str1[] = "Hello C";
// 方式2:字符指针指向字符串常量
char *str2 = "Hello Pointer";
printf("str1 = %s\\n", str1);
printf("str2 = %s\\n", str2);
return 0;
}
运行结果:
str1 = Hello C
str2 = Hello Pointer
⚠️ 注意:字符指针指向的字符串常量存放在只读数据区,不能通过指针修改字符串内容。
以下代码会导致程序崩溃:
char *str = "Hello";
str[0] = 'h'; // 错误,字符串常量不可修改
39.1.2 字符串与指针的关联
💡 字符串的名字本质上是指向字符数组首元素的指针,我们可以通过指针算术运算访问字符串的每个字符。
字符串的结束标志 '\\0' 是指针遍历字符串的关键判断条件。
示例代码:
#include <stdio.h>
int main() {
char str[] = "C Language";
char *p = str; // 指针指向字符串首字符
// 通过指针遍历字符串
while (*p != '\\0') {
printf("%c ", *p);
p++;
}
return 0;
}
运行结果:
C L a n g u a g e
从代码可以看出,利用指针遍历字符串不需要知道字符串长度,只需要判断当前指针指向的字符是否为 '\\0' 即可。
39.2 指针操作字符串的实战案例
使用指针操作字符串可以让代码更简洁高效,接下来我们通过几个实战案例,掌握指针处理字符串的核心技巧。
39.2.1 案例1:手写字符串长度计算函数
🔧 需求:实现一个类似 strlen 功能的函数,使用指针计算字符串的长度,要求不使用库函数。
#include <stdio.h>
// 计算字符串长度
int my_strlen(char *str) {
char *p = str;
int len = 0;
// 遍历到字符串结束标志
while (*p != '\\0') {
len++;
p++;
}
return len;
}
int main() {
char str[] = "Pointer and String";
printf("字符串长度:%d\\n", my_strlen(str));
return 0;
}
运行结果:
字符串长度:16
💡 技巧:这个函数的核心是利用指针逐个遍历字符,直到遇到 '\\0' 停止计数,和库函数 strlen 的原理完全一致。
39.2.2 案例2:手写字符串拷贝函数
🔧 需求:实现一个类似 strcpy 功能的函数,使用指针将源字符串拷贝到目标字符串,要求不使用库函数。
#include <stdio.h>
// 字符串拷贝函数
void my_strcpy(char *dest, char *src) {
// 拷贝源字符串到目标字符串,包括'\\0'
while (*src != '\\0') {
*dest = *src;
dest++;
src++;
}
*dest = '\\0'; // 手动添加结束标志
}
int main() {
char src[] = "Hello World";
char dest[50]; // 目标数组要足够大
my_strcpy(dest, src);
printf("目标字符串:%s\\n", dest);
return 0;
}
运行结果:
目标字符串:Hello World
⚠️ 注意:目标字符数组的空间必须足够大,否则会导致数组越界,引发程序异常。
39.2.3 案例3:手写字符串拼接函数
🔧 需求:实现一个类似 strcat 功能的函数,使用指针将源字符串拼接到目标字符串的末尾。
#include <stdio.h>
// 字符串拼接函数
void my_strcat(char *dest, char *src) {
char *p = dest;
// 1. 移动指针到目标字符串末尾
while (*p != '\\0') {
p++;
}
// 2. 拷贝源字符串到目标字符串末尾
while (*src != '\\0') {
*p = *src;
p++;
src++;
}
*p = '\\0';
}
int main() {
char dest[50] = "C Language: ";
char src[] = "Pointer Operation";
my_strcat(dest, src);
printf("拼接后字符串:%s\\n", dest);
return 0;
}
运行结果:
拼接后字符串:C Language: Pointer Operation
💡 技巧:字符串拼接的关键是先找到目标字符串的末尾,再从末尾开始拷贝源字符串。
39.2.4 案例4:手写字符串比较函数
🔧 需求:实现一个类似 strcmp 功能的函数,使用指针比较两个字符串的大小。
函数返回值规则:
- 若字符串1 = 字符串2,返回 0
- 若字符串1 > 字符串2,返回正数
- 若字符串1 < 字符串2,返回负数
#include <stdio.h>
// 字符串比较函数
int my_strcmp(char *str1, char *str2) {
while (*str1 != '\\0' && *str2 != '\\0') {
if (*str1 != *str2) {
return *str1 – *str2;
}
str1++;
str2++;
}
// 处理长度不同的情况
return *str1 – *str2;
}
int main() {
char str1[] = "Hello";
char str2[] = "Hello C";
char str3[] = "Hi";
printf("str1 与 str2 比较结果:%d\\n", my_strcmp(str1, str2));
printf("str1 与 str3 比较结果:%d\\n", my_strcmp(str1, str3));
printf("str2 与 str2 比较结果:%d\\n", my_strcmp(str2, str2));
return 0;
}
运行结果:
str1 与 str2 比较结果:-67
str1 与 str3 比较结果:-3
str2 与 str2 比较结果:0
💡 技巧:字符串比较的核心是逐个字符对比ASCII码值,第一个不同字符的差值就是最终结果。
39.3 指针操作字符串的常见问题与解决方案
39.3.1 问题1:字符串缺少结束标志 '\\0'
❌ 错误代码:
char str[5] = {'H', 'e', 'l', 'l', 'o'};
printf("%s\\n", str); // 输出乱码,因为没有'\\0'
✅ 解决方案:
39.3.2 问题2:修改字符串常量
❌ 错误代码:
char *str = "Hello";
*str = 'h'; // 程序崩溃,字符串常量不可修改
✅ 解决方案:
39.3.3 问题3:目标数组空间不足
❌ 错误原因:字符串拷贝或拼接时,目标数组的空间小于拼接后的字符串长度。
✅ 解决方案:
39.4 指针操作字符串的优势
相较于数组下标操作,指针操作字符串有以下明显优势:
39.5 本章小结
✅ C语言字符串是以 '\\0' 为结束标志的字符数组,字符串名本质是指向首字符的指针。
✅ 可以通过指针实现字符串的长度计算、拷贝、拼接、比较等核心功能,原理与库函数一致。
✅ 操作字符串时要注意添加 '\\0'、避免修改字符串常量、保证目标数组空间充足。
✅ 指针操作字符串比数组下标更简洁高效,是C语言开发的必备技能。



