20.0、C语言——字符串函数的使用和剖析

20.0、C语言——字符串函数的使用和剖析

目录

20.0、C语言——字符串函数的使用和剖析

前言

函数介绍: 

strlen ( )

strcpy ( )

strncpy ( )

strcat ( )

strncat ( )

strcmp ( )

strncmp ( )

strstr ( )

strtok ( )

strerror ( )


求字符串长度:
       
strlen();

长度不受限制的字符串函数:
【那么由于长度不受限制,所以当不熟悉函数的时候比较容易出现错误,比如越界访问等】
        strcpy();
        strcat();
        strcmp();

长度受限制的字符串函数介绍:
        strncpy();
        strncat();
        strncmp();

字符串查找:
        strstr(); 
        strtok();

错误信息报告:
       
strerror();

字符操作:
 

内存操作函数:
        memcpy();
        memmove();
        memsrt();
        memcmp();

前言

        C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中,或者字符数组中,字符串常量 适用于那些不做修改的字符串函数

函数介绍: 

strlen ( )

size_t  strlen ( const char*str );

        1.字符串将 ' /0 ' 作为结束标志,strlen函数返回的是在字符串中 ' /0 ' 前面出现的字符个数 (不包含 ' /0 ');        
        2.参数指向的字符串必须要以 ' /0 ' 结束;
        3.注意函数的返回值size_t【查看源码后可知该类型被 typedef 后的 unsigned int 类型】,是无符号的(易错;比如 -> strlen("abc") - strlen("abcdef") 结果是否大于0呢?答案是:大于0 因为strlen();函数返回的是无符号数)
        4.学会 strlen 函数的模拟实现;

strcpy ( )

char* strcpy(char* destination , const char* source);  //将源头(source)拷贝到目的地(destination)中去
        Coples the C String pointed by source into the array pointed by destination , including the terminating null character ( and stopping at that point )

        1.源字符串必须以 ' /0 ' 结束【就是必须保证源字符串中必须要有 ' \0 ',不然一直找不到' \0 '很可能会导致访问越界】;
        2.会将源字符串中的 ' /0 ' 拷贝到目标空间;
        3.目标空间必须足够大,以确保能放得下原字符串;
        4.目标空间必须可变,不能是常量字符串【例如:char* p = "abcdefgh" 这就是一个常量字符串】;
        5.学会模拟实现,模拟实现代码如下:

char* my_strcpy(char * dest,char const* source) {
	assert(dest != NULL);
	assert(source != NULL);
	char* ret = dest;
	//拷贝原字符串到目标字符串中,包含 '\0'
	while (*dest++ = *source++) {
		;
	}
	//返回目的空间原始的首地址
	return ret;
}

strncpy ( )

char* strncpy ( char* destination , const char* source , size_t num); 
        Copies the first num characters of source to destination.If the end of the source C string (which is signaled bt a null-character) is found before num characters hava been copied , destination is padded with zeros until a total of num characters hava been written to it

        1.拷贝 num 个字符从源字符串到目标空间【指定拷贝多少个字符串,单位是 字节】;
        2.如果源字符串的长度小于 num ,则拷贝完源字符串之后,在目标的后面追加 0 ,直到num个;

        1.例如:char str1[15] = "abcdef"; char str2[ ] = "hello world"; strcpy(str1,str2,11);
        这段代码就表示 -> 将 str2 拷贝到 str1中 并不拷贝 ' \0 '【因为只拷贝了11位字符】 ,这里我们参数写多少就拷贝多少位字符,和 strcpy() 不同,sytcpy() 一直拷贝完源字符串的 ' \0 ' 才会停止;
        2.那如果我们拷贝的参数超过了源字符串的大小 -> 那么超过的部分将会自动补齐 ' \0 '

自定义模拟实现 styncpy() 函数,实现代码如下所示:

char* my_styncpy(char* dest,char const* source,int num) {
	char* ret = dest;
	int source_len = strlen(source);
	while (num--) {
		if (*source == '\0') {
			*dest = '\0';
			dest++;
			continue;
		}
		*dest = *source;
		dest++;
		source++;
	}
	return ret;
}

strcat ( )

char* strcat(char* destication , const char* source);
        Appends a copy of the source string to the destication string.The terminating null character in destiantion is overwritten by the first character of source,and a null-character is included at the end of the new string formed by the concatenation of both in destinatoin

        1.源字符串必须以 ' \0 ' 结束
        2.目标空间必须有足够大,能容纳下源字符串的内容,且目标字符串中也必须包含 ' \0 ',这样源字符串才知道从何处开始追加拼接
        3.目标空间必须可修改  
        4.字符串如何自己给自己追加?

自定义 strcat() 追加函数,代码如下所示:

char* my_strcat(char* dest, char const* source) {
	assert(dest && source);
	int dest_len = strlen(dest);
	char* ret = dest;
	dest += dest_len;
	while(*dest++ = *source++) {
		;
	}
	return ret;
}

strncat ( )

char* strncat ( char* destination , const char* source , size_t num );
        Appends the first num characters of source to destination , plus a terminating null-character , If the length of the C string in source is less than num , only the content up to the terminating null-charater is copied

        1.当我们追加完定义好的字符的个数后,会自动在追加的字符后面加上一个 ' \0 ',因为他默认我们追加完字符后仍然是一个字符串;
        2.strncat() 和 styncpy() 不同,当我们定义追加的个数大于源字符串个数的时候,他只会把源字符串全部追加到 目标字符串中【并不会像 strncpy() 一样默认将超过的个数置为 ' /0 '】 ,并且在追加的最后面加上一个 ' /0 ';

strcmp ( )

int strcmp const char* str1 , const char* str2 ) 
        This function starts comparing the first character of each string.If they are equal to each other,it conrinues with the following pairs until the characters differ or until a terminating null-character is reached

标准规定:
        1.第一个字符串大于第二个字符串,则返回大于 0 的数字;【在 vs 编译器下默认返回 1】
        2.第一个字符串等于第二个字符串,则返回 0;
        3.第一个字符串小于第二个字符串,则返回小于 0 的数字;【在 vs 编译器下默认返回 -1】
        4.那么如何判断两个字符串呢?

strcmp()函数比较的方法是 -> 一对一对两个字符比较; 
        比如: char* str1 = "abc"; char* str2 = "afg"; strcmp(str1,str2);
        那么他会先比较 'a' 和 'a' 由于这两个 ascall 码值相同,会继续向下比较 'b' 和 'f' 这时由于 'f' 的  ascall 码值 大于 'b' 的 ascall 码值,那么则会判定 'f' 所在的字符串较大,则返回一个负数

自定义my_strcmp() 函数,代码如下所示:

int my_strcmp(char const* str1, char const* str2) {
	assert(str1 && str2);
	while (*str1 == *str2) {
		if (*str1 == '\0') {
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2) {
		return 1;
	}
	else {
		return -1;
	}
}

strncmp ( )

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

        比较到出现两个字符不一样,或者一个字符串结束,或 num 个字符全部比较完

        标准规定:
        1.第一个字符串大于第二个字符串,则返回大于 0 的数字;【在 vs 编译器下默认返回 1】
        2.第一个字符串等于第二个字符串,则返回 0;
        3.第一个字符串小于第二个字符串,则返回小于 0 的数字;【在 vs 编译器下默认返回 -1】

strstr ( )

char* strstr ( const char* str1 , const char* str2 );
        Returns a pointer to the first occurrence of str2 in str1 , or null pointer if str2 is not part of str1.

        1. 在 str1 中寻找 str2 ,如果子字符串 str2 存在于 str1 中,则返回第一次找到该子字符串的首字符地址;
        2. 例 char str1[] = " abcdefabcdef "; char str2[] = " def "; char* p = strstr( str1 , str2 ); 则返回的地址是 str1 中第一次出现 def 中的字符 d 的地址;
        如果输出 printf("%s" , p);  则输出的结果是 -> defabcdef

那么接下来我们自定义模拟实现一下my_strstr() 函数,实现代码如下所示 ->

char* my_strstr(const char* p1,const char* p2) {
	assert(p1 && p2);
	char* s1 = p1;
	char* s2 = p2;
	char* cur = p1;
	if (*p2 == '\0') {
		return p1;
	}
	while (*cur) {
		s1 = cur;
		s2 = p2;
		while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2)) {
			s1++;
			s2++;
		}
		if (*s2 == '\0') {
			return cur; //找到子串
		}
		if (*s1 == '\0') {
			return NULL; //找不到子串
		}
		cur++;
	}
	return NULL; //找不到子串
}

strtok ( )

char* strtok ( char* str , cosnt char* sep );

        1. sep参数是个字符串,定义了用作分隔符的字符串集合;

例如 ->

        char arr[ ] = { " www.hkl@澜色海湾.com " }; 那么 arr 就是 strtok 的第一个参数;
        char* p = " .@ "; 那么 p 就是strtok的第二个参数,用于分割arr字符串的分隔符;

        2. 第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的标记;
        3. strtok 函数找到 str 中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针;(注: strtok 函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容并且可以修改);
        4. 若 strtok 函数的第一个参数不为 NULL ,函数将找到 str 中第一个标记【这里指的就是 > 找到第一个分隔符,并把它改为 ' \0 '】,strtok 函数将会自动保存该分隔符在字符串中的位置,然后返回该分隔符前的字符串首字符地址;
        5. 若 strtok 函数的第一个参数为 NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
        6. 如果字符串中不存在更多的标记,则返回 NULL 指针

        接下里看看代码实例 ->

int main() {
	char arr[] = {"www.hkl@澜色海湾.com"};
	char* p = ".@";
	char* ret = NULL;
	ret = strtok(arr,p);
	printf("%s\n", ret);
	ret = strtok(NULL, p);
	printf("%s\n", ret);
	ret = strtok(NULL, p);
	printf("%s\n", ret);
	ret = strtok(NULL, p);
	printf("%s\n", ret);
	return 0;
}

输出的结果是 :
        www
        hkl
        澜色海湾
        com
当然这么写主要是让大家容易理解,在真实开发中并不会这样去用;


        那么来看看真实开发中如何使用 strtok() 函数 ->

int main() {
	char arr[] = {"www.hkl@澜色海湾.com"};
	char* p = ".@";
	char* ret = NULL;
	for (ret = strtok(arr,p); ret != NULL; ret = strtok(NULL,p)) {
		printf("%s\n",ret);
	}
	return 0;
}

        这里巧妙运用了 for() 循环中 初始化只会执行一次;输出的结果和上面相同

strerror ( )

char* strerror ( int errnum );

返回错误码,所对应的错误信息【 使用时 记得引入头文件 #include <errno.h> 】

        1. strerror() 函数就是把错误码转 换成 相对应的错误信息,反馈回来;

        例如 ->

int main() {
    char* p = strerror(0);
    printf("%s\n", p);
	return 0;
}

        那么输出的结果是:No error 这样一个字符串;
        但是我们在实际开发中不会这么使用,不会自己放一个数字到strerro()函数中去,而是放errno  ->  strerror( errno );
        当C语言的库函数在执行的过程中,发生了错误,就会把对应的错误码 -> 赋值到 errno 中;下面给大家举个例子 ->

int main() {
	FILE* pf = fopen("test.txt","r");//打开文件
	if (pf == NULL) { //如果等于 NULL 说明文件打开失败,
		printf("%s\n",strerror(errno));
	}
	else {
		printf("open file success\n");
	}
	return 0;
}

        最后输出的结果是 - > No such file or directory

下面总结了从 0 ~ 43的错误码所对应的错误信息->

0          ——        No error
1          ——        Operation not permitted
2          ——        No such file or directory
3          ——        No such process
4          ——        Interrupted function call
5          ——        Input/output error
6          ——        No such device or address

7          ——        Arg list too long
8          ——        Exec format error
9          ——        Bad file descriptor
10        ——        No child processes
11        ——        Resource temporarily unavailable
12        ——        Not enough space
13        ——        Permission denied
14        ——        Bad address
15        ——        Unknown error
16        ——        Resource device
17        ——        File exists
18        ——        Improper link

19        ——        No such device
20        ——        Not a directory
21        ——        Is a directory
22        ——        Invalid argument
23        ——        Too many open files in system
24        ——        Too many open files
25        ——        Inappropriate I/O control operation
26        ——        Unknown error
27        ——        File too large
28        ——        No space left on device
29        ——        Invalid seek
30        ——        Read-only file system
31        ——        Too many links
32        ——        Broken pipe
33        ——        Domain error
34        ——        Result too large

35        ——        Unknown error
36        ——        Resource deadlock avoided
37        ——        Unknown error
38        ——        Filename too long
39        ——        No locks available
40        ——        Function not implemented
41        ——        Directory not empty
42        ——        Illegal byte sequence
43        ——        Unknown error

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值