位置:首页 > C > C语言基础:字符与字符串函数详解及模拟实现

C语言基础:字符与字符串函数详解及模拟实现

时间:2026-08-27  |  作者:实验室老王  |  阅读:0

目录

  1. 一、字符函数
  2. 1. 字符分类函数
  3. 2. 字符转化函数
  4. 二、字符串函数
  5. 1. strlen函数的使用和模拟实现
  6. strlen函数的使用
字符分类函数 对应的技术说明图
字符分类函数概括字符分类函数的核心概念、关键要点与实践提示。
一、字符函数 对应的技术说明图
一、字符函数概括一、字符函数的核心概念、关键要点与实践提示。

前言

本文深入解析C语言中字符与字符串处理的核心函数。首先介绍ctype.h头文件下的字符分类与转换机制,通过islower、tolower等实例演示大小写转换逻辑。随后重点剖析string.h中的strlen函数,明确其以空字符为结束标志的特性及无符号返回值易错点,并详细展示strlen与strcpy函数的实际使用方法及底层模拟实现代码,帮助读者夯实C语言基础编程能力。

C语言基础:字符与字符串函数详解及模拟实现 的核心流程信息图
C语言基础:字符与字符串函数详解及模拟实现用简体中文信息图概括C语言基础:字符与字符串函数详解及模拟实现的核心流程、关键规则与实践要点。

一、字符函数

1. 字符分类函数

C语言中有一系列的函数是对字符进行分类的,就是对判断一个字符属于什么类型的字符,这类字符函数的使用都要包含一个头文件ctype.h

这些函数的使用方法非常类似,这里我们就只举一个例子。

 int islower ( int c );

在C语言中,islower是一个用于判断字符是否为小写字母的函数。该函数接受一个整数参数c,它应该是无符号字符或EOF(常量)。如果参数c是小写字母,则返回非零值(真);否则返回0(假)。

【示例】将字符串中的小写字母转大写,其他字符不变。

#include
#include
int main()
{
	char str[] = "Test String.n";
	int i = 0;
	char c;
	while (str[i])
	{
		c = str[i];
		if (islower(c))
			c -= 32;  // 小写字母的ASCII码值减去32就等于它对应的大写字母的ASCII码
		putchar(c);
		i++;
	}
	return 0;
}

2. 字符转化函数

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

int tolower ( int c ); //将参数传进去的写字转写 
int toupper ( int c ); //将参数传进去的写字转写

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

#include
#include
int main()
{
	char str[] = "Test String.n";
	int i = 0;
	char c;
	while (str[i])
	{
		c = str[i];
		if (islower(c))
			c = toupper(c);
		putchar(c);
		i++;
	}
	return 0;
}

二、字符串函数

1. strlen函数的使用和模拟实现

函数原型:

size_t strlen ( const char * str );
  • 字符串以 '' 作为结束标志,strlen函数返回的是在字符串中 '' 前出现的字符个数(不包含 '' )。
  • 参数指向的字符串必须要以 '' 结束。
  • 注意函数的返回值为 size_t,是无符号的( 易错 )
  • strlen的使用需要包含头文件
  • 学会strlen函数的模拟实现

strlen函数的使用

计算字符串的长度

#include
#include
int main()
{
	char str1[] = "abcdef";
	size_t len = strlen(str1);
	printf("%zun", len);
	return 0;
}

strlen函数的模拟实现

方法一:计数器的方式实现

#include
#include
int my_strlen(const char* str)  // const修饰,使其不能被修改
{
	int count = 0;
	assert(str);  // 断言,避免传入空指针
	while (*str)
	{
		count++;  // 进入循环,说明不为空
		str++;
	}
	return count;
}
int main()
{
	char str1[] = "abcdef";
	int len = my_strlen(str1);
	printf("%dn", len);
	return 0;
}

方法二:递归实现

#include
#include
int my_strlen(const char* str1)
{
	assert(str1);   // 断言,避免传入空指针
	if (*str1 == '')
		return 0;  // 等于'',说明字符串结束,直接返回
	else
		return 1 + my_strlen(str1 + 1);
}
int main()
{
	char str1[] = "abcdef";
	int len = my_strlen(str1);
	printf("%dn", len);
	return 0;
}

方法三:指针 - 指针的方式实现

#include
int my_strlen(char* s)
{
	char* p = s;
	while (*p != '')
		p++;
	return p - s;
}
int main()
{
	int len = my_strlen("abcdef");
	printf("%dn", len);
	return 0;
}

2. strcpy函数的使用和模拟实现

函数原型:

char* strcpy(char * destination, const char * source );

将source指向的C字符串复制到destination指向的数组中,包括结束的null字符(并在该点停止)。

strcpy函数的使用

strcpy函数的使用

将str1中的内容拷贝到str2中去

#include
#include
int main()
{
	char str1[] = "hello world";
	char str2[20] = { 0 };
	strcpy(str2, str1);  // 将str1中的内容拷贝到str2中去
	printf("%sn", str2);
	return 0;
}

注意:这里str2的空间必须得能够装下str1中的内容,也就是str2的空间要足够大

strcpy函数的模拟实现

在模拟实现之前,首先我们要了解strcpy的实现原理,只有这样才会更加方便我们去模拟实现。那么,strcpy的实现原理是怎样的呢? 这里我们根据上面的代码进行修改再调试一下:

#include
#include
int main()
{
	char str1[] = "hello world";
	char str2[20] = "xxxxxxxxxxxxxxxxxx";
	strcpy(str2, str1);
	printf("%sn", str2);
	return 0;
}

str1加上空格和字符串的结束标志 '' 一共有12个字符,如果在str2中第12(下标为11)个字符也变成了 '',那就说明是把str1中的 '' 搬到了str2中。 事实证明strcpy的确是这样实现字符串拷贝的,所以我们在模拟实现时要一直将字符串拿到 '' 才能结束。 注意

  • 源字符串必须以 '' 结束。
  • 会将源字符串中的 '' 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可修改。

接下来我们来一步一步模拟strcpy函数

void my_strcpy(char* dest, char* src)
{
	while (*src != '')  // 拷贝''之前的内容
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;  // 拷贝''
}

这样其实也能模拟实现,但这样的代码明显还有很多缺陷,还有很多优化的空间。

char* my_strcpy(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = dest;
	while (*dest++ = *src++)
		;
	return ret;
}

这是最终优化后的代码,大家看到这里可能会有点懵,别急,我们慢慢来:

3. strcat函数的使用和模拟实现

函数原型:

char * strcat ( char * destination, const char * source );

连接字符串。该函数将源字符串的副本追加到目标字符串中。具体而言,目标字符串中的结束null字符会被源字符串的第一个字符覆盖,并且在目标字符串中由两者串联形成的新字符串的末尾包含一个空字符。

  • 源字符串必须以 '' 结束。
  • 目标字符串中也得有 '',否则没办法知道追加从哪里开始。
  • 目标空间必须有足够的大小,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 字符串自己给自己追加,如何?

strcat函数的使用

将arr2中的字符串追加到arr1后面去。

#include
#include
int main()
{
	// 注意数组空间大小,要足以容纳追加后的字符数量
	char arr1[20] = "hello ";  
	char arr2[] = "world";
	strcat(arr1, arr2);
	printf("%sn", arr1);
	return 0;
}

注意:这里arr1的空间必须得能够装下arr2追加到arr1后的内容,也就是arr1的空间要足够大。

strcat函数的模拟实现

  1. 首先,为了确保安全,我们需要判断传入的dest和src是否为空指针。因此,这里必须使用断言进行校验,一旦它们为空指针,程序将直接报错终止。
  2. 其次,为了确保源字符串src不被意外修改,可以使用const关键字对其进行修饰。在while循环中,表达式*dest++ = *src++作为判断条件。这里需要注意,后置++的优先级高于*,但因为是后置自增,所以是先使用当前值再自增,即先解引用赋值,然后指针后移。
  3. 第一次判断会将src中的第一个字符赋值给dest。由于while循环体内是空语句,执行后不会有任何额外效果,程序就这样一直循环,将src中的字符逐个复制到dest中,直到遇到''并赋值给dest。此时,while循环括号内的表达式值为0,跳出循环。注意,src中的''也被完整地复制到了dest中。
  4. 原strcat函数的返回值类型是char *,为了模拟实现的一致性,我们也将其改为char *类型。原本我们需要返回dest,但由于在while循环中dest已经经过后置++操作,不再指向首地址。因此,在循环开始前,我们需要用一个指针ret来保存dest的首地址,最后直接返回ret即可。

在模拟实现 strcat 函数之前,我们需要深入理解其底层实现原理。通过调试观察可以发现,字符串追加操作是从目标字符串 arr1 中的结束符 处开始的。值得注意的是,源字符串 arr2 中的结束符 并不会被拷贝到目标字符串中,追加的内容直接覆盖了该位置。

#include
#include
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);  // 断言判断传入的是否为空指针
	char* ret = dest;  // 记录dest的起始地址
	// 找到目标空间的
	while (*dest != '')
		dest++;
	// 拷贝追加
	while (*dest++ = *src++)
		;
	return ret;
}
int main()
{
	// 注意数组空间大小,要足以容纳追加后的字符数量
	char arr1[20] = "hello ";  
	char arr2[] = "world";
	// my_strcat(arr1, arr2);
	char* ret = my_strcat(arr1, arr2);
	printf("%sn", arr1);
	printf("%sn", ret);
	return 0;
}

基于上述调试结果,我们可以明确 strcat 的核心逻辑:被追加的字符串从目标字符串的 处开始写入,但源字符串末尾的 不会被包含在追加过程中。为了实现这一功能,我们需要遵循以下步骤进行模拟:

  1. 首先,必须对传入的指针进行合法性检查。使用断言确保指针不为空,同时为了防止追加源字符串被意外修改,应使用 const 关键字修饰源字符串指针。
  2. 由于追加操作始于目标字符串的末尾,因此在执行追加前,需要将指针移动至字符串结束符 处。可以通过 while 循环判断,只要当前字符不是 ,指针就向后移动一位,直到指向字符串末尾。
  3. 接下来的逻辑与 strcpy 函数类似。在 while 循环的条件判断中执行 *dest++ = *src++。只要源字符串指针指向的字符不是 ,该表达式的结果就不为 0,循环将继续执行,直到遇到 为止。
  4. strcat 函数的原型返回值为 char * 类型。因此,我们的模拟实现也需返回 char * 类型。需要注意的是,返回值应为被追加字符串的起始地址。由于在追加过程中指针已向后偏移,不再指向起始位置,因此需要创建一个临时指针变量来记录起始地址,并在函数结束时返回该变量。

4. strcmp函数的使用和模拟实现

函数原型如下:

int strcmp ( const char * str1, const char * str2 );

该函数用于比较两个字符串。它执行的是字符的二进制比较。比较过程从每个字符串的第一个字符开始,如果字符相等,则继续比较后续字符对,直到发现字符不同或遇到终止空字符为止。

  • 标准规定: 若第一个字符串大于第二个字符串,则返回大于 0 的数字。 若两个字符串相等,则返回 0。 若第一个字符串小于第二个字符串,则返回小于 0 的数字。 判断依据是比较两个字符串中对应位置上字符的 ASCII 码值大小。

strcmp函数的使用

比较三个字符串

可以看到,标准里面的返回值是一个大于或小于0的数,但VS的编译器直接定为1和-1,其他编译器可能是返回一个大于0或小于0的数。

strcmp函数的模拟实现

模拟后发现结果是一样的。

  1. 还是和上面一样,因为函数中我们只是比较字符串,不需要进行修改,所以要对其进行const修饰,而且为了避免传入空指针,要对其进行断言处理。
  2. while循环中进行条件判断,相等就进入循环,并自增,不相等跳出循环,跳出循环后又分两种情况,一种是 *str1 > *str2,直接返回1,*str1 < *str2,直接返回-1。
  3. 相等的情况只可能出现在while循环中,因为不相等就直接跳出循环了,一旦当 *str1 == ,也就说明 *str2也等于了,直接返回0就行了。

这只是在模拟VS编译器里的结果,模拟其他编译器上的结果更加简单,不相等时直接返回他们对应的ASCII码的差值就行了。

#include
#include
#include
char* my_strcpy(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = dest;
	while (*dest++ = *src++)
		;
	return ret;
}
int main()
{
	char str1[] = "hello world";
	char str2[20] = "xxxxxxxxxxxxxxxxxx";
	my_strcpy(str2, str1);
	printf("%sn", str2);
	char * ret = my_strcpy(str2, str1);
	printf("%sn", ret);
	return 0;
}
#include
#include
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abd";
	char arr3[] = "abcdef";
	int ret1 = strcmp(arr1, arr2);
	int ret2 = strcmp(arr1, arr3);
	int ret3 = strcmp(arr2, arr3);
	printf("%dn", ret1);
	printf("%dn", ret2);
	printf("%dn", ret3);
	return 0;
}
#include
#include
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '')
			return 0;
		str1++;
		str2++;
	}
	if (*str1 > *str2)
		return 1;
	else
		return -1;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abd";
	char arr3[] = "abcdef";
	int ret1 = my_strcmp(arr1, arr2);
	int ret2 = my_strcmp(arr1, arr3);
	int ret3 = my_strcmp(arr2, arr3);
	printf("%dn", ret1);
	printf("%dn", ret2);
	printf("%dn", ret3);
	return 0;
}
#include
#include
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;

}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abs";
	char arr3[] = "abcdef";
	int ret1 = my_strcmp(arr1, arr2);
	int ret2 = my_strcmp(arr1, arr3);
	int ret3 = my_strcmp(arr2, arr3);
	printf("%dn", ret1);
	printf("%dn", ret2);
	printf("%dn", ret3);
	return 0;
}
注意

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多