C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串或字符数组中,字符串常量适用于那些对它不做修改的字符串函数。
求字符串长度:
1:strlen函数:size_t strlen(const char*str)【size_t=unsigned int】
举例:
#include<stdio.h>
#include<string.h>
int main()
{
int len = strlen("hello,C");
printf("%d\n", len);
return 0;
}
字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含‘\0’),因此输出结果为6
6
但如果我们将其换一种写法,输出结果还会是6吗?
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = { 'h','e','l','l','o','C' };
int len = strlen(arr);
printf("%d\n", len);
return 0;
}
**参数指向的字符串必须要以’\0’结束。
74
输出结果为什么是74呢?原因为,此时的hello,C,被我们存放在了字符数组而不是字符串,而字符数组并不包含’\0‘,但strlen函数只有遇到’\0’会停止计算长度,因此这种情况下,strlen函数会在随机值中继续查找,直到碰到’\0’,才会输出长度。
strlen函数返回的类型是size_t(unsigned int)
证明如下:
对上述示例中的stlen函数的返回值类型,我们进行了调整。
左边输出结果为hehe,原因:由于strlen函数的返回值类型是size_t(unsigned int),因此即使字符串”abc”和字符串“abcdef”相减,都不会返回-3,系统会将-3进行,按无符号整数输出。
右边的strlen函数的返回值类型是int,是有符号整数,因此函数返回值为-3.
2:使用指针:
#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)//const修饰指针char*
//由于要求的字符串是常量字符串,因此指针指向的内容无法被改变
{
assert(str != NULL);assert(断言):如果出现括号中的情况,则程序会停止运行
int count = 0;
while (*str != 0)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] =("abcdef");
int my_strlens = my_strlen(arr);
printf("%d\n", my_strlens);
}
6
注意:strlen函数的返回值是无符号整数,因此不会出现负数。
证明如下:
#include<stdio.h>
#include<string.h>
int main()
{
if ((strlen("abc") - strlen("abcdef")) > 0)
printf("hehe");fan
else
printf("haha");
}
hehe
长度不受限制的字符串函数:strcpy/strcat/strcmp
strcpy:char* strcpy(destination,resource)
举例:
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcpy(char* dest,const char* res)//做字符串拷贝时,源头字符串不会发生改变变,可以用const修饰
{
assert(dest != NULL);
assert(res != NULL);
char* ret = dest;//定义指针ret,指向dest
while (*dest++ = *res++)//遇到'\0',循环终止
{
;
}
return ret;//注意:这里不能直接返回dest,因此此时的dest已经不是目地空间的起始地址了
}
int main()
{
char arr1[] = "早上好呀";
char arr2[] = "小懒虫";
strcpy_s(arr1, arr2);
my_strcpy(arr1,arr2);
printf("%s\n", arr1);
return 0;
}
小懒虫
注意:*dest++ = res++,运算符和++都属于单目运算符,两者的优先级是一样的,结合性的方向是从右到左。
因此,有些小伙伴会认为这个表达式的运算顺序是:dest/res先自身+1,其次进行解引用,其实这种想法是错误的。
正确的运算顺序应该是:首先解引用指针变量dest/res,然后dest/res再自身加1,之所以不按照从右向左的结合性,是因为++自身的特性引起的。
使用strcpy函数时,需要注意的事项:
1:源字符串必须以’\0’结束
举例:
char arr[] = { 'h','e','l','l','o' };
如果源字符串是上述这种不包含’\0’的,编译器会一直往后找’\0’,因此很有可能b发生越界访问。
2:会将源字符串中的’\0’拷贝到目标空间
举例:
char arr[] = "bit";
arr其实有四个字符,其中还包含’\0’.
3:目标空间必须足够大,以确保源字符串能够完整放入
举例:
char arr[] = "bit";
char arr1[] = "hello,world";
如果是将arr1放入arr中,是不能实现的,因为arr只能存放4个字符,而arr1有12个字符
4:目标空间必须可变
char *p = "hello,world";
如果目标空间是如上所示这种,是无法将其它字符串拷入其中,因为此时p指向的是常量字符串,其无法被改变,如果强制性被改变,会导致程序崩溃。
strcat:
目标空间必须足够大:
举例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "hello";
char arr2[] = "world";
strcat_s(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
如上所示代码:由于arr1的空间不够大,只能存放6个字符,因此将arr2拷贝到arr1的过程,会导致程序崩溃。
通过调试验证源字符串中的”\0‘也被拷贝过去了
使用strcat函数时,需要注意的事项:
1:源字符串必须以’\0’结束
2:目标空间必须足够大
3:目标空间必须可修改
以上三点,具体证明结果可参考上面的strcpy函数
4:字符串自己追加自己
证明如下:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest,const char* res)
{
assert(*dest!=NULL);
assert(res);
char* ret = dest;
//先找目标字符串的结束标志
while (*dest != '\0')
{
dest++;
}
//字符串自己进行追加
while (*dest++ = *res++)
{
;
}
return ret;//不能直接返回dest,因为此时的dest并不是目标空间的首地址
}
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s ", arr1);
return 0;
}
helloworld
strcmp:int strcmp(const charstr1,const charstr2)
举例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "bbc";
//如果str1>str2,返回大于零的数字,str1<str2返回小于零的数字,二者相等返回0
int ret=strcmp(arr1, arr2);
printf("%d ", ret);
return 0;
}
为什么输出结果是-1呢?如果strcmp比较的是字符串的长度,输出结果应该为大于0的数字
-1
由此我们可以得到结论:strcmp函数在比较字符串的时候,实际比较的是首元素的ASCII码值,如果首元素ASCII码相等,则依次比较第二个第三个,直到不相等。
标准规定: 如果str1>str2,返回大于零的数,str1<str2返回小于零的数,二者相等返回0
在VS编译器下,如果str1>str2,返回1,str1<str2返回-1,二者相等返回0
而在Linux-gcc系统下,strcmp函数返回的是ASCII的差值
因此在使用strcmp函数的时候,不能将函数的返回值设置为具有局限的:
举例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "bbc";
//1,-1,0只是在VS编译器下,strcmpy函数返回的结果,但C语言并为这样定义
if (strcmp(arr1, arr2) == 1)
{
printf("str1>str2");
}
else if (strcmp(arr1, arr2) == 0)
{
printf("str1=str2");
}
else if (strcmp(arr1, arr2) == -1)
{
printf("str1<str2");
}
return 0;
}
正确写法:
if (strcmp(arr1, arr2)>0)
{
printf("str1>str2");
}
else if (strcmp(arr1, arr2) == 0)
{
printf("str1=str2");
}
else if (strcmp(arr1, arr2) <0)
{
printf("str1<str2");
}
用库函数定义的方法进行实现:
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp(const char*str1,const char*str2)//字符串只是进行比较,并会改变值,因此可以用const修饰
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 && *str2 == '\0')//字符串相等
{
return 0;
}
str1++;
str2++;
}
return (*str1 - *str2);
}
int main()
{
char arr1[] = "abcsdf";
char arr2[] = "nihao";
int ret=my_strcmp(arr1, arr2);
printf("%d", ret);
return 0;
}
-13
上述所讲的strcpy/strcat/strcmp函数,都是不受长度限制的函数,因此特们不太安全,有时会强制性的进行字符串操作。因此我们引出下受长度限制的字符串函数:
长度受限制的字符串函数:strncpy/strncat/strncmp
strncpy:charstrncpy(chardest,onst char*res,size_t count(单位是字节))
拷贝num个字符从源字符串到目标空间,如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加\0,直到num个
举例:
int main()
{
char arr1[30] = "abcdef";
char arr2[] = "bit";
strncpy_s(arr1, arr2, 8);
printf("%s ", arr1);
return 0;
}
bit
使用库函数定义的方法实现:
#include<stdio.h>
#include<string.h>
char* my_strncpy(char* dest,const char* source,size_t count)
{
char* start = dest;
//进行字符串拷贝
while (count && (*dest++ = *source++))
count--;
//将目标空间多出来的部分追加\0
if (count)
while (--count)
*dest++ = '\0';
//返回目标空间的首元素地址
return(start);
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "bit";
char* ret=my_strncpy(arr1, arr2, 6);
printf("%s ", ret);
return 0;
}
bit
strncat:charstrncat(chardest,const *strres,size_t count)
指定长度的追加,追加完毕后,给后面加\0
举例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
strncat_s(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
hellowor
使用库函数定义的方法实现:
#include<stdio.h>
#include<string.h>
char* my_strncat(char* front,const char* back,size_t count)
{
char* start = front;
while (*front++)
;
front--;//先找到目标空间中字符串的结束标志
while (count--)
if (!(*front++ = *back++))//将两个字符串进行连接
return(start);
*front = '\0';//给连接后的字符串添加'\0'
return(start);
}
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
char* ret = my_strncat(arr1, arr2, 4);
printf("%s ", ret);
return 0;
}
helloworl
strncmp:int strcmp(const charstr1,const charstr2,size_t num)
标准规定: 第一个字符串大于第二个字符串,则返回大于零的数字
第一个字符串小于第二个字符串,则返回小于零的数字
两个字符串相等,返回0
举例:
int main()
{
char arr1[30] = "abblo";
char arr2[] = "abbld";
int ret = strncmp(arr1, arr2, 4);//第三个参数为比较的字节数
printf("%d ", ret);
return 0;
}
strncmp函数和strcmp函数不同的是,该函数对所比较的字符长度进行了限制,如上述所示arr1(abblo)和str2(abbld),前四个元素的ASCII码是相同的,但由于我们对二者所比较的长度进行了限制,因此,第五个元素并不会进行比较,所以输出结果为0
0
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/81480.html