目录
求字符串长度
strlen
size_t strlen ( const char * str );
- 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。
- 参数指向的字符串必须要以 '\0' 结束。
- 注意函数的返回值为size_t,是无符号的
示例
cpp
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
模拟实现strlen
cpp
#include <stdio.h>
size_t my_strlen(const char* str) {
size_t count = 0;
while (str[count] != '\0') {
count++;
}
return count;
}
int main() {
const char* str = "Hello, World!";
size_t length = my_strlen(str);
printf("字符串的长度为: %zu\n", length);
return 0;
}
长度不受限制的字符串函数
strcpy
copy字符串到目标字符串,应该使用strcpy
char* strcpy(char * destination, const char * source)
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变
示例
cpp
char name[20] = {0};
strcpy(name, "zhang\0hai");
printf("%s\n", name); // zhang
模拟实现strcpy
cpp
char *my_strcpy(char *dest, const char *str)
{
assert(dest && str);
char *res = dest;
while (*dest++ = *str++)
{
}
return res;
}
char arr1[] = "abc\0def";
char arr2[] = {0};
my_strcpy(arr2, arr1);
printf("%s\n", arr2); // abc
strcat
拼接字符串到目标字符串,应该使用strcat
char * strcat ( char * destination , const char * source );
- 源字符串必须以 '\0' 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
cpp
/* 同样 strcpy同strcpy大概一致,需保持足够大的空间,遇\0停止 */
char arr1[] = "demo";
// strcat(arr1, "emo");
// printf("%s", arr1); // demoemo
strcat(arr1, "em\0o");
printf("%s", arr1); // demoem
模拟实现strcat
cpp
char *my_strcat(char *dest, const char *str)
{
char *res = dest;
assert(dest && str);
while (*dest != '\0') // 找到目标空间的末尾\0
{
dest++;
}
while (*dest++ = *str++)
{
;
}
return res;
}
char arr3[20] = "hello ";
my_strcat(arr3, "world");
printf("%s\n", arr3); // hello world
strcmp
两个字符串比较相等,应该使用strcmp
int strcmp ( const char * str1 , const char * str2 );
比较是基于字符的 ASCII 值来进行的。strcmp() 会逐个比较两个字符串对应位置上的字符的 ASCII 值,并按照以下规则返回结果:
当找到不同的字符时,根据其 ASCII 值的大小关系决定比较结果。较小的字符对应的字符串被认为是较小的。如果一个字符串是另一个字符串的前缀,则较短的字符串被认为是较小的。
strcmp() 是区分大小写的。大写字母的 ASCII 值小于小写字母的 ASCII 值。
strcmp() 返回一个整数,表示两个字符串的比较结果。
- 如果字符串相等,则返回 0。
- 如果第一个字符串小于第二个字符串,则返回一个负整数。
- 如果第一个字符串大于第二个字符串,则返回一个正整数。
下面是一些比较的示例:
- strcmp("apple", "apple") 返回 0,因为两个字符串相等。
- strcmp("apple", "banana") 返回一个负整数,因为 "apple" 的 ASCII 值小于 "banana"。
- strcmp("banana", "apple") 返回一个正整数,因为 "banana" 的 ASCII 值大于 "apple"。
- strcmp("apple", "Apples") 返回一个正整数,因为 'a' 的 ASCII 值大于 'A'。
示例
cpp
char arr1[20] = "zhangsan";
char arr2[20] = "zhangsanfeng";
int res = strcmp(arr1, arr2);
if (res < 0)
{
printf("<\n"); // <
}
else if (res == 0)
{
printf("=\0");
}
else
{
printf(">\0");
}
模拟实现strcmp
cpp
int my_strcmp(const char *s1, const char *s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0; // 如果全等 abc == abc
}
s1++;
s2++;
}
return *s1 - *s2;
}
char arr4[] = "zhanghai";
char arr5[] = "zhanghai";
printf("%d\n", my_strcmp(arr4, arr5)); // 0
长度受限制的字符串函数介绍
strncpy
strncpy
函数用于从源字符串复制指定数量的字符到目标字符串中,如果源字符串长度小于指定长度,则会用空字符进行填充。
char * strncpy ( char * destination, const char * source, size_t num );
- 拷贝num个字符从源字符串到目标空间。
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
示例
在这个示例中,我们声明了一个目标字符串 dest
,一个源字符串 src
以及要复制的字符数量 n
。然后,我们使用 strncpy
函数将 src
中的前 n
个字符复制到 dest
中。最后,我们手动添加了一个结尾标记 \0
,以确保目标字符串正确终止。最后,我们打印复制后的目标字符串 dest
。
请注意,要确保目标字符串 dest
的长度足够大,以容纳复制的字符和结尾标记。如果 n
大于等于源字符串的长度,那么目标字符串将没有结尾标记
cpp
#include <stdio.h>
#include <string.h>
int main() {
char dest[20];
const char* src = "Hello, World!";
size_t n = 5;
printf("源字符串: %s\n", src);
printf("复制的字符数: %zu\n", n);
strncpy(dest, src, n);
dest[n] = '\0'; // 添加结尾标记
printf("目标字符串: %s\n", dest);
return 0;
}
模拟实现strncpy
cpp
#include <stdio.h>
char* my_strncpy(char* dest, const char* src, size_t n) {
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++) {
dest[i] = src[i];
}
for ( ; i < n; i++) {
dest[i] = '\0'; // 如果源字符串长度小于 n,则用空字符填充
}
return dest;
}
int main() {
char dest[20];
const char* src = "Hello, World!";
size_t n = 5;
printf("源字符串: %s\n", src);
printf("复制的字符数: %zu\n", n);
my_strncpy(dest, src, n);
printf("目标字符串: %s\n", dest);
return 0;
}
strncat
char * strncat ( char * dest , const char * src , size_t n );
strncat
用于将指定长度的字符串拼接(追加)到目标字符串的末尾。
参数说明:
dest
:目标字符串,要将源字符串拼接到其末尾的字符串。src
:源字符串,要拼接到目标字符串末尾的字符串。n
:要拼接的最大字符数,即src
中要拷贝的字符数。
strncat
函数的作用是将 src
指向的字符串的前 n
个字符(如果 src
的长度小于 n
则拷贝整个字符串)追加到 dest
指向的字符串的末尾,并在目标字符串的末尾添加字符串结尾标志 \0
。
该函数会返回指向目标字符串 dest
的指针,即拼接后的字符串的起始地址。
需要注意的是,目标字符串 dest
必须有足够的空间来容纳源字符串 src
的字符。否则,会导致缓冲区溢出和未定义的行为。
同时,strncat
不会检查源字符串 src
是否符合 C 字符串的规范(即是否以 \0
结尾),因此要确保源字符串 src
以 \0
结尾,以避免结果不符合预期。
示例
在这个示例中,我们通过 strncat
函数将源字符串 src
的前 7 个字符拼接到目标字符串 dest
的末尾。输出中的最后一行显示了拼接后的字符串 dest
。由于目标字符串 dest
的长度限制在 20 个字符,所以只有部分字符被拼接进去,因此输出结果是 "Hello, Wo"。
cpp
#include <stdio.h>
#include <string.h>
int main() {
char dest[20] = "Hello";
const char* src = ", World!";
size_t n = 7;
printf("目标字符串: %s\n", dest); // 目标字符串: Hello
printf("源字符串: %s\n", src); // 源字符串: , World!
printf("拼接的字符数: %zu\n", n); // 拼接的字符数: 7
strncat(dest, src, n);
printf("拼接后的字符串: %s\n", dest); // 拼接后的字符串: Hello, Wo
return 0;
}
模拟实现strncat
cpp
#include <stdio.h>
char* strncat_sim(char* dest, const char* src, size_t n) {
char* dest_start = dest; // 保存目标字符串的起始位置
// 遍历目标字符串,直到达到结尾
while (*dest != '\0') {
dest++;
}
// 将源字符串中的字符逐个拼接到目标字符串中,直到达到指定的字符数 n 或源字符串结尾
while (n > 0 && *src != '\0') {
*dest = *src;
dest++;
src++;
n--;
}
*dest = '\0'; // 添加结尾标记
return dest_start; // 返回目标字符串的起始位置
}
int main() {
char dest[20] = "Hello";
const char* src = ", World!";
size_t n = 7;
printf("目标字符串: %s\n", dest); // 目标字符串: Hello
printf("源字符串: %s\n", src); // 源字符串: , World!
printf("拼接的字符数: %zu\n", n); // 拼接的字符数: 7
strncat_sim(dest, src, n);
printf("拼接后的字符串: %s\n", dest); // 拼接后的字符串: Hello, Wo
return 0;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
- 比较字符串: 函数可以比较两个字符串的前n个字符,n由调用函数时指定。
- 返回值: 如果
s1
小于s2
,函数返回一个负值;如果s1
大于s2
,函数返回一个正值;如果两个字符串在前n个字符内相等,函数返回0。 - 字符串结束判断: 与标准库中的
strncmp
类似,如果某个字符串的前n个字符中包含了'\0'
(即字符串结束符),则仅比较到该结束符为止。
示例
cpp
#include <stdio.h>
#include <string.h>
int main() {
const char* str1 = "Hello";
const char* str2 = "Hell";
int n = 4;
int result = strncmp(str1, str2, n);
if (result == 0) {
printf("两个字符串相等\n");
} else if (result < 0) {
printf("str1 小于 str2\n");
} else {
printf("str1 大于 str2\n"); // str1 大于 str2
}
return 0;
}
模拟实现strncmp
cpp
#include <stdio.h>
int custom_strncmp(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; i++) {
if (s1[i] != s2[i]) {
return (s1[i] - s2[i]);
}
if (s1[i] == '\0') {
return 0; // 达到了字符串结尾
}
}
return 0; // 前 n 个字符均相同
}
int main() {
const char *s1 = "Hello";
const char *s2 = "Hell";
int result = custom_strncmp(s1, s2, 4);
if (result < 0) {
printf("s1 小于 s2\n");
} else if (result > 0) {
printf("s1 大于 s2\n"); // s1 大于 s2
} else {
printf("s1 等于 s2\n");
}
return 0;
}
字符串查找
strstr
查找小串在大串是否出现,返回出现小串往后的字符
char* strstr(const char* haystack, const char* needle);
- 主要用途:strstr() 函数经常用于在字符串中查找子串,例如查找某个单词在文本中的位置。
- 区分大小写:strstr() 是区分大小写的,即输入的字符串要求大小写完全匹配。
- 返回的指针:如果找到了 needle 字符串在 haystack 中的位置,返回的指针指向首次出现的子串;如果未找到,返回 NULL。
示例
cpp
char email[] = "zpw@example.com.demo";
char substr[] = "example.com";
char *res = strstr(email, substr);
if (res == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s", res); // example.com.demo
}
模拟实现strstr
cpp
char *my_strstr(const char *str1, const char *str2)
{
assert(str1 && str2);
const char *s1 = str1; // 负责找大串
const char *s2 = str2; // 负责找小串
const char *p = str1; // 每次大串的起始点
while (*p)
{
s1 = p;
s2 = str2;
/* 大小串都没结束,并且当前大小串的字符相等则进入 */
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
/* 如果是因为 小串结束没有再次进到上面循环,那么说明大串中成功找到小串 */
if (*s2 == '\0')
{
return (char *)p;
}
/* 大串结束了,或者大小串当前字符不相等都会走到这里,则继续++大串的起始查找点,开始下一轮 */
p++;
}
return NULL;
}
char email[] = "zpw@example.com.demo";
char substr[] = "example.com";
char *p = my_strstr(email, substr);
printf("%s\n", p); // example.com.demo
strtok
分割字符串
char * strtok ( char * str, const char * sep );
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
示例
cpp
const char *sep = "@.";
char eml[] = "zhanghai@bitejiuyeke.com.net";
char cp[40] = {0};
strcpy(cp, eml);
char *ret = NULL;
for (ret = strtok(cp, sep); ret != NULL; ret = strtok(NULL, sep))
{
/*
zhanghai
bitejiuyeke
com
net
*/
printf("%s\n", ret);
}
模拟实现strtok
cpp
#include <stdio.h>
#include <string.h>
char* custom_strtok(char* str, const char* delim) {
static char* remaining = NULL;
if (str != NULL) {
remaining = str;
}
// 跳过开头的分隔符
while (*remaining != '\0' && strchr(delim, *remaining) != NULL) {
remaining++;
}
if (*remaining == '\0') {
return NULL;
}
char* token = remaining;
remaining = strpbrk(remaining, delim);
if (remaining != NULL) {
*remaining = '\0';
remaining++;
}
return token;
}
int main() {
char str[] = "Hello World! This is a test.";
char delim[] = " ";
char* token = custom_strtok(str, delim);
while (token != NULL) {
/*
Hello
World!
This
is
a
test.
*/
printf("%s\n", token);
token = custom_strtok(NULL, delim);
}
return 0;
}
错误信息报告
strerror
char * strerror ( int errnum );
示例
在这个示例中,我们尝试打开一个不存在的文件。由于文件不存在,fopen
函数将返回NULL
。然后,我们使用errno
变量获取最近一次错误的错误码,传递给strerror
函数。strerror
函数将错误码转换为对应的错误信息字符串。
在这里,strerror(errno)
将返回"No such file or directory ",因为我们尝试打开一个不存在的文件。我们通过printf
函数将错误信息打印到控制台上。
cpp
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
FILE* file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
printf("Failed to open file: %s\n", strerror(errno));
}
return 0;
}