C语言:常见字符串函数详解初阶(小白一看就懂,让你有一种相见恨晚的感觉哦!!!)

目录

一、前言

二、字符串函数详解

1.求字符串长度:strlen()

2.字符串的拷贝:strcpy()

3.字符串连接函数:strcat()

4.字符串比较函数:strcmp()

5.长度不受限制的拷贝字符串函数: strncpy 

6.长度不受限制的连接字符串函数: strncat

7. 长度不受限制的比较字符串函数: strncmp

8.字符串查找函数 strstr()

9.字符操作函数 

三、共勉


一、前言

    再写字符串题目的时候,对于我这个小菜狗来说是一件非常难受的事情,经常会因为字符串的麻烦而导致我有想砸电脑的冲动,对此为了能够更好的理解字符串,我专门花了一天的时间去总结了字符串函数的应用与理解,希望对大家有帮助。

二、字符串函数详解

1.求字符串长度:strlen()

知识点1:

strlen()函数的头文件:#include <string.h>

strlen()函数的声明:

 如何应用:strlen()这个函数在求字符串长度时计算的是 ‘\0’ 之前的字符,且以 ‘\0’ 为字符串的结束标志。

代码举例(1): 字符串 "abcdfefeff " 长度为10

#include <stdio.h>
#include <string.h>
int main()
{
    char a[50] = "abcdfefeff";
    int len = strlen(a);    // strlen()函数里放入字符串数组的首地址
    printf("%d\n", len);    //10
    return 0;
}

 代码举例(2):字符串 {'a','b','c','d'}  长度未知

#include <stdio.h>
#include <string.h>
int main()
{
    char a[] = {'a','b','c','d'};
    int len = strlen(a);
    printf("%d\n", len);    // 74
    return 0;
}

此时结果显示为 74 

原因解释:这里的结果是一个随机数,因为字符串里并没有 ‘\0’ 作为结束标志,所以它会继续往下数 。

 知识点2:strlen() 函数的返回值 是无符号值

代码举例 :

#include<string.h>
#include<stdio.h>
int main()
{
	if(strlen("abc") - strlen("abcdef") > 0)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

按照我们的常理判断 长度应该为 3-6=(-3)

但是streln()函数返回的是 无符号值  所以返回的(-3)就变成了  3 

结果输出 : >

如果此时题目要求我们不能用strlen()函数,我们应该如何模拟呢?

代码演示strlen()函数模拟:

 方法一:指针-指针

// 方法:指针-指针 
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strlen(const char *a)    // size_t 返回指针
{
	assert(a);
	const char* star = a;
	const char* end = a;
	while (*end != '\0')
	{
		end++;
	}
	return end - star;
}
int main()
{
	char a[] = "abcdef";
	int len = my_strlen(a);
	printf("%d\n", len);
	return 0;
}

方法二:计数器版本

#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)  // const 保证字符串不再改变
{                                  // size_t 保证返回的是一个无符号数
	assert(str != NULL); //直接引用指针不安全,需要保证指针一定有效
	int count = 0;
	while (*str++)
		count++;
	return count;
}
int main()
{
	char arr[] = "abc";
	printf("%d\n", my_strlen(arr));
	return 0;
}

知识点3:streln() 函数与  sizeof()函数的区别

1、 strlen 是函数,sizeof 是运算符。

2、strlen 测量的是字符的实际长度,以'\0' 结束。而sizeof 测量的是字符的分配大小。

代码举例:

char str[20] = "hello";
 
printf("strlen: %d\n", strlen(str));   // 5
printf("sizeof: %d\n", sizeof(str));   // 20

3、sizeof():返回所占总空间的字节数
(1)、对于整型字符型数组
(2)、对于整型或字符型指针
4、strlen():返回字符数组或字符串所占的字节数
(1)、针对字符数组
(2)、针对字符指针

其中 sizeof() 可以巧妙的计算数组的长度代码如下所示:
 

#include <stdio.h>
#include <string.h>
int main()
{
    char a[] = {'a','b','c','d'};
    int len = sizeof(a) / sizeof(a[0]);
    printf("%d\n", len);    //  4
    return 0;
}

总结:

▶字符串以 ‘\0’ 作为结束标志,strlen函数的返回值是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )
▶ 参数指向的字符必须要以 ‘\0’ 结束
▶ 注意函数的返回值为size_t,是无符号的(易错)

▶ 注意strlen()函数与sizeof()函数的区别

2.字符串的拷贝:strcpy()

知识点1:

strcpy()函数的头文件:#include <string.h>

strcpy()函数的声明:

 strcpy()函数应用:

strcpy会把源字符串中的内容拷贝到目标空间,并返回目标空间的起始位置

代码演示:

#include<stdio.h>
int main()
{
	char arr[20] = { 0 };
	strcpy(arr, "hello");
	printf("%s\n", arr);   // hello
	return 0;
}

知识点二:

模拟实现strcpy()函数:

#include <stdio.h>
#include <string.h>
char * my_strcpy(char *dest,const char* str)  //资源函数不能变,用const char *str
{
	char* ret = dest;
	while (*str!='\0')
	{
		*dest = *str;
		dest++;
		str++;
	}
	return ret;
}
int main()
{
	char arr[20] = "abc";
    char arr1[] = "hello world";
	my_strcpy(arr, arr1);
	printf("%s\n", arr);
	return 0;
}

总结:

▶ 源字符串必须以 ‘\0’ 结束
▶ strcpy在拷贝的过程中是以 ‘\0’ 为结束标志,且会将 ‘\0’ 也拷贝
▶ 目标空间必须足够大,以确保能存放源字符串
▶ 目标空间必须可变(不能用 const 修饰)

3.字符串连接函数:strcat()

知识点1:
strcat()函数的头文件:#include <string.h>

strcat()函数的声明:

strcat()函数的应用: 源字符串在追加时会找到目标字符串最后的 ‘\0’ 并将它给覆盖,然后开始追加。

代码演示:

#include<stdio.h>
int main()
{
	char arr1[20] = "hello";
	char arr2[] = "bit";
	strcat(arr1, arr2);
	printf("%s\n", arr1); // hellobit
	return 0;
}

大家是都有跟我一样的疑问,在源字符串给目标函数追加时,源字符串的 '\0' 会不会也会追加呢?我们来调试看一下。

代码如下:

#include <stdio.h>
#include <string.h>
int main()
{
	char a[20] = "hello \0 xxxxx"; //在末尾开始追加,用'\0',来判断末尾
	char b[] = "world";
	strcat(a, b);    //字符串连接
	printf("%s\n", a);  // hello world
	return 0;
}

 从图中我们发现源字符串的 '\0' 也追加过来了

知识点2:

 strcat()函数的模拟实现代码如下:

#include <stdio.h>
#include <string.h>
char *my_strcat(char* dest, const char* str)
{
	char* ret = dest;
	while (*dest != '\0')
	{
		dest++;
	}
	while (*str != '\0')
	{
		*dest = *str;
		dest++;
		str++;
	}
	return ret;
}
int main()
{
	char a[20] = "hello xx";
	char b[] = " world";
	my_strcat(a, b);
	printf("%s\n", a);
	return 0;
}

总结:

▶ 源字符串必须以 ‘\0’ 结束
▶ 目标空间必须足够大,以足以容纳字符串
▶ 目标字符串必须可修改
▶ 不能自己追加自己 

4.字符串比较函数:strcmp()

知识点1:

strcmp()函数的头文件:#include <string.h>

strcmp()函数的声明:

strcmp()函数的返回值:

 strcat()函数的应用:

比较对应而位置上的字符的大小(通过指针比较),而非长度

如果出现一对 > 或者 < ,则停止比较,否则直到比较到 '\0' 为止就是相等输出 0 。

代码验证:

#include <stdio.h>
#include <string.h>
int main()
{
	char a[] = "abc";
	char b[] = "abd";
	int len = strcmp(a, b);
	printf("%d\n", len);  // -1
	return 0;
}

 知识点2:

strcmp()函数的模拟实现:

#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2); // 保证两个指针不是空指针 
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	}
	if (*s1 > *s2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char a[] = "abc";
	char b[] = "abc";
    int len = my_strcmp(a, b);
	printf("%d\n", len);  // 0
	return 0;
}

5.长度不受限制的拷贝字符串函数: strncpy 

知识点1:

strncpy()函数的头文件:#include <string.h>

strncpy()函数的声明:

 strncpy()函数的应用:可以根据自己的想法或者题目的要求去拷贝需要的字符个数,不需要将字符串全部拷贝完。

代码演示:

#include <stdio.h>
#include <string.h>
int main()
{
	char a[20] = "abcdef";
	char b[] = "xxxx";
	strncpy(a, b, 2);    // 拷贝两个字符到目标空间
	printf("%s\n", a);  // xxcdef
	return 0;
}

大家可以考虑一个问题,当指定的拷贝个数大于源字符串的个数会出现怎样的情况呢?

代码演示:
 

#include <stdio.h>
#include <string.h>
int main()
{
	char a[20] = "abcdef";
	char b[] = "xxxx";
	strncpy(a, b, 8);
	printf("%s\n", a);  //  xxxx  多出来的后面补上 '\0'
	return 0;
}

我们发现,多出来的个数,会按 '\0' 进行补充

知识点2:
 模拟实现strncpy()函数

#include <stdio.h>
#include <string.h>
char* my_strncpy(char* dest, const char* str, size_t num)
{
	char* ret = dest;
	int len = strlen(str);
	int k = num - len;
	if (num > len)
	{
		while (len--)
		{
			*dest = *str;
			dest++;
			str++;
		}
		// 超出的部分补上 '\0'
		while (k--)
		{
			*dest = '\0';
			dest++;
		}
	}
	else
	{
		while (num--)
		{
			*dest = *str;
			dest++;
			str++;
		}
	}
	return ret;
}
int main()
{
	char a[20] = "abcdef";
	char b[] = "xxxx";
	my_strncpy(a, b, 2);
	printf("%s\n", a);
	return 0;
}

总结:

▶ 拷贝num个字符从源字符串到目标空间
▶ 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加0,直到num个

6.长度不受限制的连接字符串函数: strncat

知识点1;

strncat()函数的头文件:#include <string.h>

strncat()函数的声明:

 strncat()函数的应用:可以根据自己的想法或者题目的要求去连接需要的字符个数,不需要将字符串全部连接完。

代码演示:

#include <stdio.h>
#include <string.h>
int main()
{
	char a[20] = "abcdef\0qqqq";
	char b[] = "xxxx";
	strncat(a, b, 2);  // abcdefxx
	printf("%s\n", a);
	return 0;
}

大家可以考虑一个问题,当指定的连接个数大于源字符串的个数会出现怎样的情况呢?

#include <stdio.h>
#include <string.h>
int main()
{
	char a[20] = "abcdef";
	char b[] = "xxxx";
	strncat(a, b, 8);  // abcdefxxxx 后补上'\0'
	printf("%s\n", a);
	return 0;
}

我们发现,多出来的个数,会按 '\0' 进行补充

知识点2:
 此时的strnact()函数可以进行 自己连接自己

#include <stdio.h>
#include <string.h>
int main()
{
	char a[20] = "abc";
	strncat(a, a, 3);  
	printf("%s\n", a);  //abcabc
	return 0;
}

 知识点3:

模拟实现strncat()函数:

#include <stdio.h>
#include <assert.h>
char* My_strncat(char* dest, const char* source, size_t count)
{
    assert(dest && source);
    char* ret = dest; // 保存初始地址,因为后面会改变初始地址
    while(*dest != '\0')  // 先找到 \0 然后等待追加
    {
        dest++;
    }
    while(count)  // 因为追加受限制于 count 所以 while 循环条件是 count
    {
        
        *dest = *source;
        dest++;
        source++;
        count--;
    }
    return ret;  // 返回初始地址
}
int main()
{
    char arr1[20] = "Hello";
    char arr2[] = " world";
 
    // char* ret = My_strncat(arr1, arr2, 6); // 创建指针变量接收打印
    // printf("%s\n", ret);
 
    printf("%s\n", My_strncat(arr1, arr2, 6)); // 链式访问,也可以创建指针变量接收打印
    
    return 0;
}

7. 长度不受限制的比较字符串函数: strncmp

知识点1:
strncmp()函数的头文件:#include <string.h>

strncmp()函数的声明:

 strncmp()函数的应用:可以根据自己的想法或者题目的要求去比较需要的字符个数,不需要将字符串全部比较完。

代码演示:

#include <stdio.h>
#include <string.h>
int main()
{
	int ret = strncmp("abcdef", "abc",3);  // 相等为0
	printf("%d\n", ret);
	return 0;
}

知识点2:

模拟实现strncmp()函数

#include <stdio.h>
#include <assert.h>
int My_strncmp( const char *str1, const char *str2, size_t count )
{
    assert(str1 && str2); 
    while(count--) // count 做条件
    {    
        if(*str1 == *str2)  // 判断是否相等
        {
            if( (*str1 == '\0') || (count == 0) ) // 如果是 '\0' 或者 count = 0 返回
            {
                return 0;
            }
            str1++;
            str2++;
        }
 
        // 不相等 可以用 if 语句,但是 strncmp 返回的是 >0 <0 =0 而不是 1 -1 所以严谨一点直接解引用 相减
        // if(*str1 > *str2)
        // {
        //     return 1;
        // }
        // if(*str1 <*str2)
        // {
        //     return -1;
        // }
        // 
        
    }
    return *str1 - *str2;  // 做差 是 字符的 ASCII  码大小
}
 
int main()
{
    char arr1[] = "abcdea";
    char arr2[] = "abcdez";
 
    int ret = My_strncmp(arr1, arr2, 6); // 创建整型接受返回值
    if(ret > 0)
    {
        printf(">\n");
    }
    else if(ret < 0)
    {
        printf("<\n");
    }
    else
    {
        printf("=\n");
    }
    printf("%d\n", ret);
    return 0;
}

8.字符串查找函数 strstr()

知识点1:

strstr()函数的头文件:#include <string.h>

strstr()函数的声明:

 strstr()函数的应用:

在一个字符串中找另一一个字符串是否存在
            存在:返回的字符串所在的起始地址(第一次出现得到地址)
            不存在:返回空指针--NULL
            存在 :返回字符串第一次出现的位置

代码演示:
 

#include <stdio.h>
#include <string.h>
int main()
{
    char a[] = "abcdef";
    char b[] = "bcd";
    char* p = strstr(a, b);
    if (p == NULL)
    {
        printf("不存在");
    }
    else
    {
        printf("%s\n", p);  //bcdef
    }
	return 0;
}

*******重点:知识点2:

用于多次匹配直到母串结束记录,统计子串在母串中出现的次数

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

int main()
{
    int i,n,j,k=0;
    char a1[1001],a2[1001];
    scanf("%s %s",a1,a2);
    char *p;
    p=a1;
    while( ( p=strstr(p,a2) ) != NULL)//p为子串与母串匹配成功
    {								  //时,子串第一个符号在母串
        k++;						  //中出现的位置地址
        p++; //p++后才能匹配下一个,否则无法退出循环
    }
    printf("%d",k);
}

结果:
abababababa
aba
5

知识点3:
 模拟实现strstr()函数

#include <stdio.h>
#include <string.h>
char* my_strstr(const char* str1, const char* str2)
{
    const char* s1 = str1;
    const char* s2 = str2;
    const char* p = str1;
    if (*str2 == '\0')
    {
        return (char *)str1;
    }
    while (*p != '\0')
    {
        s1 = p;
        s2 = str2;
        while (*s1!='\0'&&*s2!='\0'&& * s1 == *s2)
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')
        {
            return (char *)p;  //找到了
        }
        p++;
    }
    return NULL;  //找不到子串
}
int main()
{
    char a[] = "abcdef";
    char b[] = "abc";
    char* p = my_strstr(a, b);
    if (p == NULL)
    {
        printf("不存在\n");
    }
    else
    {
        printf("%s\n", p);
    }
    return 0;
}

9.字符操作函数 

 知识点1:

字符分类函数:

 这些函数的头文件:#include <ctype.h>

在这里我给大家简单介绍几个常用的,大家可以跟着照猫画虎。

知识点2:

 函数isdigit() :判断是不是数字

isdigit()函数的声明:

代码演示:

#include<stdio.h>
#include<ctype.h>
int main()
{
	char ch = '@';
	//如果是数字字符返回非0的值,否则返回0
	int ret = isdigit(ch);
	printf("%d\n", ret);
	return 0;
}

三、共勉

以下就是我对C语言常用字符串函数的初阶理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对C语言常用字符串函数的进阶理解,请持续关注我哦!!!!! 

猜你喜欢

转载自blog.csdn.net/weixin_45031801/article/details/127464365