郭炜-C语言程序设计-程序设计与算法(一)-第五周

本文详细介绍了C++中的数组概念,包括一维数组和二维数组的定义、初始化、遍历以及内存存放方式。强调了数组下标的使用规则,指出数组越界可能导致的运行错误。同时,给出了用数组实现筛法求素数和矩阵乘法的实际编程示例,展示了数组在简化程序结构和提高效率上的作用。
摘要由CSDN通过智能技术生成

第五周

1.数组的概念

  • 可以用来表达类型相同的元素的集合,集合的名字就是数组名。
  • 数组里的元素都有编号,元素的编号叫下标。通过数组名和下标,就能访问元素。
  • 一维数组的定义方法如下:
    类型名 数组名[元素个数];
  • 其中“元素个数”必须是常量或常量表达式,不能是变量,而且其值必须是正整数。元素个数也称作“数组的长度”。

T a[N];

  • T是类型名,如 int double string;N为正整数或者值为正整数的常量表达式。

  • 数组a有N个元素,每个元素都是一个类型为T的变量。N个元素在内存里是一个挨一个连续存放的。a数组占用大小总共为 N × sizeof(T) 字节的存储空间。

  • 表达sizeof(a)的值就是整个数组的体积,即N × sizeof(T)

int a[100];
//名字为a的数组,有100个元素,每一个元素都是一个int型的变量。

在这里插入图片描述

  • 数组下标从0开始,N个元素的数组,下标从0 至 N-1。
  • 数组名a代表数组的地址,假设为p,则变量a[i]的地址就是
    p+i*sizeof(int)

例题:接收键盘输入的100个整数,然后将它们按和原顺序相反的顺序输出。

self:
#include<iostream>
using namespace std;
int a[100];
int main(){
for(int i=0;i<100;++i)
     cin>>a[i];
for(int i=99;i>-1;--i)
	 cout<<a[i];     
return 0;    
}
teacher:
#include <iostream>
using namespace std;
#define NUM 100 //使用符号常量,便于修改
int a[NUM]; //数组一般不要定义在main里面,尤其是大数组
int main() {
for(int i = 0;i < NUM; ++i)
cin >> a[i];
for(int i = NUM-1;i >= 0; --i)
cout << a[i] << " ";
return 0;
}
  • 数组一般不要定义在main里面,尤其是大数组。

2.数组的初始化

  • 在定义一个一维数组的同时,就可以给数组中的元素赋初值:
    类型名 数组名[常量表达式]={值,值……值};
  • { }中的各数据值即为各元素的初值,值之间用逗号间隔。
  • 数组初始化时,{ }中值的个数可以少于元素个数。相当于只给前面部分元素赋值,而后面的元素,其存储空间里的每个字节都被写入二进制数0。
  • 数组初始化时,若常量表达式为空,那么值有几个,常量表达式为几。
//正常
int a[4]={1,2,3,4};
//值缺少
int a[4]={1,2};//等价于 int a[4]={1,2,0,0};
//常量表达式缺少
int a[]={1,2,3,4};//等价于 int a[4]={1,2,3,4};

例题:筛法求素数

  • 判断一个数n是不是素数,可以用2到 之间的所有整数去除n,看能否整除。如果都不能整除,那么n是素数(慢)。
  • 筛法求素数:把2到n中所有的数都列出来,然后从2开始,先划掉n内所有2的倍数,然后每次从下一个剩下的数(必然是素数)开始,划掉其n内的所有倍数。最后剩下的数,就都是素数。
#include<iostream>
using namespace std;
#define MAX_NUM 100000
char isPrime[MAX_NUM+10];
int main(){
	for(int i=2;i<=MAX_NUM;i++)
	   isPrime[i]=1;
	for(int i=2;i<=MAX_NUM;i++){
		if(isPrime[i])
			for(int j=2*i;j<=MAX_NUM;j+=i)
			isPrime[j]=0;
		
	}
	for(int i=2;i<=MAX_NUM;i++){
		if(isPrime[i])
		cout<<i<<" ";
	}
	return 0;
}
//bool
#include<iostream>
using namespace std;
#define MAX_NUM 10000000
bool isPrime[MAX_NUM+10];
int main(){
	for(int i=2;i<=MAX_NUM;i++)
	   isPrime[i]=true;
	for(int i=2;i<=MAX_NUM;i++){
		if(isPrime[i])
			for(int j=2*i;j<=MAX_NUM;j+=i)
			isPrime[j]=false;
		
	}
	for(int i=2;i<=MAX_NUM;i++){
		if(isPrime[i])
		cout<<i<<" ";
	}
	return 0;
}

3.用数组取代复杂分支结构

有时会用一个数组存放一些固定不变的值,以取代复杂的程序分支结构。

例题:星期问题

1.简单

接受一个整数作为输入,如果输入1,则输出“Monday”,输入2,则输出“Tuesday”……输入7,则输出“Sunday”,输入其他数,则输出“Illegal”。

#include<iostream>
#include<string.h>

using namespace std;
string a[8]= {"","Monday","Tuesday","Wednesday","Thursday",
              "Friday","Saturday","Sunday"
             };
int main() {
	int c;
	cin>>c;
	if(c<0||c>7) printf("illegal");
	else cout<<a[c];
	return 0;
}
2.复杂

例题: 已知2012年1月25日是星期三,编写一个程序,
输入用“年 月 日”表示的一个2012年1月25日以后的期,
输出该日期是星期几(星期天输出0)。

self:
#include<iostream>
using namespace std;
int month[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
int main() {
	int Y,M,D,days=0;
	cin>>Y>>M>>D;
	for(int i=2012; i<Y; ++i) {//注意小于号
		if(i%4==0&&i%100!=0||i%400==0)
			days+=366;
		else days+=365;
	}
	if(Y%4==0&&Y%100!=0||Y%400==0)
		month[2]=29;
	for(int i=1; i<M; ++i) {
		days+=month[i];
	}
	days+=D;
	days-=22;
	cout<<(days%7);
	return 0;
}
teacher:
#include <iostream>
using namespace std;
int monthDays[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
int year,month,date;
int days = 0; //从2012-01-22开始过了多少天
cin >> year >> month >> date;
for(int y = 2012; y < year; ++y) {
if( y%4 ==0 && y%100!= 0 || y%400 == 0)
days += 366;
else
days += 365;
}
if( year%4 ==0 && year%100!= 0 || year%400 == 0)
monthDays[2] = 29;
for(int m = 1; m < month; ++m)
days += monthDays[m]; 36
days += date;
days -= 22; //2012年1月22日是星期天
cout << days % 7 << endl;
return 0;
}

4.数组越界

int a[10];
在这里插入图片描述

  • 在c语言或者c++语言中,数组元素的下标,可以是任何整数,可以是负数,也可以大于数组的元素个数。不会导致编译错误,但运行时很可能会出错!!!因为可能写入了别的变量的内存空间,或者写入指令的内存空间。
  • 用变量作为数组下标时,不小心会导致数组越界(变量下标值变为负数,或者太大),可能引起意外修改其他变量的值,导致程序运行结果不正确。可能试图访问不该访问的内存区域,导致程序崩溃。
  • 数组越界的程序,用某些编译器编译后可能可以正确运行,换一个编译器编译后就运行错误。

5.二维数组概念

  • 定义N行M列的二维数组:
    T a[N][M];

  • T :类型名,如char , double, int…

  • N、M : 正整数,或值为正整数的常量表达式。

  • 数组占用了一片连续的、大小总共为 N×M×sizeof(T)字节的存储空间。

  • 表达sizeof(a的值就是整个数组的体积,即N×M×sizeof(T)。

  • 行下标和列下标都从0开始,到N-1和M-1结束。

  • 访问数组元素的方法: 数组名[行下标][列下标]

6.二维数组的存放方式

int a[2][3] 在内存中的存放方式:

在这里插入图片描述

  • 二维数组的每一行,实际上都是一个一维数组。
  • 数组T a[N][M] 每一行都有M个元素
  • 第i行的元素就是a[i][0]a[i][1]……a[i][M-1]同一行的元素,在内存中是连续存放的。
  • a[0][0]是数组中地址最小的元素。如果a[0][0]存放在地址n,则a[i][j]存放的地址就是:n + i × M× sizeof(T) + j × sizeof(T)

7.二维数组的初始化

  • 在定义一个一维数组的同时,就可以给数组中的元素赋初值:
    类型名 数组名[常量表达式][常量表达式]={{值组}{值组}……{值组}};
  • 每个内层的{},初始化数组中的一行。
  • 二维数组初始化时,如果对每行都进行了初始化,则也可以不给出行数。
//正常
int a[2][3]={ {80,75,92},{61,650} };
//等价于
int a[][3]={ {80,75,92},{61,65} };
//会自动补全行数为2,而a[1][2]会被初始化为0。

8.二维数组的遍历

#define ROW 20
#define COL 30
int a[ROW][COL];
for( int i = 0; i < ROW ; ++i) {
    for( int j = 0; j < COL ; ++j )
           cout << a[i][j] << " ";
               cout << endl;
}

例题:矩阵乘法

编程求两个矩阵相乘的结果。输入第一行是整数m,n,
表示第一个矩阵是m行n列的。接下来时一个m×n的矩阵。
再下一行的输入是整数p,q,表示下一个矩阵是p行q列(n=p)
再接下来就是一个p行q列的矩阵。
要求输出两个矩阵相乘的结果矩阵(1 < m,n,p,q <= 8)。

在这里插入图片描述

#include<iostream>
using namespace std;
#define ROW 8
#define COL 8
int a[ROW][COL];
int b[ROW][COL];
int c[ROW][COL];
//提前开大数组,可以避免在运用中数组的常量表达式是变量。
int main(){
	int m,n,p,q;
	cin>>m>>n;//二重循环写入a数组
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++)
			cin>>a[i][j];
	}
	cin>>p>>q;//二重循环写入b数组
	for(int i=0;i<p;i++){
		for(int j=0;j<q;j++)
			cin>>b[i][j];
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<q;j++){
			c[i][j]=0;//对a,b数组进行矩阵乘法
			for(int k=0;k<n;k++)
			c[i][j]+=a[i][k]*b[k][j];
			
		}
	}
	for(int i=0;i<2;i++){//输出c数组
		for(int j=0;j<3;j++){
		  cout<<c[i][j]<<" ";
		}
		cout<<endl;//给一行进行换列
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值