输入两个学生的成绩, 我们可以定义两个变量来存储, 可是如果输入全班的学生的成绩, 怎么存放呢? 全校学生的成绩呢? 这时, 我们需要用到数组.
数组: 是相同数据类型组成的集合。
一维数组
声明: 数据类型 数组名[大小]
声明和定义:数据类型 数组名[大小] = {数组元素}
例子:
int a[6] = {10, 20, 30, 40,};
数组下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
数组元素 | 10 | 20 | 30 | 40 | 0 | 0 | 随机值 |
取数组值 | a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[x]越界 |
测试代码:
#include <iostream>
using namespace std;
int main()
{
int a[6] = {10, 20, 30, 40};
for(int i = 0; i <= 10; i++) {
cout << a[i] << " ";
}
return 0;
}
最重要特性: 连续! 连续! 连续! 的一块内存
这样对吗?
int n;
cin >> n;
int a[n]; //对吗?
const int N = 10000;
int a[N];
c++不支持变量定义数组长度, 虽然c支持
选择题:
c++ 中数组a[10], 下面表述正确的是()
A: a代表了是a[1]的地址
B: a代表了整个数组的元素
C: a代表了数组的首地址
D: a的值可以改变
一维数组的初始化
- 依次赋值
int a[3] = {1,2,3}; - 部分赋值
int a[3] = {1,}; - 单个赋值
int a[3]; a[0] = 1; a[1] = 2;
这样对吗? 为什么
int a[10] = {10, 1, };
int b[10];
b = a; // 对吗? c++ 为什么不支持呢?
数组大小
sizeof(a) // 返回a占用内存的字节数. 注意不是数组元素的个数.
数组的越界
- 数组下标不能是负数
- 下标应该在数组长度之内
int a[N]; // 数组元素的下标值为 0 - (N-1)
for(int i = 0; i < n; i++) {
if(a[i] > a[i-1]) { //不小心就越界了, 还有可能是a[n+1]
;
}
}
每次写完数组的循环, 都要带入数组下标的边界值确认是否越界
内存操作函数
- memcpy
void *memcpy(void *destin, void *source, unsigned n);
从存储区 source 复制 n 个字节到存储区 destin
int a[10] = {10, 1, };
int b[10];
memcpy(b, a, sizeof(b));
- memset
void *memset(void *buffer, int ch, size_t n);
buffer 是指针或者数组,ch是要初始化的变为的字符,count是buffer的长度
// 清零
int a[100];
memset(a, 0, sizeof(a));
//极大值
memset(a, 0x7f, sizeof(a));
// -1
memset(a, -1, sizeof(a));
数组类型
int a[100];
char str[100];
long long lla[100];
一维数组的应用模板
- 输入, 输出和遍历
int a[100000];
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]); //依次读入每个元素
}
for(int i = 0; i < n; i++) {
printf("a[%d]=%d", i, a[i]); //打印数组,用于调试
}
- 删除
删除第i个, 后面的元素要前移
- 插入
i下标插入 x, 原来i和i之后的元素要后移动.
例题1
- 题目描述
一个学校有100个教室, 每个教室有一盏灯, 开关控制, 拉一下,是开, 再拉一下是关. 教室编号从 1 – 100. 开始时, 所有的灯都是关的. 第一个学生把所有的灯的开关都拉一下, 第二个学生把所有编号是2的倍数的教室的灯开关都拉1下. 第三个学生把所有编号是3的倍数的灯都拉1下 … 以后每个学生都是如此.当第100个学生拉完开关后, 哪些灯是亮的呢? - 分析
灯开关状态怎么表示?
教室怎么表示?
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int a[108];
memset(a, 0, sizeof(a));
for(int i = 1; i <= 100; i++) {
for(int j = 1; j*i <= 100; j++) {
if (a[i*j] == 1)
a[i*j] = 0;
else
a[i*j] = 1;
}
}
for(int i = 1; i <= 100; i++) {
if(a[i] == 1)
cout << i << " ";
}
return 0;
}
例题 2
P5728 【深基5.例5】旗鼓相当的对手
- 题目描述
现有 N(N≤1000) 名同学参加了期末考试,并且获得了每名同学的信息:语文、数学、英语成绩(均为不超过 150 的自然数)。如果某对学生 <i,j> 的每一科成绩的分差都不大于 5,且总分分差不大于 10,那么这对学生就是“旗鼓相当的对手”。现在想知道这些同学中,有几对“旗鼓相当的对手”?同样一个人可能会和其他好几名同学结对。 - 输入格式
第一行一个正整数 N。
接下来 N 行,每行三个整数,其中第 i 行表示第 i 名同学的语文、数学、英语成绩。最先读入的同学编号为 1。
- 输出格式
输出一个个整数,表示“旗鼓相当的对手”的对数。 - 输入输出样例
3
90 90 90
85 95 90
80 100 91- 输出
2
- 输入
- 输出
- 分析
数据怎么存储呢?
怎么进行两两比较呢? - 参考代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 1002;
int n, a[MAXN], b[MAXN], c[MAXN], sum[MAXN];
int ans;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i] >> b[i] >> c[i];
sum[i] = a[i] + b[i] + c[i];
}
for(int i = 1; i <= n; i++) {
for(int j = i+1; j <= n; j++) {
if(abs(a[i] - a[j]) <= 5 &&
abs(b[i] - b[j]) <= 5 &&
abs(c[i] - c[j]) <= 5 &&
abs(sum[i] - sum[j]) <= 10)
ans++;
}
}
cout << ans;
return 0;
}
作业
作业 1:
- P1428 小鱼比可爱
- P1047 校门外的树
- P1554 梦中的统计
- P2141 珠心算测验
作业 2:
- P1427 小鱼的数字游戏
- P5728 【深基5.例5】旗鼓相当的对手
- P2550 [AHOI2001]彩票摇奖
- P1161 开灯