P 120 数组应用案例 2023/1/29
一、应用案例
案例一:创建一个char类型的26个元素的数组,分别 放置’A’-'Z‘。使用for循环访问所有元素并打印出来。提示:字符数据运算 ‘A’+1 -> ‘B’
#include<stdio.h>
void main(){
/*
创建一个char类型的26个元素的数组,分别 放置'A'-'Z‘。使用for循环访问所有元素
并打印出来。提示:字符数据运算 'A'+1 -> 'B
*/
char arr[26];
int i;
for(i = 0; i < 26 ; i++){
arr[i] = 'A' + i; // 第一个是0,A+0依然是0
}
for(i = 0; i < 26; i++){
printf("arr[%d]=%c\n",arr,arr[i]);
}
getchar();
}
案例二:请求出一个数组的最大值,并得到对应的下标。
#include<stdio.h>
void main(){
/*
请求出一个数组的最大值,并得到对应的下标。
分析:
1.自定义数组大小5
2.假定第一个元素max= arr[0]就是最大值,然后我们依次和数组后面的数进行比较,
如果发现有比max更大的数,就相应的变化,遍历完整个数组,max就是最大数。
*/
int arr[] = {
0,-1,89,99,4};
int arrLen = sizeof(arr) / sizeof(int);
int max = arr[0];
int maxIndex = 0;
int i;
for(i = 1; i < arrLen; i++){
// 这里 i 的初始值为1;因为为0则是和自己比较没有意义
// 发现有比max更大的数,就相应的变化
if(arr[i] > max){
max = arr[i];
maxIndex = i; // 对应下标就是i,所以把i 赋值即可
}
}
printf("max = %d maxIndex = %d",max,maxIndex); // 99,3
getchar();
}
P 121 字符串介绍和内存布局 2023/1/29
一、字符数组的介绍
基本介绍:用来存放字符的数组称为字符数组, 看几个案例。
char a[10]; //一维字符数组, 长度为10
char b[5][10]; //二维字符数组, 后面我们详细介绍二维数组
char c[20]={
'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a','m'}; // 给部分数组元素赋值
总结:字符数组实际上是一系列字符的集合,也就是字符串(String)。在C语言中,没有专门的字符串变量,没有string类型,通常就用一个字符数组来存放一个字符串。
#include<stdio.h>
void main(){
// c是一个一维字符数组,给部分元素赋值
char c[20]={
't','o','m'};
// 输出
printf("%s",c); // 输出tom
getchar();
}
二、字符串注意事项
- 在 C 语言中,字符串实际上是使用 null 字符 (‘\0’) [null字符就是\0,因为ASCII 0 表示空],终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。【以下为内存布局图】
- '\0’是ASCII码表中的第0个字符,用NUL表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在C语言中仅作为字符串的结束标志。
- 字符数组(字符串)在内存中的布局分析 [案例]。
- 思考 char str[3] = {‘a’,‘b’,‘c’} 输出什么? 为什么?
char c[7]={
't','o','m'};
// 正常输出tom
char str[3] = {
'a','b','c'};
// 输出a,b,c后,后面可能会出现乱码,一些垃圾值
char str[] = {
'a','b','c'};
// 不指定长度,输出结果可能同样会出现乱码
分析示意图:
结论:如果在给某个字符数组赋值时,(1)赋给的元素的个数小于该数组的长度,则会自动在后面加 ‘\0’, 表示字符串结束,(2)赋给的元素的个数等于该数组的长度,则不会自动添加 ‘\0’。
P 122 字符指针和内存布局 2023/1/30
一、字符串的访问和遍历
小结:因为字符串的本质就是字符数组,因此可以按照数组的方式遍历和访问某个元素即可, 案例如下:
#include<stdio.h>
#include<string.h>
void main(){
// 这种方式定义字符数组不会出现任何的乱码,会自动添加一个\0
char greeting[] = "Hello";
int i;
int len = strlen(greeting); // len = 5
printf("\n greeting = %s",greeting);
printf("\nlen=%d", len);
printf("\n字符串第3个字符是=%c", greeting[2]); // 下标是从0开始的,第三个字符
for(i = 0; i < len; i++) {
printf("\n%c", greeting[i]);
}
getchar();
}
- 内存布局
二、字符串的表示形式
- 用字符数组存放一个字符串
1 . char str[]=“hello tom”;
2 . char str2[] = {‘h’, ‘e’};
- 用字符指针指向一个字符串
1 . 比如: char pStr=" hello";*
#include<stdio.h>
void main(){
// 使用一个指针pStr,指向一个字符数组
char* pStr = "Hello";
printf("\n pStr指向的字符串= %s",pStr); // 输出Hello
getchar();
}
2 . 总结:
- C语言对字符串常量" hello"是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量str时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给pStr。
- 内存布局图
- printf(“%s\n”,str); 可以输出 str 指向的字符串。
三、两种方法表示字符串的讨论
-
字符数组由若干个元素组成,每个元素放一个字符;而字符指针变量中存放的是地址(字符串/字符数组的首地址),绝不是将字符串放到字符指针变量中(是字符串首地址)。
-
对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值:
char str[14]; // str 实际是一个常量
str=" hello tom"; //错误
str[0] = 'i'; //ok ,因为只是找到第一个元素在那里填了一个i而已
内存布局图:
- 对字符指针变量,采用下面方法赋值, 是可以的:
#include<stdio.h>
void main(){
char* a="yes";
// 赋值前的地址:
printf("\na本身的地址是%p,指向的地址是%p",&a,a);
a=" hello tom"; // 定义一个字符指针变量时,可以多次赋值
// 赋值后的地址:
printf("\na本身的地址是%p,指向的地址是%p",&a,a);
printf("\n%s",a);
getchar();
}
内存布局图:
- 如果定义了一个字符数组,那么它有确定的内存地址(即字符数组名是一个常量);而定义一个字符指针变量时,它并未指向某个确定的字符数据,并且可以多次赋值 [代码+图解]。
P 123 字符数组注意事项和细节 2023/1/31
一、字符串相关函数回顾
- 常用字符串函数一览
序号 | 函数 | 目的 |
---|---|---|
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