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" 不会为字符串本身在栈上分配内存。