C语言学习笔记——数组

1.数组介绍

数组可以存放多个同一类型数据组也是一种数据类型,是构造类型。传递是以引用的方式传递(即传递的是地址)

2.数组代码示例

  1. 一个养鸡场有 6 只鸡,它们的体重分别是 3kg,5kg,1kg,3.4kg,2kg,50kg 。请问这六只鸡的总体重是多少?平 均体重是多少? 请你编一个程序
    #include<stdio.h>
    void main() {
    	//一个养鸡场有 6 只鸡,它们的体重分别是 3kg, 5kg, 1kg,3.4kg, 2kg, 50kg 。请问这六只鸡的总体重是多少 ? 
    	//平均体重是多少 ? 请你编一个程序。
    	double hens[6];//申明一个可存放六个double类型数据元素的数组
    	hens[0] = 3;//数组的第一个元素为3
    	hens[1] = 5;//数组的第二个元素为5
    	hens[2] = 1;数组的第三个元素为1
    	hens[3] = 3.4;//数组的第四个元素为3.4
    	hens[4] = 2;//数组的第五个元素为2
    	hens[5] = 50;//数组的第六个元素为50
    	double totalWeitght = 0.0, avgWeight;
    	int i;
    	for (i = 0; i < 6; i++) {
    		totalWeitght += hens[i];//遍历每个数组元素得到数组所有数的总和
    	}
    	avgWeight = totalWeitght / 6;
    	printf("六只鸡的总体重为%.1f,平均体重为%f", totalWeitght, avgWeight);
    }

  2. 求出数组的总长度和个数

    #include<stdio.h>
    void main() {
    	int arr[20], arrLen;
    	//sizeo(arr)得到的是数组arr的总大小,单位为byte
    	//sizeof(int)得到的是数据类型int的单位大小,单位为byte
    	//因此sizeof(arr) / sizeof(int)可以理解为总长度除以单位长度
    	//也就得到了数组的长度
    	arrLen = sizeof(arr) / sizeof(int);
    	printf("arr[20]的总大小为%d\n", sizeof(arr));
    	printf("arr[20]的数组元素个数为%d\n", arrLen);
    }

3.数组定义和内存布局

3.1.数组的定义

数据类型 数组名[数组大小]
int num[7];// num为数组名字,nnum数组的类型为int,num数组最多存放七个int类型的数据

3.2.数组的内存图

  1.  数组名就代表该数组的首地址 ,即a[0]地址
    #include<stdio.h>
    void main() {
    	int num[3];
    	num[0] = 1;
    	num[1] = 2;
    	num[2] = 3;
        //num指向num数组的首地址,即num指向num[0]的地址
    	printf("%p %p", &num[0], num);
    }

  2. 数组的各个元素是连续分布

    #include<stdio.h>
    void main() {
    	int num[3];
    	num[0] = 1;
    	num[1] = 2;
    	num[2] = 3;
    	//int类型的数据占4byte,因此每个数组元素的地址都差4byte
    	printf("%p %p %p", &num[0], &num[1], &num[2]);
    }

3.3.访问数组元素

数组名[下标] 比如:你要使用 a 数组的第三个元素 a[2], 下标是从 0 开始计算

3.4.代码示例

从终端循环输入 5 个成绩,保存到 double 数组,并输出

#include<stdio.h>
void main() {
	double score[5];//定义一个能存放5个double类型的数组
	int i, arrLen;//用于遍历数组
	arrLen = sizeof(score) / sizeof(double);
	while (1) {
		for (i = 0; i < arrLen; i++) {
			printf("\n请输入五个成绩:");
			scanf_s("%lf", &score[i]);
		}
		for (i = 0; i < arrLen; i++) {
			printf("第%d位同学的成绩为:%f\n", i, score[i]);
		}
	}
}

3.5.三种初始化数组的方式

#include<stdio.h>
void main() {
	int arr1[3], arr2[3], arr3[3], i;
	arr1[3] = { 1, 2, 3 };//初始化数组方式1:
	arr2[] = { 1, 2, 3 };//如果在初始化数组时,直接指定值,可以省略数组大小
	for (i = 0; i < sizeof(arr3) / sizeof(int); i++) {//初始化数组方式3
		arr3[i] = i + 1;
	}
}

4.数组使用注意事项和细节

  1. 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化
  2. 数组创建后,如果没有赋值,则遵守如下规则:全局数组默认值 0,非全局数组初值是机器垃圾值(即:原来系统分配给这块空间的值)(类似全局变量和局部变量)
  3. 数组的下标是从 0 开始的,不是从 1 开始
  4. 数组下标必须在指定范围内使用,编译通过,在运行时会因为数组越界而异常中断
    int arr[5];//数组arr的长度是五个int类型的变量,有效下表为0-4
  5. C 的数组属构造类型, 是引用传递(传递的是地址),因此当把一个数组传递给一个函数时/或者变量,函数/变量操作数组会影响到原数组

    #include<stdio.h>
    void f1(int arr[]) {
    	printf("f1 函数中 的 arr 的地址 = %p\n", arr); 
    	arr[0] = arr[0] + 1;//对arr数组的第一个元素的值进行加一操作
    	}
    void main() {
    	int arr[3] = { 3,4,5 }; 
    	int i; 
    	printf("main 函数中 的 arr 的地址 = %p\n", arr);
    	f1(arr);//调用f1函数,传入的实际参数是arr数组的首地址
    	//遍历 main 函数中的 arr 
    	for (i = 0; i < 3; i++) {
    		printf("arr[%d]=%d ", i, arr[i]);//遍历输出arr数组的每一个元素
    	}
    }

5.数组应用案例

  1. 创建一个 char 类型的 26 个元素的数组,分别 放置'A'-'Z‘。使用 for 循环访问所有元素并打印出来
    //创建一个 char 类型的 26 个元素的数组,分别 放置'A' - 'Z‘。使用 for 循环访问所有元素并打印出来。
    #include<stdio.h>
    void main() {
    	char arr[26];//申明一个长度为26个char数据类型的数组
    	int i;//用于遍历数组,表明当前所正在遍历的数组的组号
    	for (i = 0; i < 26; i++) {
    		arr[i] = 'A' + i;
    	}
    	for (i = 0; i < 26; i++) {
    		printf("%c\n", arr[i]);
    	}
    }

  2.  请求出一个数组的最大值,并得到对应的下标

    #include<stdio.h>
    void main() {
    	int arr[7], i;//定义一个长度为7个int数据类型的数组,i用于遍历数组和输出当前下标
    	for (i = 0; i < sizeof(arr) / sizeof(int); i++) {
    		printf("请输入要存入的数字:");
    		scanf_s("%d", &arr[i]);
    	}
        //MAX用于存放最大值,MAXi存放数组中最大值的下标
        //MAX默认为arr[0],即数组第一个数;MAXi为数组第一个数的下标
    	int MAX = arr[0], MAXi = 0;
    	for (i = 0; i < sizeof(arr) / sizeof(int); i++) {
    		if (MAX < arr[i]) {
    			MAX = arr[i];//如果当前遍历的数组大于MAX中存放的数值,则将该值赋值给MAX
    			MAXi = i;//用于保存该值的下标
    		}
    	}
    	printf("该数组中的最大值为%d,存放该最大值的数组下标为%d", MAX, MAXi);
    }

6.字符数组与字符串

6.1.字符数组基本介绍

  1. char a[10]; //一维字符数组, 长度为 10
  2. char b[5][10]; //二维字符数组
  3. char c[20]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a','m'}; // 给部分数组元素赋值
  4. 字符数组实际上是一系列字符的集合,也就是字符串(String)。在 C语言中,没有专门的字符串变量,没有 string 类型,通常就用一个字符数组来存放一个字符串

6.2.字符串注意事项

  1. 在 C 语言中,字符串实际上是使用 null 字符 ('\0') 终止的一维字符数组。因此,一个以 null 结尾的字符串, 包含了组成字符串的字符(未定义完全的字符数组,在已定义的最后一个字符后的第一个字符中存入"\0",当计算机遍历到"\0"时,就知道该字符数组定义到上一个字符为止,不再继续向后遍历)
  2. '\0'是ASCII 码表中的第 0 个字符,用NULL表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在 C 语言中仅作为字符串的结束标志
  3. //在给某个字符数组赋值时,应当注意字符数组的大小
    //如果刚好赋值的元素的个数刚好等于字符数组的长度
    //则系统无法自动给已赋值的元素末尾加上\0
    //此时如果输出该字符数组,则有可能导致输出错误
    char str[3] = {'a','b','c'};
    printf("str = &s", str);

    在给某个字符数组赋值时,应当注意字符数组的大小。如果刚好赋值的元素的个数刚好等于字符数组的长度,则系统无法自动给已赋值的元素末尾加上\0,此时如果输出该字符数组,则有可能导致输出错误

6.3.字符串的访问和遍历

//按照数组方式遍历即可
#include<stdio.h>
void main() {
	char arr[9] = "jiangnan";
	int i;
	for (i = 0; i < sizeof(arr) / sizeof(char) - 1; i++) {
		printf("%c", arr[i]);
	}
}

6.4.字符串的表达形式

6.4.1.用字符数组存放一个字符串

  1. char str[]="hello tom";
  2. char str2[] = {'h', 'e'};

6.4.2.用字符指针指向一个字符串

char* pStr=" hello tom";
  1. C语言对字符串常量" hello tom"是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量 str 时,只是把字符串首地址(即存放字符串的字符数组的首地址)赋给 pStr(先定义了一篇内存内存,用来存放字符数组,再将存放该字符数组的内存空间的首地址赋值给pStr,使其指向该字符数组的首地址
  2. printf("%s\n",str); 可以输出 str 指向的字符串

6.4.3.使用字符指针变量和字符数组两种方法表示字符串的讨论

  1. 字符数组由若干个元素组成,每个元素放一个字符;而字符指针变量中存放的是地址(字符串/字符数组的首址)(字符数组存放的是各个元素的数据,而字符指针变量存放的是字符数组的首地址;它们的区别可以参考值传递和地址传递)
  2. 对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值(这样会改变了str自身的地址,因此不能用次方法对字符数组赋值)
    char str[14]; 
    str=" hello tom";//错误 
    str[0] = 'i'; //ok

    str的本质上是一个常量,不可修改,且它是一个字符数组,而第二行代码中右边"hello tom"实质上是在内存中开辟了另一个新的内存空间,用于存放"hello tom"数组,如果这样赋值,str将会指向的是这一块新的内存空间,而不是开始定义的它本来的内存空间,即改变了它本身的地址

  3. 对字符指针变量,采用下面方法赋值, 是可以的(同样不能不改变自身的地址,但它是一个指针变量,它自身的内容就是地址,可以修改它的内容,即它所指向的地址,从而实现对字符数组的赋值)

    char* a="yes"; 
    a=" hello tom";

    第一局代码定义了一个名为a的字符指针变量,并使其指向存放"yes"的字符数组的内存空间的首地址;第二句代码,使a改为指向存放"hello tom"的字符数组的内存空间的首地址

  4. 如果定义了一个字符数组,那么它有确定的内存地址(即字符数组名是一个常量),(即不能修改自身的地址);而定义一个字符指针变量时, 它并未指向某个确定的字符数据,并且可以多次赋值(同样不能修改自身地址,但它是一个指针变量,它自身的内容就是地址,可以修改它的内容,即它所指向的地址,从而达到多次赋值

7.字符串相关函数

8.字符串(字符数组)使用注意事项和细节

  1. 程序中往往依靠检测 '\0' 的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。因此,字 符串长度不会统计 '\0', 字符数组长度会统计
  2. 在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度, 否则,在输出字符数组时可能出现未知字符(如果字符串的实际长度等于数组的长度,那么将会没有位置放 "\0",程序也就检测不到"\0",即检测不到哪里是字符串的结束位置
  3. 系统对字符串常量也自动加一个'\0'作为结束符。例如"C Program”共有 9 个字符,但在内存中占 10 个字节, 最后一个字节'\0'是系统自动加上的
  4. 定义字符数组时,如果 给的字符个数比数组的长度小,则系统会默认将剩余的元素空间,全部设置为 '\0', 比 如 char str[6] = "ab" , str 内存布局就是 [a][b][\0][\0][\0][\0]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值