【c】字符串进阶篇

我的博客栈
前言:本文主要介绍了在c语言中经常出现的和字符,字符串相关的一些函数知识点。


字符串函数

使用这些库函数都需要引用<string.h>头文件。

strlen函数

以下是引用runoob关于strlen的描述。

C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。

一共可以得出三个要点,首先strlen的作用是计算字符串的长度,其次其计算的标准是到’\0’为止,并且不包括’\0’。

其声明为:

size_t strlen(const char *str);

指向的字符串一定要以’\0’结束。且函数返回值为size_t,是无符号的。
为何要强调这一点呢,来看一个例子。

char *arr1[]="abc";
char *arr2[]="a";
if(strlen(arr2)-strlen(arr1)>0)
  printf("arr2>arr1");
else
  printf("arr1>arr2");

arr2是比arr1要短的,所以会输出arr1>arr2吗?答案是输出arr2>arr1,因为strlen的返回值是一个非负数,所以是必然大于0的。

strlen的模拟实现(仅展示大概思路):

int MyStrlen(char *s)
{
   char *p = s;
   while(*p != '\0' )
       p++;
   return p-s;
}

除此之外还可以借助递归等方式来实现。
使用时常用以计算字符串长度。

int length = strlen(arr);

strcpy函数

以下是引用runoob关于strcpy的描述。

C 库函数 char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest。
需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。

strcpy函数的作用是复制字符串。其声明为:

char *strcpy(char *dest, const char *src)

返回值为指向dest这个字符串的指针。
注意,源字符串(src)必须包含'\0',且斜杠0也会被一同复制到目标字符串(dest)中去,成为新的结束标志。如果源字符串中加入了’\0’,那么就会截断到此斜杠0。例如"abc\0a",只会将"abc\0"复制过去。
其模拟实现为

void Mystrcpy(char* dest,char *str)
{
	while((*dest++ = *src++))
 {
  ;
 }
}

在这里并未实现返回指针,如果需要的话,需要定义一个指针指向原先的dest。之后返回这个指针。
使用示例:


   char arr1[10] = "hello ";
   char arr2[10] = "world";
   char ret=strcpy(arr1,arr2);
   printf("%s",ret);

打印出world的字样。

strcat函数

以下是引用runoob关于strcat的描述。

C 库函数 char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾

从描述中可以看出,其作用是在一个字符串的末尾追加另一个字符串的内容。源字符串必须是以’\0’结束,修改目标字符串也是从’\0’开始。

其声明为:

char *strcat(char *dest, const char *src) 

返回一个指针指向dest这个字符串。

其模拟实现为:

char *MyStrcat(char *dest, char*src)
{
 char *ret = dest;
 while(*dest)
 {
  dest++;
 }
 while((*dest++ = *src++))
 {
  ;
 }
 return ret;
}

将指针dest不断后移至dest字符串的末尾,同时指定一个新指针指向字符串的头,方便返回。在找到了字符串的终止位置斜杠0时,将另一个字符串的值通过指针src和dest的不断后移,赋给目标字符串。
使用示例:

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

打印出hello world字样。

strcmp函数

以下是引用runoob关于strcmp的描述。

C 库函数 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

strcmp的作用是比较两个字符串,比较的方法是计算二者ASC码值的大小。例如"abc"与"abd",会先比较两个字符串的首位a与a,相等再比较下一位,如果可以确定二者不相等就停止后面的比较。
其声明为:

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

返回值分为三种情况:
1.返回值大于0,说明str1比str2大。
2.返回值小于0,说明str1比str2小。
3.返回值等于0,说明str1与str2相等。
其模拟实现为:

int Mystrcmp(int* str1, int* str2)
{
  int ret = 0 ;
  while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
    ++src, ++dst;if ( ret < 0 )
    ret = -1 ;
  else if ( ret > 0 )
    ret = 1 ;return( ret );
}

使用示例:

int ret=strcmp(arr,str);

比较两个字符串,arr大于str则返回大于0的数,小于str则返回小于0的数,等于str则返回0。一定要记得其比较大小的依据是同位字符的ASC码值

strstr函数

以下是引用runoob关于strstr的描述。

C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 ‘\0’。

strstr是一个查找函数,在haystack中找不到needle就返回NULL。找的到就返回第一次发现needle字符串的位置。
其声明为:

char *strstr(const char *haystack, const char *needle)

模拟实现为:

char *  strstr (const char * str1, const char * str2)
{
        char *cp = (char *) str1;
        char *s1, *s2;
 
 
        if ( !*str2 )
            return((char *)str1);
 
 
        while (*cp)
        {
                s1 = cp;
                s2 = (char *) str2;
 
 
                while ( *s1 && *s2 && !(*s1-*s2) )
                        s1++, s2++;
 
 
                if (!*s2)
                        return(cp);
 
 
                cp++;
        }
 
 
        return(NULL);
}

使用示例:

 char haystack[20] = "hello";
 char needle[10] = "llo";
 char *ret;
 ret = strstr(haystack, needle);
 printf("子字符串是: %s\n", ret);

strncpy函数,strncat函数,strncmp函数

以下是引用runoob关于strncpy的描述。

C 库函数 char *strncpy(char *dest, const char *src, size_t n) 把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

和strcpy无太大差别,strncpy主要是可以自行选择复制的长度。以下的strncat和strncmp相同。
其声明为:

 char *strncpy(char *dest, const char *src, size_t n);

以下是引用runoob关于strncat的描述。

C 库函数 char *strncat(char *dest, const char *src, size_t n) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。
其声明为:

char *strncat(char *dest, const char *src, size_t n);

同时追加完后会在末位添加斜杠0。

以下是引用runoob关于strncmp的描述。

C 库函数 int strncmp(const char *str1, const char *str2, size_t n) 把 str1 和 str2 进行比较,最多比较前 n 个字节。

比较到出现另个字符串不一样或者num个字符全都比较完。
其声明为:

int strncmp(const char *str1, const char *str2, size_t n);

三个函数都和前面的相对应的函数演示差不多。

strtok函数

以下是引用runoob关于strtok的描述。

C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。

其声明为:

char *strtok(char *str, const char *delim)

delim是一个字符串,其定义了用作分隔符的字符集合。
str则包含了0个或多个由delim字符串中一个或多个分隔符分割的标记。strtok会去找到这个标记,并用\0来结尾。
使用示例:

char str[] = "a.b.c.d";
   char* p;
   p = strtok(str, ".");
   while (p != NULL)
   {
   	printf("%s\n", p);
   	p = strtok(NULL, ".");
   }

屏幕上会输出a,b,c,d四行,点作为一个分隔符将四个字符隔开了。但为何要这样去输出呢?为何while循环里再次引用strtok时第一个参数为NULL?
其返回值规定:该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。上文提到了标记,这里的点就是一个标记。若strtok函数第一个参数str不是NULL,则函数会找到str中的第一个标记,并且保存它在字符串的位置。若第一个参数为NULL,则函数将在同一个字符串被保存的位置开始,查找下一个标记。

strerror函数

以下是引用runoob关于strerror的描述。

C 库函数 char *strerror(int errnum) 从内部数组中搜索错误号 errnum,并返回一个指向错误消息字符串的指针。strerror 生成的错误字符串取决于开发平台和编译器。

其声明为:

char *strerror(int errnum)

简单的来讲,就是会当程序出错时,返回一个错误码并存放在变量errnum中去。我们可以通过解引用strerror的返回值去寻找错误码。
其需要包含除string.h外,errno.h这个头文件。

使用示例:

FILE *fp;
   fp = fopen("file.txt","r");
   if( fp == NULL ) 
      printf("Error: %s\n", strerror(errno));

若不存在此文件,则打印出Error: No such file or directory的字样。


字符分类函数

字符串的常用函数已经介绍完毕,接下来就是一些应用于字符的函数。
其包含于头文件<ctype.h>

ctype.h是C标准函数库中的头文件,定义了一批C语言字符分类函数(C character classification functions),用于测试字符是否属于特定的字符类别,如字母字符、控制字符等等。既支持单字节字符,也支持宽字符。—援引自百度词条。

大概有以下几种常用函数。
单字节字符处理函数在ctype.h(C++的cctype)中声明。宽字节字符处理函数在wctype.h(C++的cwctype)中声明。我们常用单字节处理函数。也就是isalnum,isalpha这种。

isalnum(单)
iswalnum (双) 是否为字母数字
isalpha
iswalpha 是否为字母
islower
iswlower 是否为小写字母
isupper
iswupper 是否为大写字母
isdigit
iswdigit 是否为数字
isxdigit
iswxdigit 是否为16进制数字
iscntrl
iswcntrl 是否为控制字符
isgraph
iswgraph 是否为图形字符(例如,空格、控制字符都不是)
isspace
iswspace 是否为空格字符(包括制表符、回车符、换行符等)
isblank
iswblank 是否为空白字符(C99/C++11新增)(包括水平制表符)
isprint
iswprint 是否为可打印字符
ispunct
iswpunct 是否为标点
tolower
towlower 转换为小写
toupper
towupper 转换为大写

以字符转换为例子,讲解几个大小学转换函数。

int i = 0;
	char str[] = "aAbBcC";
	char c;
	while (str[i])
	{
		c= str[i];
		if (isupper(c))
			c = tolower(c);
		putchar(c);
		i++;
	}

输出aabbcc。


内存函数

memcpy函数

以下是引用runoob关于memspy的描述。

C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。

其声明为:

void *memcpy(void *dest, const void *str, size_t n)

memcpy和strcpy是有区别的,strcpy在遇到\0会停下来,而memcpy不会停止。并且memcpy是可以复制不止字符串的其他内容。但当str和dest发生重叠时,其复制结果将无法定义。
该函数返回一个指向目标存储区 str1 的指针。

其模拟实现为:

void* MyMemcpy(void* dst, void* src, size_t count)
{
	void* ret = dst;
	while (count--)
	{
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}
	return ret;

}

使用void来接收是因为不知道memcpy会接受字符型还是整型等参数进来。将指针强转为char是为了控制其前进的步长。

使用示例:

char src[50] = "hello,world";
char dest[50];
memcpy(dest, src, strlen(src)+1); //加1将\0一起复制过去。
printf("dest = %s\n", dest);
   

memmove函数

以下是引用runoob关于memmove的描述。

库函数 void *memmove(void *str1, const void *str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。

其声明为:

void *memmove(void *str1, const void *str2, size_t n)

是一个加强版的memcpy。
其模拟实现为:

void *MyMemmove(void *dst,const void *src,size_t num)
{
	if( dst>src&&dst<src+num)
	{
	  const char*src_=(char*)src+num-1;
      char*dst_=(char*)dst+num-1;
	    while(num>0)
	    {
	  	   *dst_=*src_;
	    	dst_--;
		    src_--;
		    num--;
     	}
	}
	else
	{
		const char*src_=(char*)src;
        char*dst_=(char*)dst;
	    while(num>0)
		{
			*dst_=*src_;
			dst_++;
			src_++;
			num--;
		}
	}	
}

memcmp函数

以下是引用runoob关于memcmp的描述。

C 库函数 int memcmp(const void *str1, const void *str2, size_t n)) 把存储区 str1 和存储区 str2 的前 n 个字节进行比较

其声明为:

int memcmp(const void *str1, const void *str2, size_t n)

如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值