C -- string.h

本文深入解析C语言中的字符串处理函数,如查找、比较、复制、拼接等操作,通过实例展示memchr、strchr、strrchr、strstr、strspn、strcspn、strpbrk、strtok、memcmp、strcmp、strcpy、strcat、strerror、strlen等功能及使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c–string.h标准库:

在这里插入图片描述

字符串查找

void* memchr(const char* str,int c,size_t n);	//(没有memrchr)在str的前n个字节中  搜索第一次出现c 的位置(c为无符号字符)
char* strchr(const char* str, int c);		//搜素 在str中第一次出现c的位置(c为无符号字符)
char* strrchr(const char* str, int c);		//搜素 在str中最后一次出现c的位置(c为无符号字符)
char* strstr(const char* str1,const char* str2);	//在str1中查找第一次出现str2的位置(不包含空结束符)

size_t strcspn(const char* str1,const char* str2);	//检索str1 从开头连续有几个字符都不含有 str2中的字符
size_t strspn(const char* str1,const char* str2);	//检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标。

char* strpbrk(const char*str1,const char*str2);	//检查str2是否包含str1(依次检验字符串 str1 中的字符,当被检验字符在字符串 str2 中也包含时,则停止检验,并返回该字符位置)
//源码
char * __cdecl strchr ( constchar * string,   int ch  ) 
{
   while (*string && *string != (char)ch)
        string++;
  
   if (*string == (char)ch)
       return((char *)string);

    return(NULL);

}
void * my_memchr(const void * buffer,int ch,int count)
{
   while ( count && (*(unsigned char *)buffer != (unsigned char)ch) )
   {
       buffer = (unsigned char *)buffer + 1;
       count--;
   }
   return(count ? (void *)buffer : NULL);
}
 //memchr与strchr区别
 /*
* memchr检测的是一段内存,strchr检测的是一个字符串 
* 如果一段内存中有0x0的话,显然不能用strchr去查找的。建议看看两个函数的原型
* strchr会停在\0,memchr不会
* mem*系 针对字节  str*系 针对字符
* mem  的效率高 类似strcpy memcpy
* memchr针对与内存操作,shtchr只能是字符串操作
*/
 //memchr在字符串的前n个字节内,搜索第一次出现字符c的位置
 //memchr 该函数返回一个指向匹配字节的指针,如果在给定的内存区域未出现字符,则返回 NULL。

#include <stdio.h>
#include <string.h>
 
int main ()
{
   const char str[] = "http://www.runoob.com";
   const char ch = '.';
   char *ret;
   int pos = 0;
 
 //查单个字符
   ret = (char*)memchr(str, ch, strlen(str));   //未出现字符,则返回 NULL。
   if(ret != NULL)
  	 printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);  //|.| 之后的字符串是 - |.runoob.com|
 	
   ret = strchr(str, ch);   //如果未找到该值,则函数返回一个空指针。
   if(ret != NULL)
   	printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);  //|.| 之后的字符串是 - |.runoob.com|
   pos = strlen(str) - strlen(ret);
   printf("子字符串所在的位置 下标 是: %d\n", pos); //下标 是 10

   ret = strrchr(str, ch); 
   if(ret != NULL)
   	printf("|%c| 之后的字符串是 - |%s|\n", ch, ret); //|.| 之后的字符串是 - |.com|
   pos = strlen(str) - strlen(ret);
   printf("子字符串所在的位置 下标 是: %d\n", pos); //17

 //查字符串
   const char needle[] = "noob";
   ret = strstr(str, needle); 
   if(ret != NULL)
   	printf("子字符串是: %s\n", ret);  //子字符串是: noob.com
   pos = strlen(str) - strlen(ret);
   printf("子字符串所在的位置 下标 是: %d\n", pos);  //下标 是13 在第14个
   
   return(0);
}
#include <stdio.h>
#include <string.h> 

int main ()
{
	const char str1[] = "ABCDEFG019874";
	const char str2[] = "ABCD";
	
	//返回匹配的长度
	//查找子串在父串中的匹配度,从父串的第一位字符开始比对
	int len = strspn(str1, str2);	//返回 str1 中第一个不在字符串 str2 中出现的字符下标。
	printf("初始段匹配长度 %d\n", len ); //len=4 走到下标为4的地方的时候,str2与str1不再匹配
	
	strcpy((char*)str2,"ABD"); //BCD 覆盖了原来的ABCD
	len = strspn(str1, str2);
	printf("初始段匹配长度 %d\n", len ); //len = 2
	
	strcpy((char*)str2,"BCD"); //BCD 覆盖了原来的ABCD
	len = strspn(str1, str2);
	printf("初始段匹配长度 %d\n", len ); //len = 0

	//返回下标
	//查找子串在父串中出现的下标
	len = strcspn(str1, str2); //BCD在str1中出现的位置在下标为len=1的地方
	printf("第一个匹配的字符是在 %d\n", len + 1);  //第一个匹配的字符是在 2

	//该函数返回 str1 中第一个匹配字符串 str2 中字符的字符数,如果未找到字符则返回 NULL。
	const char str3[] = "abcde2fghi3jk4l";
	const char str4[] = "34";
	const char *ret1;
	ret1 = strpbrk(str1, str2);
	if(ret1 != NULL)
		printf("第一个匹配的字符是: %c【%s】\n", *ret,ret); //第一个匹配的字符是:3【3jk4l】
		
	return(0);
}

字符串以分隔符分隔

char* strtok(char* str,const char* delim);	//分解str为一组字符串,以delim为分隔符
//该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
#include <string.h>
#include <stdio.h>
 
int main () 
{
  char str[80] = "This is-www.runoob.com-website";
	const char s[2] = "-";
	char *token;
	char* bufTok[10] = {NULL};

	/* 获取第一个子字符串 */
	token = strtok(str, s);
	printf( "第一次: %s\n", token );
	int i = 0;

	/* 继续获取其他的子字符串 */
	while( token != NULL ) 
	{
		printf( "%s\n", token );
		bufTok[i] = token;	 //bufTok[0] = This is;  bufTok[1] = www.runoob.com; bufTok[2] = website
		++i;

		token = strtok(NULL, s);
	}

	return(0);
}

字符串比较

int memcmp(const void* str1,const void* str2,size_t n);		//比较str1和str2的前n个字符

int strcmp(const char* str1, const char* str2);			//str1与str2进行比较
int strncmp(const char* str1, const char* str2,size_t n);	//比较str1和str2的前n个字符

int strcoll(const char* str1, const char* str2);	//把 str1 和 str2 进行比较,结果取决于 LC_COLLATE 的位置设置。
/*
* 如果返回值 < 0,则表示 str1 小于 str2。
* 如果返回值 > 0,则表示 str1 大于 str2。
* 如果返回值 = 0,则表示 str1 等于 str2。
*/
#include <string.h>
#include <stdio.h>

int main () 
{
	char str1[15] = {'\0'};		//必须要初始化,否则打印出来的字符串会有乱码,当然如果不初始化的话,memcpy复制的字节数得为15
	char str2[15]= {'\0'};		//如果是new的话,要用memset初始化
	int ret;
		
	//memcmp 把存储区 str1 和存储区 str2 的前 [n 个字节] 进行比较。 str -- 指向内存块的指针	 n -- 要被比较的字节数。
	memcpy(str1, "abcdef", 6);	//也可以strcat((char*)str1,"abcdef");
	memcpy(str2, "ABCDEF", 6);  //cpy 會覆蓋源字符串

	printf("str1 %s\n",str1);
	printf("str2 %s\n",str2);
	
	ret = memcmp(str1, str2, 5);  // ret = 1
	if(ret > 0)
		printf("str2 小于 str1");
	else if(ret < 0) 
		printf("str1 小于 str2");
	else 
		printf("str1 等于 str2");

	//strcmp  strncmp  str -- 要进行比较的 字符串。
	strcpy(str1, "ddabcdef");
	strcpy(str2, "ddABCDEF");

	printf("\nstr1 %s\n",str1);
	printf("str2 %s\n",str2);

	ret = strcmp(str1, str2);
	//ret = strncmp(str1, str2);

	if(ret < 0)
	{
		printf("str1 小于 str2");
	}
	else if(ret > 0) 
	{
		printf("str1 大于 str2");
	}
	else 
	{
		printf("str1 等于 str2");
	}
	return(0);
}

字符串复制

void* memcpy(void* dest, const void* src, size_t n);	//从src复制n个字符到dest
void* memmove(void* dest, const void* src, size_t n);	//同上

char* strcpy(char* dest, const char* src);	//把src复制到dest
char* strncpy(char* dest, const char* src,size_t n);	//把src的前n个字符复制到dest  strncpy(str, src+3, 3); 复制下标从3开始的3个字符

void* memset(void* str, int c, size_t n);			//将无符号字符c复制到str的前n个字符 (从下标0到n-1,设置str的值为c)(属于字符数组初始化)

size_t strxfrm(char* dest,const char* src,size_t n);	//(src复制给dest)根据程序当前的区域选项中的 LC_COLLATE 来转换 src 的前 n 个字符,并把它们放置在 dest 中。
 //memcpy与strcpy
 /*
 *在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。
 *如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的 字节拷贝到目标区域中,复制后源区域的内容会被更改。
 *如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。
 */
#include <string.h>
#include <stdio.h>

int main () 
{
	const char dest[] = "oldstring";
	const char src[]  = "newstring";

	printf("Before memmove dest = %s, src = %s\n", dest, src); 
	memmove((char*)dest, src, 9);  //覆盖原数据
	printf("After memmove dest = %s, src = %s\n", dest, src);
	/*
	* Before memmove dest = oldstring, src = newstring
	* After memmove dest = newstring, src = newstring
	*/
	
	char str[50];
	strcpy(str,"This is string.h library function");
	puts(str);
	memset(str,'$',7);
	puts(str);

	/*
	*This is string.h library function
	*$$$$$$$ string.h library function
	*/
	
	strxfrm(str,"给str",7); //覆盖原数据
	puts(str);		//给str
	
	return(0);
}

字符串拼接

char* strcat(char* dest, const char* src);		//将src追加到dest结尾
char* strncat(char* dest, const char* src, size_t n);	//将src追加到dest结尾,追加长度为n
#include <string.h>
#include <stdio.h>

int main () 
{
	char src[50], dest[50];

	strcpy(src,  "This is source");
	strcpy(dest, "This is destination");

	strcat(dest, src);
	//strcat_s(dest,sizeof(src),src);  //第二个参数是目标缓冲区的大小
	//strncat(dest, src,10); //最终的目标字符串: |This is destinationThis is so
	printf("最终的目标字符串: |%s|", dest); //最终的目标字符串: |This is destinationThis is source|

	return(0);
}

错误信息

char *strerror(int errnum);   //从内部数组中搜索错误号 errnum,并返回一个指向错误消息字符串的指针。
#include <string.h>
#include <stdio.h>
int main () 
{
	FILE *fp;

	fp = fopen("file.txt","r");
	if( fp == NULL ) 
	{
		printf("Error: %s\n", strerror(errno));
	}
	return(0);
}

字符串长度

size_t strlen(const char* str);		//计算str的长度,直到空结束符,不包括结束符
#include <string.h>
#include <stdio.h>

int main () 
{
	char str[50];
	int len;

	strcpy(str, "This is runoob.com");

	len = strlen(str);  //18
	printf("|%s| 的长度是 |%d|\n", str, len); 

	return(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值