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");fanelseprintf("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,指向destwhile (*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返回小于零的数字,二者相等返回0int 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--;//将目标空间多出来的部分追加\0if (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

C语言之字符串函数一相关推荐

  1. C语言常用字符串函数strlen、strcpy、strcat、strcmp、strchr

    C语言常用字符串函数,求串长strlen(char *s).串复制strcpy(char *s1,char *s2).串连接strcat(char *s1,char *s2).串比较strcmp(ch ...

  2. 【C语言】字符串函数详解

    hello~~,我是~小鹿 ,这是我的第一篇博客,没有循序渐进从基础开始写,只是最近在学习这里就写了,比较随心吧.希望这一篇博客能够给你带来帮助,之后也会继续写的,只是可能没有循序渐进,会比较杂七杂八 ...

  3. 超详细C语言的字符串函数讲解

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

  4. 【C语言】字符串函数strtok 按照指定字符串分割

    C语言字符串函数 strtok() 函数原型 char *strtok(char *str,const char *delimiters); 参数 str,待分割的字符串 delimiters,分隔符 ...

  5. c语言处理字符串函数的头文件,C语言字符处理函数 - 20131125的个人空间 - OSCHINA - 中文开源技术交流社区...

    C语言提供了丰富的字符串处理函数, 大致可分为字符串的输入.输出.合并.修改.比较.转换.复制.搜索几类. 使用这些函数可大大减轻编程的负担.用于输入输出的字符串函数,在使用前应包含头文件" ...

  6. C语言常见字符串函数、字符分类函数与内存函数的使用

    前言 C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中.下面介绍C语言中的一些常用的字符串函数和内存函数的功能以及实现原理. 字 ...

  7. C语言常用字符串函数——头文件 <string.h> 到底有什么?

    1. strlen -- 求字符串长度 1.1 strlen 的声明与用处 strlen ,我们有一些英语基础的话不难通过字面意思来知道这个函数是干嘛用的,str 表 string ,字符串的意思,l ...

  8. C语言常用字符串函数详解

    在C语言标准库里面,存在一个对字符串数组进行操作的函数的头文件为string.h. 常用的字符串函数有strlen,strcpy,strcat等等. 了解这些字符串函数是如何实现的可以有助于更好的使用 ...

  9. c语言初始化字符串 函数 manment,[转载]3.09进程(C语言班最后一天的课程)

    1,进程:是容器,是内存上的概念.线程是CPU的概念. 2,fork的作用是根据一个现有的进程复制出一个新进程,原来的进程称为父进程(Parents Process),新进程称为子进程(Child P ...

最新文章

  1. 获取jQuery中的复选框值
  2. Symantec Backup Exec Remote Agent 2010在Redhat Enterprise 6.6上启动问题
  3. AT2305-[AGC010D]Decrementing【博弈论】
  4. 2019-2020 ICPC Asia Hong Kong Regional Contest 补题(部分)
  5. 如何删除github远程仓库?三部搞定!
  6. Canalys:2021年第四季度苹果智能手机出货量占全球总量的22%
  7. Docker详解(五)——Docker基本使用
  8. deepin linux安装微信,Ubuntu20.04安装Deepin-wine,微信,Tim
  9. The processing instruction target matching [xX][mM][lL] is not allowed.
  10. 主键中mappedBy的具体使用及其含义
  11. 从零实现一个3D目标检测算法(1):3D目标检测概述
  12. eval函数python原理_Python 中 eval 函数的神奇用法
  13. cad断点快捷键_CAD中打断于点的快捷键
  14. 把FIL放在哪里最值钱
  15. 为什么数码相机可以拍出彩色照片?
  16. oracle恢复误删的表
  17. RecyclerView与CardView的使用
  18. 苏州交管局领导参观闪马智能,考察视频分析交通领域应用
  19. 蓝桥杯 ALGO-121 猴子分苹果 java
  20. 【转】windows安装jira

热门文章

  1. HTML+CSS+JavaScript实现下拉菜单效果
  2. php对接苹果cms采集接口,苹果cms的资讯采集api接口以及使用教程
  3. 兴业银行长沙分行“狂飙”,李军跻身湖南“头部投资人”?
  4. 安装Nvidia驱动并使用Anaconda搭建GPU环境(安装CUDA)+ PyTorch + TensorFlow + PyTorch Lightning
  5. 多核危机:Scala vs Erlang
  6. 公共wifi不再安全 看看这些商用wifi服务商
  7. MATLAB——图片自动编号、命名及保存
  8. 企消互动广告:网络时代广告活动的创新形式——兼谈杜丽反败为胜对企业的启示
  9. [CSP-S模拟测试]:回家(塔尖)
  10. 【课程设计】基于java GUI实现学生个人信息管理系统(源码+论文+ppt+视频)