C语言基础Day4-数组

308 篇文章 0 订阅
68 篇文章 4 订阅
本文详细介绍了C语言中的数组,包括数组的定义、声明、初始化、长度计算、内存存储方式以及操作。讲解了数组的冒泡排序算法,并探讨了一维、二维及多维数组的特性和用法。此外,还涉及字符数组和字符串的概念,以及输入输出函数如scanf、gets和fgets的使用。最后,文章提到了如何避免输入函数导致的内存污染问题。
摘要由CSDN通过智能技术生成

C语言基础Day4-数组

一、数组定义

 将若干个相同的数据类型的变量存放在一块连续的内存中,同一个数组中所有的成员都是具有相同的数据类型,同时所有的成员在内存中的地址是连续的。

二、声明一个数组

  • 数组内每一个元素的类型由数组名前面的类型决定
  • 数组中的元素个数由[]里面的数值决定
  • 定义数组时,[]里面的值不可以是变量,只能是常量
  • 使用数组,[]里面的值可以是常量也可以是变量
  • 数值数组不可以整体操作
  • 数组的每一个元素都是变量
int num[10];

int num[10] = {1,2,3,4,5,6,7,8,9,10};

// 如果数组只初始化部分元素,其他元素被初始化为0
int num[10] = {1,2};
int num[10] = {0};// 将数组所有元素都初始化为0
int num[10] = {[5] = 5};// 将下标为5的元素赋值为5

int num[] = {1,2,3};// []中没有值 这个数组的元素个数由{}里面的元素个数决定

三、数组的长度

int num[10] = {0};
int n = sizeof(num) / sizeof(num[0]);// 数组长度

四、数组在内存中如何存储

 启动一个程序,系统会给这个程序分配一块内存空间;内存的最小单位是一个字节,内存中的每一个字节都会有编号,这个编号就是内存中的地址。

数据在内存中的地址,就是它在内存中的起始地址。

比如,int b,占用内存四个字节,那么这四个字节占用的地址分别是:0x1001、0x1002、0x1003、0x1004,那么b的内存地址就是起始地址:0x1001。

在这里插入图片描述

  • 说明:
    • a[0] 第0个元素
    • &a[0] 第0个元素的地址 == 01
    • 数组名a 代表数组,也代表第0个元素的地址 a == &a[0] == 01,所以说数组名是一个常量,是一个地址。
    • &a 取得是整个数组的地址 == 01 在数值上 &a[0],a,&a, 相等,但是意义不相同
    • &a[0] + 1 元素的地址加一 跨过一个元素 == 05
    • a+1 元素的地址加一 跨过一个元素 == 05
    • &a + 1 整个数组的地址加一,跨过整个数组 == 21
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	int a[5];
	printf("%u\n",&a[0]);
	printf("%u\n",a);// 数组名 就是第一个元素的地址
	printf("%u\n",&a);// 取出 数组的地址

	printf("%u\n",&a[0] + 1);//数组第一个元素 加一 跨过一个元素  + 4
	printf("%u\n",a + 1);// 元素的地址加一 跨过一个元素
	printf("%u\n",&a + 1);// 整个数组的地址加一  跨过整个数组

	return 0;
}

五、冒泡排序

在这里插入图片描述

冒泡排序:相邻的两个元素进行比较,前面的比后面的大,两个元素进行交换,如果数组有n个元素,那么总共需要交换n - 1轮,每i轮交换n - i次。

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	int a[5] = {2,5,6,3,-1};
	/*printf("%u\n",&a[0]);
	printf("%u\n",a);// 数组名 就是第一个元素的地址
	printf("%u\n",&a);// 取出 数组的地址

	printf("%u\n",&a[0] + 1);//数组第一个元素 加一 跨过一个元素  + 4
	printf("%u\n",a + 1);// 元素的地址加一 跨过一个元素
	printf("%u\n",&a + 1);// 整个数组的地址加一  跨过整个数组*/

	int n = sizeof(a) / sizeof(a[0]);// 计算数组有多少个元素  将数组所有字节长度除以单个元素的长度

	for (int i = 0; i < n - 1; i++)
	{
		// 外层循环 主要是控制循环次数
		// 内层循环主要是控制每一次循环的比较次数
		for (int j = 0; j < n - i - 1; j++)
		{
			if (a[j] > a[j+1])
			{
				// 交换元素
				int t = a[j];
				a[j] = a[j+1];
				a[j+1] = t;
			}
		}
	}

	for (int i = 0; i < n; i++)
	{
		printf("%d ",a[i]);
	}

	return 0;
}

六、二维数组

在这里插入图片描述

  • 二维数组在概念上是二维的:其下标在两个方向上变化,对其访问一般需要两个下标
  • 在内存中并不存在二维数组,二维数组实际的硬件存储器是连续编址的,也就是说内存中只有一维数组,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的。
  • int a[2][4] 定义了一个二维数组,二维数组有两个一维,每个一维数组有四个元素,那么二维数组的a[0]代表第0行

6.1 数组的初始化

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };// 二维数组的初始化

	// 如果给二维数组的部分元素初始化,其他元素为0
	int b[3][4] = { 1,2,3 };

	int c[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};// 二维数组本质上还是一维数组  可以自动计算下标

	int d[][3] = { 1,2,3,4,5 };// 二维数组定义时 不能省略列的下标 可以省略行的下标 可以自动计算行的下标

	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ",d[i][j]);
		}
	}

	return 0;
}

6.2 计算数组的行数和列数

  • 计算数组元素的总个数:sizeof(a) / sizeof(a[0][0]);
  • 计算数组的行数:sizeof(a) / sizeof(a[0]); a[0]代表一行元素的大小
  • 计算数组的列数:sizeof(a[0]) / sizeof(a[0][0]);一行元素的字节数除以一个元素的字节数
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };// 二维数组的初始化

	int n = sizeof(a) / sizeof(a[0][0]);// 计算元素的总个数
	int row = sizeof(a) / sizeof(a[0]);// 计算数组的行数  二维数组的大小除以一行的大小
	int column = sizeof(a[0]) / sizeof(a[0][0]);// 计算数组的列数  一行的大小除以一个元素的大小

	printf("%d %d %d\n",n,row,column);
	
	return 0;
}

6.3 数组名

在这里插入图片描述

int a[2][3];

* a[0][0]0行第0个元素
* &a[0][0]0行第0个元素的地址
* a[0]  代表第0行一维数组的数组名,也代表第0行一维数组的地址a[0] = &a[0][0]
* &a[0]0行的地址 = 01
* a 二维数组的数组名 代表二维数组,也代表首行地址&a[0]
* &a 二维数组的地址

* &a[0][0] + 1  元素地址加1,跨过一个元素
* a[0] + 1      元素地址加一,跨过一个元素
* &a[0] + 1     行地址加一,跨过一行
* a + 1         行地址加一,跨过一行
* &a + 1        二维数组地址加一,跨过整个数组
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };// 二维数组的初始化

	int n = sizeof(a) / sizeof(a[0][0]);// 计算元素的总个数
	int row = sizeof(a) / sizeof(a[0]);// 计算数组的行数  二维数组的大小除以一行的大小
	int column = sizeof(a[0]) / sizeof(a[0][0]);// 计算数组的列数  一行的大小除以一个元素的大小

	printf("%d %d %d\n",n,row,column);

	printf("%u\n",&a[0][0]);
	printf("%u\n",a[0]);
	printf("%u\n",&a[0]);
	printf("%u\n",a);
	printf("%u\n",&a);

	printf("%u\n",&a[0][0] + 1);// 只加上一个元素地址
	printf("%u\n",a[0] + 1);// 只加上一个元素的地址
	printf("%u\n",&a[0] + 1);// 加上一行元素的地址
	printf("%u\n",a + 1);// 加上一行元素的地址
	printf("%u\n",&a + 1);// 加上整个数组的元素地址

	
	return 0;
}

七、多维数组

 int num[2][3][4]; 定义了一个三维数组,有两个二维数组,每一个二维数组都有三个一维数组,每一个一维数组有四个元素。

八、字符数组

 字符串就是字符数组中有\0字符的数组,因为有\0字符的字符数组,操作起来方便,数字0(字符’\0’的ACSII码)结尾的char数组就是一个字符串,但是如果chaR数组没有以数字0结尾,那么就不是一个字符串,只是普通的字符数组,所以字符串是一种特殊的char数组。

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	char a[5] = {'a','b','c','d','\0'};// 字符数组中含有\0字符的 就是字符串
	char b[5] = "abcd";// 定义了一个字符数组 存的是abcd\0
	char c[] = "world";// 数组的长度是6  字符串
	char d[100] = "abc";// 定义了一个字符数组 有100个元素 其他元素都是\0
	char e[100] = {0};// 将一个字符数组清0 0是字符'\0' 的acsii码

	for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		printf("%d ",a[i]);// 单个打印字符  十进制形式打印
	}
	printf("\n");
	// 字符数组也可以当作字符串进行打印 只要直到数组的首地址
	printf("%s\n",a);
	printf("%s\n",b);
	printf("%s\n",c);
	printf("%s\n",d);
	printf("%s\n",e);// 全部都是空格
	
	return 0;
}

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	char a[128] = "abcd\0def\0";

	printf("%d\n",sizeof(a));// 128
	printf("%s\n",a);// 打印abcd
		

	return 0;
}
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	char a[] = {'a','b','c'};// 普通的字符数组
	printf("%d\n",sizeof(a));// 输出3
	printf("%s\n",a);// 没有字符0 结尾  输出abc烫烫 乱码
	return 0;
}

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	char a[] = {'a','b',0,'c'};// 中间有0 表示'\0'
	char b[] = {'a','b','0','c',0};// 中间的0字符会被打印 因为acsii是48
	char c[] = {'a','b','c','\0','v'};// 打印abc

	printf("%s\n",a);// 打印ab
	printf("%s\n",b);// 打印ab0c
	printf("%s\n",c);// 打印abc

	return 0;
}

九、scanf输入字符串

遇到回车结束,遇到空格也结束,同时,如果存放读取字符的空间不足,继续想后面存放字符,没有’\0’字符,那么打印的时候会直接将所有的字符都打印,即使超过字符数组的长度,这就造成了内存污染

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	char num[128] = "";// 字符数组清0
	scanf("%s",num);// 从键盘中获取一个字符串  遇到回车结束 不需要取地址符
	printf("%s\n",num);// %s 要的是打印字符数组的首元素地址

	return 0;
}

十、gets函数

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	// gets函数遇到\n结束  但是遇到空格不会结束 读取空格  但是也会造成内存污染
	char num[128] = "";// 字符数组清0
	gets(num);// 参数是存放读取字符串的地址
	printf("num = %s\n",num);

	return 0;
}

十一、fgets()函数

 库函数:从键盘读取一个字符串;char num[128]; fgets(num,sizeof(num),stdin);// fgets从stdin(标准输入-键盘)读取字符串到num数组中,最大可以读取sizeof(num) - 1个字符,因为后面需要加上’\0’;

  • 如何将最后一个字符重置成’\0’
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)

int main()
{
	char buf[128] = "helloA";

	// 将字符串最后一个字符置为'\0'
	// 首先需要找到最后一个字符的下标
	// 求的是字符数组的有效字符个数

	int i = 0;
	while (buf[i] != '\0')
	{
		i++;
	}
	// 最后i 落了下标6的位置
	printf("%d\n",i);

	buf[i - 1] = '\0';// 将最后一个字符置为'\0'
	printf("%s\n",buf);// 打印hello

	return 0;
}

使用strlen()函数计算字符数组的有效字符个数,然后将最后一个字符置为’\0’

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#include<stdlib.h>
#include<string.h>

int main()
{
	char buf[128] = "helloA";

	// 将字符串最后一个字符置为'\0'
	// 首先需要找到最后一个字符的下标
	// 求的是字符数组的有效字符个数

	int i = strlen(buf);// strlen() 计算字符数组有效字符的个数

	buf[i - 1] = '\0';// 将最后一个字符置为'\0'


	printf("%s\n",buf);// 打印hello

	return 0;
}


#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#include<stdlib.h>
#include<string.h>

int main()
{
	//fgets会把回车键读取
	char buf[1024] = "";
	fgets(buf,sizeof(buf),stdin);// 读取换行符
	buf[strlen(buf) - 1] = '\0';// 将换行符直接置为'\0'
	printf("%s\n",buf);// 打印hello

	return 0;
}

十二、字符数组的输出

  • puts、fputs函数
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#include<stdlib.h>
#include<string.h>

int main()
{
	char buf[1024] = "helloworld";
	puts(buf);// 自动输出一个换行
	fputs(buf,stdout);// 第一个参数,数组首元素地址 stdout标准输出(屏幕)


	return 0;
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少写代码少看论文多多睡觉

求打赏,求关注,求点赞

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值