46 字符数组和字符串
1,用来存放字符的数组称为字符数组
2,字符数组实际上是一系列字符的集合,也就是字符串(String),在C语言中,没有专门的字符串变量,没有 string 类型,通常就用一个字符数组来存放一个字符串
3,C语言中,字符串实际上是使用 null 字符 ( ' \0 ' ) 终止的一维字符数组,因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
4,' \0 ' 是 ASCII 码表中的第0个字符,用NULL表示,称为空字符,该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在C中仅作为字符串的结束标志。
5,字符数组(字符串)在内存中的布局分析
① 字符数组 c 分配了7个字节,但是它的字符串长度只有3占3个字节,所以系统会自动在 'm' 的后面再添加一个 '\0' 作为字符串的结束标志
②字符数组 str 只分配了3个字节,它本身的字符串长度也是3个字节,没有多余的空间让系统添加一个 '\o' ,会异常输出
1 void main() { 2 char str1[7] = { 't','o','m' }; 3 char str2[3] = { 'a','b','c' }; 4 printf("str1=%s\n", str1); 5 printf("str2=%s\n", str2); 6 }
str1 正常输出,str2输出 abc 后,没有找到字符串的结束标志 '\0' ,会继续输出,直到输出 m 时在后面遇到了 '\0' 为止。
若将第2行改为 char str2[4] = { 'a','b','c','\0'}; ,手动添加一个 '\0' ,就能正常输出 tom
⑥如果在给某个字符数组赋值时,赋给的元素的个数小于该数组的长度,则会自动在后面加 '\0' ,表示字符串结束。赋给的元素的个数等于该数组的长度时,则不会自动添加 '\0',
char str[] = { 'a','b','c' }; 没有定义字符数组的长度时,系统也不会自动添加 '\0',abc后面输出仍是乱码
6,字符串的访问和遍历
①因为字符串的本质就是字符数组,因此可以按照数组的方式遍历和访问某个元素,
1 #include<stdio.h> 2 #include<string.h> 3 void main() { 4 char greeting[] = "hello"; 5 6 //1,字符串长度 7 int len = strlen(greeting); 8 printf("字符串的长度为:%d\n", len); 9 10 //2,字符串的访问 11 printf("字符串第2个字符是%c\n", greeting[1]); 12 13 //3,遍历字符串 14 for (int i = 0;i < len;i++) { 15 printf("%c ", greeting[i]); 16 } 17 }
②对应的内存分析图
7,字符串的表示形式
①用字符数组存放一个字符串
如:char str[ ] =" hello tom " ;
char str2[ ] = { 'h' , 'e' } ;
②用字符指针指向一个字符串
如:char* pstr=" hello tom " ;
C 语言中对字符串常量“ hello tom " 是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量 str 时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给 pstr
printf(" %s \n" ,pstr) ; 可以输出 str 指向的字符串
对应的内存布局:
pstr 是一个字符指针,存储的是字符串常量”hello " 的地址(字符数组的首地址),指向的是 “ hello"
8,①字符数组由若干个元素组成,每个元素放一个字符,而字符指针变量中存放的是地址(字符串/字符数组的首地址),绝不是将字符串放到字符指针变量中
②对字符数组只能对各个元素赋值,不能用以下方式对字符数组赋值
这里的 str 实际上是一个常量,在内存中开辟了14个字节存储这个常量,不能修改str这个值,不能再给它赋值” hello tom "
③对字符指针变量,采用下面的方法赋值,是可以的
void main() {
char* a = "yes";
a = "hello tom";
}
a 是一个字符指针,存储的是 yes 的地址,指向的 yes 这个字符串常量,执行 a = "hello tom " 时,a 这个字符指针存储的是 "hello tom"的地址,指向的是” hello tom “
如果定义了一个字符数组,那么它有确定的内存地址(即字符数组名是一个常量),而定义一个字符指针变量时,它并未指向某个确定的字符数组,并且可以多次赋值。
9,字符串相关函数
常用字符串函数
10,字符串(字符数组)使用细节:
①程序中往往靠检测 ' \0 ' 的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度,因此,字符串长度不会统计 ' \0 ' ,字符数组长度会统计
②在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度,否则,在输出字符数组时可能出现未知字符。
③系统对字符串常量也自动加一个 '\0' 作为结束符,录入“ C progrom” 共有9个字符,但在内存中占用10个字节,最后一个字节 ' \0 ' 是系统自动加上的。(通过 sizeof()可以验证)
④定义字符数组时,如果给的字符个数比数组的长度小,则系统会默认将剩余的元素空间,全部设置为 ' \0 ' ,比如 char str[6] = "ab" ,str 内存布局就是: [a][b][\0][\0][\0][\0]
⑤字符数组定义和初始化的方式比较多
1 void main() { 2 char str1[] = { "I am happy" }; //默认后面加 '\0' 3 char str2[] = "I am happy"; //省略{},默认后面加'\0' 4 char str3[] = { 'I',' ','a','m',' ','h','a','p','p','y' };//字符数组后面不会加'\0',可能有乱码 5 char str4[5] = { 'C','h','i','n','a' };//字符数组后面不会加'\0',可能有乱码 6 char* pstr = "hello"; 7 8 printf("str1=%s\n", str1); 9 printf("str2=%s\n", str2); 10 printf("str3=%s\n", str3); 11 printf("str4=%s\n", str4); 12 printf("pstr=%s\n", pstr); 13 }