(C语言)字符函数和字符串函数(超级详解)

目录

一:字符串函数:

1.strlen函数

模拟strlen函数

2.strcpy函数

3.strcat函数

4.strcmp函数

5.strncpy函数

6.strncat函数

7.strncmp函数

8.strstr函数

9.strtok函数

10.strerror

二:字符函数

1.字符分类函数

 2.字符转换函数


开门见山,直接进入讲解。

一:字符串函数:

字符串函数有:

strcpy            strcat            strcmp         

strncpy          strncat          strncmp        //第二行的函数近比第一行的函数都多加一个n,它们                                                                   的使用方法也相似

strlen             strstr             strtok          strerror

1.strlen函数

函数原型:size_t strlen(const char *str);

头文件:string.h

功能:计算给定字符串(const char *str)的长度,不包括'\0'在内。

返回值:返回字符串的长度,返回值为size_t类型

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
   char arr[]="abcdef";//创建字符串arr
   printf("%d",strlen(arr));//打印arr的长度

   return 0;
}

接下来我们来尝试模拟strlen的实现,来增强我们对函数的掌握。

模拟strlen函数

可以用三种方式来模拟实现strlen函数。

第一种方法:计数器方式

1.计数器方式
int my_strlen(const char* arr)
{
   assert(arr);//判断arr是否为野指针
   int count=0;//创建变量count来计数
   while (*arr++)//当字符串循环到'\0'时停下来,此时count就是字符串的长度
   {
	 count++;
   } 
   return count;//返回count的值
}
int main()
{
	char arr[] = "abcdefghijk";//创建字符串arr
	int ret=my_strlen(arr);//创建一个函数,参数为字符串首地址,返回值为int
	printf("%d", ret);
	return 0;
}

第二种方法:递归方式(不会递归的话可以不选择这种方式)

int my_strlen(char* arr)
{
   assert(arr);
   if (*arr == '\0')
   {
	return 0;
   }
    else
	return 1 + my_strlen(arr + 1);
}
int main()
{
	char arr[] = "abcdefghijk";
	int ret=my_strlen(arr);
	printf("%d", ret);
	return 0;
}

第三种方法:指针减去指针的方式

int my_strlen(char* arr)
{
    assert(arr);
	char* pt = arr;
	while (*arr++)//当循环到'\0'时停止,此时的arr指向的是'\0'的下一位
		;	
    return arr-1 - pt;//因此应该先减去1后再减去首地址,得到的字符尾部相对于字符首地址的偏移量。
}
int main()
{
	char arr[] = "abcdefghijk";
	int ret=my_strlen(arr);
	printf("%d", ret);
	return 0;
}

当然,不管这三种用哪种方式,最终程序运行的结果都会是:

strlen函数讲解结束。

2.strcpy函数

函数原型:char *strcpy(char* dest, const char *src);

头文件:#include <string.h

功能:把从src地址开始且含有结束符的字符串复制到以dest指向的地址空间

返回值:字符串dest的地址

注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

返回指向dest的指针

代码示例:

#include<stdio.h>
#include<string.h>
//strcpy使用
  int main()
{
	char arr1[20] = "abcdefg";
	char arr2[] = "hijklm"; 
    strcpy(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

运行结果:

我们可以看到原先arr1中的字符串内容已经全部被 arr2所替换。

在知道了如何使用strcpy后,我们来尝试一下模拟strcpy函数功能的实现。

#include<stdio.h>
char* my_strcpy(char* arr1, char* arr2)
{
	char* pa = arr1;//把arr1的首地址存在pa中
	while (*arr1++ = *arr2++)当(*arr2)为'\0'时,赋给(*arr1)后循环会停止,此时arr1的长度和内容就 
                                                                       和arr2一样了。
		;
	return pa;//返回pa(arr1)的地址
}
int main()
{
	char arr1[20]="xxxxxxxxxxxx";
	char arr2[] = "abcdefg";
	char*p=my_strcpy(arr1, arr2);
	printf("%s", p);//打印被覆盖后的字符串arr1

	return 0;
}

运行结果:

strcpy函数的讲解结束。

3.strcat函数

函数原型:extern char *strcat(char *dest, const char *src);

头文件:string.h

功能:把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”)。*src中原有的字符不变。返回指向dest的指针。

返回值:指向字符串dest地址的指针

注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abcdefg";
	char arr2[] = "hijklmn";
	strcat(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

运行结果:

在知道strcat函数如何使用后,我们来尝试模拟strcat函数功能的实现。

#include<stdio.h>
char* my_strcat(char* arr1, char* arr2)
{
	char* pa = arr1;
	while (*++arr1)//当*arr1为'\0'时循环停止
		;
	while (*arr1++ = *arr2++)//用循环把*arr2的值一个个赋给*arr1,直到*arr2为'\0'时停止循环
		;
	return pa;
}
int main()
{
	char arr1[20] = "abcdefg";
	char arr2[] = "hijklmn";
	char* p = my_strcat(arr1, arr2);
	printf("%s", p);

	return 0;
}*/

运行结果:

 strcat函数讲解结束。

4.strcmp函数

函数原型:extern int strcmp(const char *s1,const char *s2);

头文件:string.h

功能:比较s1字符串和s2字符串,两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。

返回值:

当s1<s2时,返回为负数;

当s1=s2时,返回值为0;

当s1>s2时,返回正数。

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
  char arr[]="abcdef";
  char arr1[]="abcdes";
  int ret=strcmp(arr,arr1);
  if(ret>0)
  printf("arr>arr1");
  else if(arr<0)
  printf("arr<arr1");
  else
  printf("arr==arr1"); 

  return 0;
}

在这里不展示运行结果了,如果感兴趣可以自己尝试。

在了解strcmp如何使用后,我们可以尝试模拟strcmp的功能实现。

代码示例:

#include<stdio.h>
#include<assert.h>
int my_strcmp(char* arr1, char* arr2)
{
	assert(arr1 && arr2);//判断指针是否为野指针
	while (*arr1++ == *arr2++)//如果在循环过程中arr1!=arr2,则跳出循环执行return。
	{
		if (*arr1 == '\0')如果在循环过程中arr1为'\0',则arr2也为'\0',则直接返回0.
		{
			return 0;
		}
	}
	return *(arr1 - 1) - *(arr2 - 1);
}
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcd";
	int ret = my_strcmp(arr1, arr2);
	printf("%d", ret);

	return 0;
}

运行结果:

strcmp函数讲解结束。

5.strncpy函数

函数原型:char *strncpy(char *destinin, char *source, int n);

头文件:string.h

功能:把source指向的字符串的前n个字符(不包括\0,\0得自己手动加在*destin被复制之后)复制到destin指向的字符串中。如果要复制的*source的部分有\0,就把\0复制进去,之后就提前结束,即使没复制到第n个字符也是。

返回值:指向destin的地址的指针

注意: 如果复制source的n个字符不含NULL字符,则结果不会以NULL字符结束,会导致                   为乱码。因此,如果不考虑source串复制完整性,可以将destin 最后一字符置为'\0'。

           如果n > destin串长度,destin栈空间溢出产生崩溃异常。

综上,一般情况下,使用strncpy时,建议将n置为destin串长度,复制完毕后,为保险起见,将destin串最后一字符置NULL,避免发生输出乱码问题。当然喽,无论是strcpy还是strncpy,保证destin串容量(能容纳下source串)才是最重要的。

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "xxxxx";
	strncpy(arr1, arr2, 4);
	printf("%s", arr1);

	return 0;
}

运行结果:

在知道如何使用strncpy后,我们模拟一下strncpy函数的功能实现来加深理解。

char* my_strncpy(char* arr2, const char* arr1, int sz)
{
	char* pa = arr2;
	while (sz--)
	{
		*arr2++= *arr1++;
	}
	return pa;
}
int main()
{
	int sz = 0;
	char arr1[] = "abcdefghijk";
	char arr2[20] = { 0 };
	scanf("%d", &sz);
	char* p = my_strncpy(arr2, arr1, sz);
	printf("%s", p);

	return 0;
}

因为代码比较简单易懂,因此没有添加注释。strncpy函数讲解结束。

6.strncat函数

函数原型:char * strncat(char *dest, const char *src, size_t n);

头文件:string.h

功能:把src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的'\0',从而实现字符串的连接

返回值:指向dest的地址的指针

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[10] = "abcde";
	char arr2[] = "fgh";
	strncat(arr1, arr2, 2);
	printf("%s", arr1);

	return 0;
}

运行结果:

 学会如何使用strncat函数后,我们来尝试模拟实现strncat函数的功能。

代码示例:

char* my_strncat(char* arr1, const char* arr2, int sz)
{
	char* pa = arr1;
	while (*++arr1)//当arr1为'\0'时循环停止
		;
	while (sz--)
	{
		*arr1++ = *arr2++;//把arr2中sz个字符衔接到arr1的后面,覆盖住'\0'.
	}
	return pa;
}
int main()
{
	int a = 0;
	char arr1[20] = "abcde";
	char arr2[] = "fghijk";
	scanf("%d", &a);
	char* p = my_strncat(arr1, arr2, a);
	printf("%s\n", p);

	return 0;
}

运行结果:

strncat函数讲解结束。

7.strncmp函数

函数原型:int strncmp(const char *str1, const char *str2, size_t  n)

头文件:string.h

功能:用来比较s1和s2字符串的前n个字符。如果两个字符串相等的话,strncmp将返回0。如果s1是s2的一个子串的话,s1小于s2。

返回值:返回指向str1的地址

由于strcmp与strncmp的使用用法与模拟实现方法极其相似,只是多了选择比较字符数量的功能,因此,在此处不再详细讲解。

8.strstr函数

函数原型:extern char *strstr(char *str1, const char *str2);

头文件:string.h

功能:返回str1字符串中首次出现子串(str2)的地址。

返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[10] = "abcdefg";
	char arr2[] = "def";
	char* ret = strstr(arr1, arr2);
	printf("%s", ret);

	return 0;
}

运行结果:

接下来尝试模拟一下strstr函数功能的实现。

#include<stdio.h>
char* my_strstr(const char* arr1, const char* arr2)
{
	const char* s1 = NULL;//创建两个空指针变量s1、s2
	const char* s2 = NULL;
	const char* start = arr1;//把arr1的地址存在start中
	while (*start)
	{
		s1 = start;//再把start里存的地址赋给s1
		s2 = arr2;//把arr2的地址赋给s2
		while(*s1!='\0'&& *s1 == *s2)当循环停下时,说明*s1不等于*s2,或者*s1等于'\0'
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')此时判断s2是否等于'\0'
		{
			return (char*)start;//如果等于则返回此时start指向的arr1的地址
		}
		start++;如果不等于则start(arr1)++,继续判断
	}
	return NULL;当没有在arr1中找到arr2时,则返回NULL

}
int main()
{
	char arr1[] = "abcdefghk";
	char arr2[] = "cdefg";
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到");
	}
	else
	printf("%s", ret);

	return 0;
}

strstr的模拟有点困难,需要画图+看代码来理解。

9.strtok函数

函数原型:char *strtok(char*s, const char *delim);

解释:

头文件:string.h

功能:用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。

注意:

    例如:strtok(123,234,567",")

strtok()函数第一次调用需设置两个参数。第一次分割的结果,返回串中第一个 ',' 之前的字符串123,也就是上面的程序第一次输出123,再把标记设置为\0.

第二次调用该函数strtok(\0,","),返回第一个NULL后面且下一个','前的字符串234,然后再把第二个标记置为\0

一直调用到字符串中不存在更多的标记。因此想要彻底把字符串分割完需要多次调用strtok

返回值:

从s开头开始的一个个被分割的串。当s中的字符查找到末尾时,返回NULL。

如果查找不到delim中的字符时,返回当前strtok的字符串的指针。

所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。

代码示例:

#include<stdio.h>
#include<string.h>
int main()
{
	//strtok使用
	const char str[] = "aaa-bbb-ccc@";
	const char s[] = "-@";
	char* p = NULL;
	for (p = strtok(str, s); p != NULL; p = strtok(NULL, s))
	{
		printf("%s\n", p);
	}
    return 0;
}

10.strerror

函数原型:char * strerror ( int errnum );

errnum为错误码

头文件:string.h和errno.h

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

返回值:strerror函数就可以将错误对应的错误信息字符串的地址返回。

函数示例:

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

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

使用结果:

 至此,字符串函数全部讲解完毕。

二:字符函数

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

1.字符分类函数

 2.字符转换函数

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

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

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

我们可以联立字符分类函数和字符转换函数写一个代码:

#include<stdio.h>
#include<ctype.h>
int main()
{
	int i = 0;
	int j = 0;
	char arr[] = "abcdefg";
	char arr1[] = "JFDKSKJ";
	while ( arr[i])
	{
		if (islower(arr[i]))//判断是否为小写
		{
			int c = toupper(arr[i]);//利用toupper函数将小写转换为大写
			putchar(c);
		}
		i++;
	}
	printf("\n");
	while (arr1[j])
	{
		if (isupper(arr1[j]))//判断arr1是否为大写
		{
			int a = tolower(arr1[j]);//利用tolower函数将大写转换为小写
			putchar(a);
		}
		j++;
	}

	return 0;
}

运行结果:

由于字符函数太多且不复杂,在此就不把剩下的字符函数一个个代码举例了,大家可以自己去实践

至此,字符和字符串函数内容已经全部讲解结束。

制作不易,如果本章内容对你有所帮助的话不妨留个赞再走。

### C语言字符串插入字符函数 在C语言中,虽然标准库并未提供直接用于字符串插入函数,但可以通过自定义函数实现这一功能。下面展示如何创建一个名为`insert_char_at`的函数来实现在指定位置插入单个字符的功能。 此方法涉及分配新的内存空间以容纳修改后的字符串,并将原有内容复制到新地址,在目标索引处加入所需字符[^1]。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> char* insert_char_at(const char *original, int index, char ch) { size_t length = strlen(original); // 如果index超出范围,则默认插到最后 if (index > (int)length || index < 0){ index = length; } // 创建一个新的字符数组存储结果 char *result = malloc(length + 2); // 额外的空间给新增加的字符以及'\0' if (!result) return NULL; // 将原始字符串前半部分拷贝过来 strncpy(result, original, index); // 插入字符 result[index] = ch; // 继续拷贝剩余的部分并加上终止符 strcpy(&result[index + 1], &original[index]); return result; } // 测试代码 int main() { const char *test_str = "hello"; char new_ch = 'X'; int pos = 3; char *modified_string = insert_char_at(test_str, pos, new_ch); printf("Modified string is %s\n", modified_string ? modified_string : "(null)"); free(modified_string); // 记得释放动态分配的内存 return 0; } ``` 上述程序展示了如何在一个已存在的字符串中的特定位置插入另一个字符。需要注意的是,由于C语言处理字符串的方式是基于零结尾的字节数组,所以在操作过程中要特别小心越界访问等问题。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值