一、字符串引入
二、字符串内存存放方式
三、字符串常用的API
1、输出字符串
2、获取字符串
3、字符串长度
4、字符串拷贝
编辑
5、断言函数
6、字符串拼接
7、字符串比较
8、查找子字符
9、查找字符串
10、字符串分割
四、malloc动态开辟内存空间
1、malloc函数
2、free函数
3、realloc函数
4、memset函数
一、字符串引入
【1】定义一个字符型数组,将逐个字符作为元素放入,对数组遍历访问字符,如下图所示。
【2】改进,定义一个字符串数组将字符串直接赋值给该数组,如下图所示。
【3】利用指针实现遍历,即对其地址进行偏移取其地址的内容,如下图所示。
【4】在利用指针的情况喜爱,对打印函数进行改进,对于printf()利用“%s”格式控制,即可输出。
【注意】第【2】种和第【3】种是不一致的,【2】是字符串变量,【3】是字符串常量(不允许被修改),在实际应用的过程中,这两者都是常用的。注意指针的操作:保存地址可以,修改指向,指向字符串常量的地址空间,对野指针的内存空间操作不行。
二、字符串内存存放方式
看这边这一段程序,就是计算一中第【1】和【2】种方式定义字符串的数组长度,如下图所示。
可以看到第【1】种定义方式按照我们所想的元素个数返回了长度5,那为什么第【3】种却返回了6呢,这是因为第【3】种这种方式是字符串赋值,最后一个字母后面会自动追加一个“\0”作为字符串的结束标志。在
三、字符串常用的API
1、输出字符串
【1】puts("");(自带换行)
【2】printf("%s",p);
2、获取字符串
【1】scanf("%s",p);
【2】gets,函数原型:char *get(char *str)
因为这个函数可以无限读取,易发生溢出,如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。
3、字符串长度
【区分sizeof与strlen】一句话概括就是,sizeof是计算整个数组的大小,strlen是计算有效字符的大小!如下图所示,strlen的运行结果始终为有效字符数且忽略字符串的结束标志“\0”,sizeof则会受定义的空间的影响,例如指针类型是8个字节(操作系统地址的大小),一个字符是1个字节等,即使定义了一个128个元素的数组,只给五个元素赋值,sizeof返回的也是128.
4、字符串拷贝
【1】strcpy——char *strcpy(char* dest, const char *src)
自己编写程序实现字符串拷贝
一下写法均可正确输出
【2】strncpy——char* strncpy(char *dest, const char *src, int n)
表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回或复制后的dest
下面进行自己编写实现同样功能的代码
源码加上了下图所示的处理
5、断言函数
#include
void assert(int expression)
assert的作用是现计算表达式expression,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort来终止程序运行。
assert的缺点:频繁的调用会极大的影响程序的性能,增加额外的开销
现定义一个字符型空指针,将其给函数MyStrcpy,观察是否有异常,如下图所示。
6、字符串拼接
一般用strcat函数来实现字符串拼接,如下图所示,拼接后的结果可以赋值给一个指针而且是在第一个输入的字符串基础上进行拼接。
接下来通过自己编写代码来实现,以下有不同种的做法
7、字符串比较
【1】strcmp——int strcmp(const char *str1, const char* str2);
若str1 = str2,则返回零;若str1 < str2,则返回负数;若str1 > str2,则返回正数
下面是自己进行实现该函数的测试
【2】strncmp——int strcmp(const char *str1, const char* str2, size_t n);
对str1和str2进行比较,最多比较前n个字节,若str1与str2的前n个字节相同,则返回0;若str1 > str2,则返回正数,若str1 < str2,则返回负数
8、查找子字符
函数原型:strchr——char* strchr(const char* str, int c);
函数作用:在参数str所指向的字符串中搜索第一次出现字符c(一个无符号字符)的位置
9、查找字符串
函数原型:strstr——char* strstr(char* str1, const char* str2);
函数作用:返回值:若str2是str1的子串,则返回str2在str1的首次出现的地址;若str2不是str1的子串,则返回NULL;
10、字符串分割
函数原型:char* strtok(char* str, const char* delim)
函数功能:分解字符串str为一组字符串,delim为分隔符
特别要注意分割处理后原字符串 str 会变,原字符串的改动是切分符原位置均更改为 '\0'。
四、malloc动态开辟内存空间
1、malloc函数
【1】函数原型:void *malloc(size_t size)
【2】函数功能:分配所需的内存空间,并返回一个指向它的指针
如下图所示,end没有正常输出,因为程序中的p是一个野指针,即没有指向具体的内存,会导致程序异常。
下面我们用malloc函数对p分配1个字节的内存空间,如下图所示。
我们还可以继续开辟新的内存空间并赋值给p,如下图所示。
2、free函数
【1】函数原型:void free(void *ptr)
【2】函数功能:释放之前调用calloc、malloc或realloc所分配的内存空间,目的是释放以及防止内存泄漏,还有就是防止悬挂指针
对上一小节“malloc函数”种最后一个程序进行分析,如下图所示,首先为了解决p这个野指针的问题开辟了1个字节的内存空间,之后为了存放更多的字节又开辟了12个字节的内存空间,如下图所示,这样最开始开辟的1个字节的内存空间就被限制了,此时应该被释放。
下面利用free函数对内存空间进行释放,如下图所示。
3、realloc函数
【1】函数原型:void *realloc(void *pts, size_t size)
【2】函数作用:扩容(追加空间),尝试重新调整之前调用malloc或calloc所分配的ptr所指向的内存块的大小。
对上一小节“free函数”中最后一个程序进行操作,如下图所示。
运行后发现没有输出,编写程序显然是没有问题的,那么问题应该是开辟的内存空间不够,那么现在利用realloc函数进行扩容。
4、memset函数
【1】函数原型:void *memset(void *str, int c, size_t n)
【2】函数作用:清理内存空间
下面演示清理malloc申请的12个字节的内存空间进行清理