当前位置: 首页 > news >正文

C语言字符串操作汇总

C语言字符串操作汇总

这里提供C语言字符串操作汇总,AI含量过高,过几天会验证的。

字符串基础操作

字符串的初始化

在 C 语言中字符串本质上是以 \0 结尾的字符数组,因此初始化既可以通过字面量,也可以通过手动赋值构造。

初始化方式示例说明
字面量初始化char s[] = "abc";自动分配数组长度为 4,包括末尾 \0
指针指向常量区const char *p = "abc";指向的是只读字符串常量,不可修改
指定长度初始化char s[32] = "abc";剩余位置自动填充为 0
手动填充字符char s[32]; memset(s, 0, 32); strcpy(s,"abc");先清空,再复制
初始化为空字符串char s[16] = {0};char s[16] = "";一个只包含 \0 的字符串

🔎 注:

  • char* p = "abc" 中的 "abc" 通常存放在 只读段,对其执行 p[0] = 'x' 会导致段错误。
  • 如果需要修改字符串内容,应使用 字符数组(如 char s[])而不是指针常量。

✅ 示例

// 字面量初始化
char s1[] = "hello";// 指向常量字符串(只读)
const char *s2 = "hello";// 指定一个更大的缓冲区,为后续拼接做准备
char s3[64] = "hello";// 初始化为空字符串
char s4[32] = {0};// 使用 memset + strcpy
char s5[32];
memset(s5, 0, sizeof(s5));
strcpy(s5, "hello");

字符串的长度

在 C 语言中,字符串以 \0 作为结束标志,因此长度的计算方式是从首字符开始,直到遇到第一个 \0 为止的字符数
标准库提供了用于计算长度的 API:strlen()

API头文件功能说明
size_t strlen(const char *s)<string.h>返回字符串中 \0 之前的字符个数

⚠️ 注意事项

  • 返回值不包含末尾的 \0
  • 参数必须是以 \0 结尾的合法字符串,否则会造成越界读取。
  • 复杂操作中(例如循环里反复调用)建议先保存长度,避免重复遍历。

✅ 示例

#include <stdio.h>
#include <string.h>int main(){char s[] = "hello";size_t len = strlen(s);  // len = 5printf("length = %zu\n", len);// 典型用法:遍历字符串for(size_t i = 0; i < strlen(s); i++){       // ❌ 每次都会重新计算putchar(s[i]);}// 更好的写法size_t n = strlen(s);for(size_t i = 0; i < n; i++){               // ✅ 性能更优putchar(s[i]);}return 0;
}

字符串的修改

字符串内容可以通过索引直接修改,也可以通过内存函数批量修改。

场景常用方法
修改单个字符s[i] = 'X'
批量替换memset, memmove, 手动循环
大小写转换toupper, tolower(需逐字符处理)

示例

char s[] = "hello";
// 修改第一个字符
s[0] = 'H';// 批量修改
for (int i = 0; s[i]; i++) {if (s[i] >= 'a' && s[i] <= 'z') {s[i] = toupper(s[i]);}
}

字符串的追加

将一个字符串追加到另一个字符串的尾部,可以使用标准库函数或手动追加。

场景方法
简单追加strcat(dest, src)
指定长度追加strncat(dest, src, n)
手动追加memcpy 或逐字符复制

注意dest 必须有足够的空间容纳追加后的内容。

示例

char dest[64] = "hello";
char src[] = " world";
strcat(dest, src);           // dest = "hello world"// 指定添加前 3 个字符 => "hello wo"
char shortSrc[] = "world";
strncat(dest, shortSrc, 2);

字符串的删除

字符串没有现成的删除 API,通常通过移动后面的字符覆盖掉要删除的内容完成。

场景方法
删除某一段字符串memmove
删除末尾字符s[len - 1] = '\0'

示例:删除第 i 个位置开始的 n 个字符

char s[64] = "hello world";
int pos = 5;   // 从第5个字符开始删除
int n = 1;     // 删除1个字符(删除空格)// 将 "world\0" 移动到原先空格的位置
memmove(s + pos, s + pos + n, strlen(s) - pos - n + 1);// 结果: "helloworld"
场景方法
复制一个字符串strcpy, strncpy
拼接字符串strcat, strncat
格式化构造sprintf, snprintf

注意事项

  • strcpystrcat 在目标缓冲区长度不足时会导致 越界写入
  • sprintf 没有边界检查,建议使用 snprintf

示例

char buf[32] = {0};
strcpy(buf, "hello");
strcat(buf, "_world");// 格式化构造
int id = 10;
snprintf(buf, sizeof(buf), "item_%d", id);

字符串比较与判断

strcmp 判断两个字符串是否相等

原型

int strcmp(const char *s1, const char *s2);

说明
按字典序比较字符串 s1 和 s2:

  • 返回 0 表示相等
  • 返回 <0 表示 s1 < s2
  • 返回 >0 表示 s1 > s2

示例

char a[] = "apple";
char b[] = "banana";if (strcmp(a, b) == 0){printf("equal\n");
} else if (strcmp(a, b) < 0){printf("a < b\n");
} else {printf("a > b\n");
}

strncmp 比较字符串前n个字符是否相等

原型

int strncmp(const char *s1, const char *s2, size_t n);

说明
最多比较 前 n 个字符。常用于判断是否具有某个前缀。

示例

char s[] = "prefix_test";if (strncmp(s, "pre", 3) == 0) {printf("has prefix 'pre'\n");
}

字符串查询与解析

场景方法
查找字符strchr, strrchr
查找子串strstr
按格式解析sscanf
按分隔符切割strtok

当然,下面按照和之前一致的方式,以函数名为标题,依次补充 API 说明和示例。


strchr

原型

char *strchr(const char *s, int c);

说明
在字符串中查找第一次出现的字符 c,返回指针;如果没找到,返回 NULL

示例

char s[] = "a:b:c";
char *p = strchr(s, ':');
if (p != NULL) {printf("first ':' at position %ld\n", p - s);
}

strrchr

原型

char *strrchr(const char *s, int c);

说明
在字符串中查找最后一次出现的字符 c

示例

char s[] = "a:b:c";
char *p = strrchr(s, ':');
if (p) {printf("last ':' at position %ld\n", p - s);
}

strstr

原型

char *strstr(const char *haystack, const char *needle);

说明
查找子串 needlehaystack 中第一次出现的位置,返回指针;找不到返回 NULL

示例

char s[] = "hello world";
char *p = strstr(s, "lo");
if (p) {printf("found at index %ld\n", p - s);
}

sscanf

原型

int sscanf(const char *str, const char *format, ...);

说明
按照 format 从字符串中解析数据,返回成功匹配的字段个数。

示例

char s[] = "10,3.14";
int i; float f;
if (sscanf(s, "%d,%f", &i, &f) == 2) {printf("i=%d, f=%f\n", i, f);
}

strtok

原型

char *strtok(char *str, const char *delim);

说明
按指定分隔符把字符串分成一段一段,每次调用返回一个 token。

⚠️ 注意:该函数会修改原始字符串。

示例

char s[] = "a,b,c";
char *p = strtok(s, ",");
while (p != NULL) {printf("%s\n", p);p = strtok(NULL, ",");
}

数值与字符串之间的转换

场景方法
int→stringsnprintf, itoa
string→intatoi, strtol

注意事项

  • atoi 没有错误检测,建议使用 strtol
  • strtol 需要检查 errno 和 endptr

数值到字符串

sprintf / snprintf
char buf[32];
int n = 123;
snprintf(buf, sizeof(buf), "%d", n);   // 十进制
itoa(十进制 / 十六进制 / 任意进制)

注意:itoa 是扩展函数,不是标准 C,但在多数编译器中可用。

char buf[32];
int n = 255;
itoa(n, buf, 10);  // 十进制 => "255"
itoa(n, buf, 16);  // 十六进制 => "ff"

字符串到数值

atoi / strtol(十进制)
char *s = "123";
int n = atoi(s);            // => 123// 推荐方式(可检测错误)
char *endptr;
long val = strtol(s, &endptr, 10);
strtol(任意进制)
char *s = "ff";
long v = strtol(s, NULL, 16);   // => 255
atof / strtof(浮点)
char *s = "3.14";
float f = strtof(s, NULL);     // => 3.14
double d = atof(s);            // 同样支持

字符串输出

场景方法
输出到终端printf
输出到缓冲区snprintf

注意事项

  • 输出到 char* 时 始终 指定缓冲区大小
  • 避免使用未初始化的 char* 作为输出缓冲区

示例

char out[64];
snprintf(out, sizeof(out), "Name:%s Age:%d", name, age);
printf("%s\n", out);

字符串数组

好的,以下是**“字符数组(即存放多个 char* 的数组)”**这一部分的追加内容,只包含你要求的 4 个操作示例:


字符数组常用操作示例(char *arr[]

初始化字符串数组

// 静态初始化
char *arr[] = { "apple", "banana", "orange" };// 动态添加(提前申请空间)
char *arr2[10];
arr2[0] = "alpha";
arr2[1] = "beta";

获取数组大小

int count = sizeof(arr) / sizeof(arr[0]);
printf("size = %d\n", count);

增删改查

// 增加(假设当前已有3项)
arr2[3] = "gamma";  // append// 修改
arr2[1] = "new_beta";// 删除(把后面的元素向前移动)
int pos = 1;  // 删除下标 1
int total = 4;  // 当前数组元素个数
for(int i = pos; i < total - 1; i++){arr2[i] = arr2[i + 1];
}
total--;// 查找
for(int i = 0; i < total; i++){if(strcmp(arr2[i], "gamma") == 0){printf("found at %d\n", i);}
}

排序

#include <stdlib.h>
#include <string.h>// 比较函数
int cmp_str(const void *a, const void *b){const char *sa = *(const char **)a;const char *sb = *(const char **)b;return strcmp(sa, sb);
}int main(){char *arr[] = { "orange", "apple", "banana" };int n = sizeof(arr) / sizeof(arr[0]);qsort(arr, n, sizeof(char*), cmp_str);for(int i = 0; i < n; i++){printf("%s\n", arr[i]);}return 0;
}
http://www.dtcms.com/a/336551.html

相关文章:

  • 线程相关知识
  • NokoPrint:安卓平台上的便捷无线打印解决方案
  • 存储引擎 InnoDB
  • 【Python】Python 面向对象编程详解​
  • k8s-单主机Master集群部署+单个pod部署lnmp论坛服务(小白的“升级打怪”成长之路)
  • 集成电路学习:什么是SIFT尺度不变特征变换
  • oom 文件怎么导到visualvm分析家
  • 双指针和codetop2(最短路问题BFS)
  • 闭区间是否存在一个开区间包含之
  • ESP32S3在圆形240x240 1.8寸GC9A01 SPI显示屏显示双眼睛表情
  • 寻找数组的中心索引
  • ai测试(六)
  • [Java恶补day50] 174. 地下城游戏
  • 数据结构03(Java)--(递归行为和递归行为时间复杂度估算,master公式)
  • 数学建模 13 SVM 支持向量机
  • 原子操作及基于原子操作的shared_ptr实现
  • PYTHON让繁琐的工作自动化-PYTHON基础
  • 【撸靶笔记】第五关:GET - Double Injection - Single Quotes - String
  • 基于STM32单片机智能RFID刷卡汽车位锁桩设计
  • Qt同步处理业务并禁用按钮
  • linux系统------kubenetes单机部署
  • LeetCode 分类刷题:2962. 统计最大元素出现至少 K 次的子数组
  • 5G虚拟仿真平台
  • [激光原理与应用-292]:理论 - 波动光学 - 驻波的本质是两列反向传播的相干波通过干涉形成的能量局域化分布
  • 安全多方计算(MPC)简述
  • Compose笔记(四十六)--Popup
  • Houdini 粒子学习笔记
  • 服装外贸管理软件 全流程优化解决方案
  • 学习记录(二十)-Overleaf如何插入参考文献
  • Chrome 插件开发实战:从入门到上架的全流程指南