字符函数和字符串函数

发布于:2025-07-04 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

1. 字符分类函数

2. 字符转换函数

3. strlen的使用和模拟实现

4. strcpy的使用和模拟实现

5. strcat的使用和模拟实现

6. strcmp的使用和模拟实现

7. strncpy函数的使用

8. strncat函数的使用

9. strncmp函数的使用

10. strstr的使用和模拟实现

11. strtok函数的使用和模拟实现

12. strerror函数的使用和模拟实现


在编程的过程中,我们经常要处理字符和字符串,为了方便操作字符和字符串,C语言标准库中提供了⼀系列库函数,接下来我们就学习⼀下这些函数。

1. 字符分类函数

C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使用都需要包含⼀个头文件是 ctype.h

这些函数的使用方法大相径庭,今天就举⼀个函数的例子,其他的非常类似:

islower 是能够判断参数部分的 c 是否是小写字母的。这个函数通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回 0

接下来我们用小写字母转换为大写字母这个例子练一下手~

int main()
{
	char ch1[] = "hello world";
	char ch2[20] = { 0 };
	int i = 0;
	int len = strlen(ch1);
	for (i = 0; i < len; i++)
	{
		if (islower(ch1[i])) // 判断是不是小写字符,若是则返回非0数,若不是则返回0
		{
			ch2[i] = ch1[i] - 32;// 小写字符比大写字符的ASCII值大32
		}
		else
		{
			ch2[i] = ch1[i];// 若不是小写字符则直接复制即可
		}
	}
	ch2[i] = '\0';// 结尾添加'\0'保证结束
	printf("%s\n", ch2);
	return 0;
}

2. 字符转换函数

C语言提供了2个字符转换函数:

上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用 tolower 函 数。

我们改造一下:

#include <stdio.h>
#include<ctype.h>

int main()
{
	char ch1[] = "hello world";
	char ch2[20] = { 0 };
	int i = 0;
	int len = strlen(ch1);
	for (i = 0; i < len; i++)
	{
		ch2[i] = toupper(ch1[i]);
	}
	ch2[i] = '\0';
	printf("%s\n", ch2);
	return 0;
}

3. strlen的使用和模拟实现

以下有几点注意事项

1.字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。

2.参数指向的字符串必须要以 '\0' 结束。

3.注意函数的返回值为size_t,是无符号的( 易错 )

4.strlen的使用需要包含头文件(string.h) 

3.1 strlen的使用

#include <stdio.h>
#include<string.h>

int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

嗯?怎么会是这个结果呢?明明是str1更长。大家可以思考一下原因。

其实问题就出在这条上。哈哈,大家是不是已经踩坑了。

所以我们得修改一下让它可以返回负数:

#include <stdio.h>
#include<string.h>

int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if ((int)strlen(str2) - (int)strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

直接强制转换为整形,以保证有负数的返回。

现在就对了:

3.2 strlen的模拟实现

我列举了三种模拟实现的方法,代码如下:

3.2.1 计数器实现

int my_strlen1(char* c)// 计数器方式
{
	assert(c);
	int count = 0;
	while (*c)
	{
		count++;
		c++;
	}
	return count;
}

int main()
{
    char ch[] = "hello world";
	int ret1 = my_strlen1(ch);
	printf("%d\n", ret1);
}

3.2.2 递归实现

int my_strlen2(char* c)// 递归
{
	assert(c);
	if (*c == '\0')
	{
		return 0;
	}
	else
	{
		return 1 + my_strlen2(c + 1);
	}
}

int main()
{
    char ch[] = "hello world";
	int ret2 = my_strlen2(ch);
	printf("%d\n", ret2);
}

3.2.3 指针偏移量实现

int my_strlen3(char* c)// 通过指针的偏移量进行判断
{
	assert(c);
	char* str = c;
	while (*c)
	{
		c++;
	}
	return (c - str);

}

int main()
{
    char ch[] = "hello world";
	int ret3 = my_strlen3(ch);
	printf("%d\n", ret3);
}

4. strcpy的使用和模拟实现

以下有几点注意事项

1.源字符串必须以 '\0' 结束。

2. 会将源字符串中的 '\0' 拷贝到目标空间。

3.目标空间必须足够大,以确保能存放源字符串。

4. 目标空间必须可修改。

4.1 strcpy的使用

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

上述代码实现的是通过strcpy这个函数将arr1中的字符拷贝到arr2上,可以看到我设置的arr2的空间大小是足够大的。

4.2 strcpy的模拟实现

#include <stdio.h>
#include <assert.h>

char* my_strcpy(char* dest, const char* sorc)
{
	char* ret = dest;
	assert(dest && sorc);
	while (*(dest++) = *(sorc++))
	{
		;
	}
	return ret;

}


int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

5. strcmp的使用和模拟实现

标准规定如下:

1.第⼀个字符串大于第二个字符串,则返回大于0的数字

2.第⼀个字符串等于第二个字符串,则返回0

3. 第⼀个字符串小于第二个字符串,则返回小于0的数字

4.那么如何判断两个字符串? 比较两个字符串中对应位置上字符ASCII码值的大小。

5.1 strcmp的使用

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "hello";
	char arr2[] = "world";
	int ret = strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf("arr1 > arr2\n");
	}
	else if (ret < 0)
	{
		printf("arr1 < arr2\n");
	}
	else
	{
		printf("arr1 = arr2\n");
	}
	return 0;
}

5.2 strcmp的模拟实现

#include <stdio.h>
#include <assert.h>

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1++ == *str2++)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;
}

int main()
{
	char arr1[] = "hello";
	char arr2[] = "world";
	int ret = my_strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf("arr1 > arr2\n");
	}
	else if (ret < 0)
	{
		printf("arr1 < arr2\n");
	}
	else
	{
		printf("arr1 = arr2\n");
	}
	return 0;
}

6. strcat的使用和模拟实现

注意事项:

1.源字符串必须以 '\0' 结束。

2.目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。

3.目标空间必须有足够的大,能容纳下源字符串的内容。

4.目标空间必须可修改

6.1 strcat的使用

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[20] = "hello";
	char arr2[] = " world";
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

6.2 strcat的模拟实现

#include <stdio.h>
#include <assert.h>

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)// 使其移到'\0'
	{
		*dest++;
	}
	while (*dest++ = *src++)// 复制
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "hello";
	char arr2[] = " world";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

7. strncat函数的使用

注意事项:

1. 将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符。

2.如果source指向的字符串的长度小于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾。

7.1 strncat的使用

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[20] = "hello";
	char arr2[] = " world";
	strncat(arr1, arr2,6);
	printf("%s\n", arr1);
	return 0;
}

注:6是因为有个空格要算

7.2 strncat的模拟实现

#include <stdio.h>
#include <assert.h>

char* my_strncat(char* dest, const char* src,size_t num)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)// 使其移到'\0'
	{
		*dest++;
	}
	int i = 0;
	for (i = 0; i < num; i++)// 根据指定长度进行复制
	{
		*dest++ = *(src + i);
	}
	*dest = '\0';// 结尾追加'\0'
	return ret;
}

int main()
{
	char arr1[20] = "hello";
	char arr2[] = " world";
	my_strncat(arr1, arr2, 6);
	printf("%s\n", arr1);
	return 0;
}

8. strncpy函数的使用和模拟实现

 

注意事项:

1. 拷贝num个字符从源字符串到目标空间

2.如果源字符串的长度小于num,则拷贝完源字符串之后,在⽬标的后边追加0,直到num个。

8.1 strncpy的使用

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	strncpy(arr2, arr1,11);
	printf("%s\n", arr2);
	return 0;
}

8.2 strncpy的模拟实现

#include <stdio.h>
#include <assert.h>

char* my_strncpy(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;
	int i = 0;
	for (i = 0; i < num; i++)
	{
		*dest++ = *(src + i);
	}
	dest = '\0';
	return ret;

}

int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	my_strncpy(arr2, arr1, 11);
	printf("%s\n", arr2);
	return 0;
}

9. strncmp函数的使用

比较方法:

比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不一样,就提前结束,大的字符所在的字符串大于另外⼀个。如果num个字符都相等,就是相等返回0

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "hello world";
	char arr2[] = "hello moon";
	int ret = strncmp(arr1, arr2, 7);
	if (ret < 0)
	{
		printf("arr1 < arr2\n");
	}
	else if (ret > 0)
	{
		printf("arr1 > arr2\n");
	}
	else
	{
		printf("arr1 = arr2\n");
	}
	return 0;
}

10. strstr的使用和模拟实现

注意事项:

1.函数返回字符串str2在字符串str1中第一次出现的位置

2.字符串的比较匹配不包含 \0 字符,以 \0 作为结束标志

10.1 strstr的使用

#include <stdio.h>
#include <string.h>

int main()
{
	char str[] = "This is a simple string";
	char* pch;
	pch = strstr(str, "simple");
	if (pch == NULL)
	{
		printf("这个字符不存在\n");
	}
	else
	{
		printf("%c\n", *pch);
	}
	return 0;
}

10.2 strstr的模拟实现

#include <stdio.h>
#include <assert.h>

const char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	
	if (*str2 == '\0')
	{
		return str1;
	}

	char* s1 = str1;
	char* s2 = str2;
	char* cp = str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (s1 != '\0' && s2 != '\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	return NULL;
}


int main()
{
	char str[] = "This is a simple string";
	char* pch;
	pch = my_strstr(str, "simple");
	if (pch == NULL)
	{
		printf("这个字符不存在\n");
	}
	else
	{
		printf("%c\n", *pch);
	}
	return 0;
}

11. strtok函数的使用

注意事项:

1.sep参数指向⼀个字符串,定义了用作分隔符的字符集合

2.第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标 记。

3. strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串⼀般都是临时拷贝的内容并且 可修改。)

4. strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。

5.strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标 记。

6. 如果字符串中不存在更多的标记,则返回 NULL 指针。

代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
	char arr[] = "192.168.6.111";
	char* sep = ".";
	char* str = NULL;
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s\n", str);
	}
	return 0;
}

strtok(arr,sep)使用后,原字符串变成"192'\0'168'\0'6'\0'111 "。

strtok(arr,sep)会从'\0'位置开始向后标记。

12. strerror函数的使用

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来

在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明 的,C语言程序启动的时候就会使用⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。

#include <errno.h>
#include <string.h>
#include <stdio.h>

int main()
{
 int i = 0;
 for (i = 0; i <= 10; i++) {
 printf("%s\n", strerror(i));
 }
 return 0;
}

在Windows11+VS2022环境下输出的结果如下:

举例:

输出:

也可以了解⼀下perror函数,perror函数相当于⼀次将上述代码中的第9行完成了,直接将错误信息 打印出来。perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。

输出:

到这里文章就结束咯,感谢大家的阅读~


网站公告

今日签到

点亮在社区的每一天
去签到