1、在C语言中使用字符数组来模拟字符串,C语言没有字符串数据类型。
2、C语言中的字符串是以'\0'结束的字符数组
3、C语言中的字符串可以在栈上、堆空间、或制度存储区进行分配内存。
4、strlen()求字符串的长度,字符串长度不包含'\0',sizeof(类型)字符串类型的大小时,包括了‘\0’
(一)字符串的初始化
字符串初始化有两种方法,默认元素个数和指定元素个数。
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
//1 大{}号法 初始化列表
//数组初始化有2种方法 默认元素个数、指定元素个数
char buf1[] = { 'a', 'b', 'c', 'd', 'e' };//若没有指定长度,默认不分配零
//若指定长度,不够报错;buf长度多于初始化个数,会自动补充零
char buf2[6] = { 'a', 'b', 'c', 'd', 'e' };
char buf3[100] = { 'a', 'b', 'c', 'd', 'e' };
//char buf4[5] = {'a', 'b', 'c', 'd', 'e'}; #因为有'\0' 所以需要6个字符
printf("buf3:%s", buf3);
system("pause");
return 0;
}
int main()
{
//1 用字符串来初始化数组
char buf2[] = {'a', 'b','c','d','\0'};
//2 字符串常量初始化一个字符数组
char buf3[] = {"abcde"}; //结论:会补充零
char buf4[] = "abcde";
char buf5[100] = "abcde";
printf(" strlen(buf5) :%d \n", strlen(buf5));
printf(" sizeof(buf4) :%d \n", sizeof(buf5));
printf(" sizeof(buf4) :%d \n", sizeof(buf4));
}
(二)数组法和指针法操作字符串
字符数组名,是个指针,是个常量指针,代表字符数组首元素的地址,不代表整个数组。
当我们有了一个数组的首地址,这个首地址是被c编译器保护的,不能被做任何修改,因为数组的的变量名
也就是数组的首地址,如果一旦我们修改的首地址,那么这个数组就会‘’找不到‘’。
指针法:利用指针间接赋值,对字符串进行修改,(这里只能对栈区和堆区的字符串修改,在全局区的字
符串不可以修改) 如下代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
char *p ="sadfsaf";
char buf[] = { "adsad" };
printf("%s\n", p);
//p[2] = 'j'; //报错
buf[2] = '1';
printf("%s\n", buf);
system("pause");
return 0;
}
我们从内存四区的角度对上面代码进行分析,知道我们的变量的内存从哪里来到哪里去。
我们的代码在预编译,编译器先会将代码中所有的字符串常量在全局区进行内存分配,然后将其存入全局区,此时*p 和 buf[] 在栈中有内存,但是没有数据。
char *p ="sadfsaf";
char buf[] = { "adsad" };
当执行上面两句代码的赋值时,我们的内存会做如下变化:
即此时会让指针p指向全局区存储字符串"sadfsaf"的首地址,会将全局区的"adsad"字符串拷贝到栈上的buf里面。
因为buf在栈上有内存,我们使用buf[2] = '1' 实际上是修改栈上的buf,而不是全局区,而p是一个指针,*p是指针所指向的内存空间的值,因此p[2] ='j' 修改的是我们全局区的内存数据,这在c语言里面是不被允许的。我们使用数组法 buf[ ] = "sads"
会在栈上分配内存,但是我们使用指针 *p = "sads" 不会为字符串本身在栈上分配内存。