文章目录
- 字符数组基本介绍
- 字符串注意事项
- 字符串的访问和遍历
- 字符串的表示形式
- 用字符数组存放一个字符串: 用字符数组存放一个字符串,
- 用字符指针指向一个字符串
- 使用字符指针变量和字符数组两种方法表示字符串的讨论
- 字符串相关函数
- 常用字符串函数一览
- 字符串函数应用案例
- 字符串(字符数组)使用注意事项和细节
- 字符串(字符数组)课堂练习
字符数组基本介绍
用来存放字符的数组称为字符数组, 看几个案例
1)char a[10]; //一维字符数组, 长度为 10
2)char b[5][10]; //二维字符数组, 后面我们详细介绍二维数组
3)char c[20]={‘c’, ’ ', ‘p’, ‘r’, ‘o’, ‘g’, ‘r’, ‘a’,‘m’}; // 给部分数组元素赋值
字符数组实际上是一系列字符的集合,也就是字符串(String)。在 C 语言中,没有专门的字符串变量,没有 string 类型,通常就用一个字符数组来存放一个字符串。
字符串注意事项
1)在 C 语言中,字符串实际上是使用 null 字符 (’\0’) 终止的一维字符数组。因此,一个以 null 结尾的字符串, 包含了组成字符串的字符。
2)’\0’是 ASCII 码表中的第 0 个字符,用 NUL 表示,称为空字符。该字符既不能显示,也不是控制字符,输出该 字符不会有任何效果,它在 C 语言中仅作为字符串的结束标志。
3)字符数组(字符串)在内存中的布局分析 [案例]
4)思考 char str[3] = {‘a’,‘b’,‘c’} 输出什么? 为什么?
输出abc
结论:如果在给某个字符数组赋值时,
(1)赋给的元素的个数小于该数组的长度,则会自动在后面加 ‘\0’, 表示 字符串结束,
(2)赋给的元素的个数等于该数组的长度,则不会自动添加 ‘\0’
char str2[] = {‘t’,‘m’,‘o’} 输出什么? 输出的是 tmo 乱码
5)案例演示
#include <stdio.h>
void main() { //c 是一个一维字符数组,给部分元素赋值 char c[7]={'t','o','m'}; char str[4] = {'a','b','c'}; char str2[] = {'j','a','c','k'}; // 这个后面系统也不会自动添加 '\0' char str3[] = {'t','m','o'};//输出 c , 系统会这样处理 //1. 从第一个字符开始输出,直到遇到 \0 , 表示该字符串结束 printf("\nc=%s", c); printf("\nstr=%s", str); // abc? printf("\nstr2=%s", str2); // jack 乱码 printf("\nstr3=%s", str3); // }
字符串的访问和遍历
因为字符串的本质就是字符数组,因此可以按照数组的方式遍历和访问某个元素即可, 案例如下
#include <string.h>
#include <stdlib.h>
#include <stdio.h> void main() { char greeting[] = "Hello"; //如果将char greeting[] 改成 char* greeting 对下列式子无任何变化int i; //strlen 获取字符数组长度 int len = strlen(greeting); // len = 5 printf("\ngreeting=%s", greeting); printf("\nlen=%d", len); //5 printf("\n 字符串第 3 个字符是=%c", greeting[2]); //l printf("\n"); for(i = 0; i < len; i++) { //遍历 printf("%c ", greeting[i]); //H e l l o }system("pause");
}
对应的内存分析图
字符串的表示形式
用字符数组存放一个字符串: 用字符数组存放一个字符串,
1 )char str[]=“hello tom”;
2)char str2[] = {‘h’, ‘e’};
用字符指针指向一个字符串
比如:char* pStr=" hello tom";
1)C 语言对字符串常量" hello tom"是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程 序在定义字符串指针变量 str 时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给 pStr
2)printf("%s\n",str); 可以输出 str 指向的字符串
3)对应的内存布局图(!!)
使用字符指针变量和字符数组两种方法表示字符串的讨论
1)字符数组由若干个元素组成,每个元素放一个字符;而字符指针变量中存放的是地址(字符串/字符数组的首地址),绝不是将字符串放到字符指针变量中(是字符串首地址)
2)对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值
char str[14];
str=" hello tom"; //错误 str是常量
str[0] = 'i'; //ok
3)对字符指针变量,采用下面方法赋值, 是可以的
char* a="yes";
a=" hello tom";
a本身的地址不会发生变化,a指向的地址会发生变化
a本身的地址 -> &a ,a 指向的地址 a
printf(“a本身的地址为 %p,a指向的地址为 %p”, &a,a);
4)分析上面的结论
5) 如果定义了一个字符数组,那么它有确定的内存地址(即字符数组名是一个常量);而定义一个字符指针变量时, 它并未指向某个确定的字符数据,并且可以多次赋值
字符串相关函数
常用字符串函数一览
序号 | 函数&目的 |
---|---|
1 | strcpy(s1,s2);复制字符串s2到字符串s1 |
2 | strcat(s1,s2); 连接字符串s2到字符串s1的末尾 |
3 | strlen(s1);返回字符串s1的长度 |
4 | strcmp(s1,s2);如果s1,s2相同,则返回0,如果s1 < s2 则小于 0 如果s1 > s2 则大于0 |
5 | strchr(s1,ch);返回一个指针,指向字符串s1中字符ch的第一次出现的位置 |
6 | strstr(s1,s2);返回一个指针,指向字符串s1中的字符串s2第一次出现的位置 |
字符串函数应用案例
#include <stdio.h>
#include <string.h> void main() { char str1[12] = "Hello"; char str2[12] = "World"; char str3[12]; int len ; // 复制 str1 到 str3 strcpy(str3, str1); // str3 内容 "Hello" printf("strcpy( str3, str1) : %s\n", str3 ); //"Hello" // 连接 str1 和 str2 strcat( str1, str2); printf("strcat( str1, str2): %s\n", str1 ); //"HelloWorld"// 连接后,str1 的总长度len = strlen(str1);// printf("strlen(str1) : %d\n", len );//10 }
字符串(字符数组)使用注意事项和细节
1) 程序中往往依靠检测 ‘\0’ 的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。因此,字 符串长度不会统计 ‘\0’, 字符数组长度会统计 [案例]
2) 在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度, 否则,在输出字符数组 时可能出现未知字符.
3)系统对字符串常量也自动加一个’\0’作为结束符。例如"C Program”共有 9 个字符,但在内存中占 10 个字节, 最后一个字节’\0’是系统自动加上的。(通过 sizeof()函数可验证)
4)定义字符数组时,如果 给的字符个数 比 数组的长度小,则系统会默认将剩余的元素空间,全部设置为 ‘\0’, 比 如 char str[6] = “ab” , str 内存布局就是 [a][b][\0][\0][\0][\0]
5)字符数组定义和初始化的方式比较多,比如
#include <stdio.h> void main() { char str1[ ]={"I am happy"}; // 默认后面加 '\0' char str2[ ]="I am happy"; // 省略{}号 ,默认后面加 '\0'char str3[ ]={'I',' ','a','m',' ','h','a','p','p','y'}; // 字符数组后面不会加 '\0', 可能有乱码 char str4[5]={'C','h','i','n','a'}; //字符数组后面不会加 '\0', 可能有乱码 char * pStr = "hello";//ok printf("\n str1=%s", str1); printf("\n str2=%s", str2);//ok printf("\n str3=%s", str3);//乱码 printf("\n str4=%s", str4);//乱码
}
字符串(字符数组)课堂练习
char str[ ];
str="I am happy";
题 1 错误,因为 str 是常量