第1关:销售波动统计
100
- 学习内容
- 参考答案
- 记录
- 评论
任务描述
本关任务:假定有一组数据记录着卖场每天(不超过30天)的销售额(假设都是整数),要求你统计并输出销售的波动情况,即计算每天相对于前一天的销售额的增减情况(即后项减前项的差值)。
例如连续5天的销售额分别是:23 56 12 76 43,则销售波动情况的输出为:33 -44 64 -33。
其中:33 = 56 - 23,-44 = 12 - 56,以此类推。
相关知识
一段时间内每天销售额的记录需要由一组数据来完成,其中,数据的个数可能为0到30中的任何一个数,尽管我们可以用30个变量来存储它们,但这显然很不方便。
使用数组则不仅简单直观,而且逻辑清晰。本关我们就一起来学习数组的运用。
一维数组
声明一维数组的一般形式为:
<元素类型> <数组名>[<元素个数>];
-
<元素类型>指明了数组元素的类型,可以是整型、实型、布尔型和字符型等简单数据类型,也可以是用户定义的复合数据类型,包括数组类型; -
<数组名>由标识符充当,是整个数组的名字;<数组名>后面的方括号是必须的,C 和 C++ 把[]作为运算符处理,其优先级与括号相同,左结合; -
方括号中的
<元素个数>是整常量表达式,可以省略,表示数组元素的个数,注意数组元素的下标是从零开始计数的。
例如:
int a[10];
上述声明了一个数组名为 a 的整型数组,它有10个整型元素,下标的变化范围是0~9。
数组元素的访问
给定一个数组,我们可以采用以下形式访问数组里的元素:
<数组名>[<下标表达式>]
<下标表达式>是值为整型的表达式,它指明了拟访问的数组元素的下标。
例如,数组 a 的10个元素可以依次表示为:a[0] ,a[1] ,a[2] ,…… ,a[9]。
注意:如果访问数组元素时使用的下标超出了元素的数目,会导致访问越界错误。C 和 C++ 不检查访问越界,如果发生了访问越界,有可能导致程序在运行时发生错误。
数组的各元素按顺序存储在一片连续的内存单元中。数组int a[10]的内存分配见下图所示:

数组的初始化
数组初始化的方法是把初始值按顺序放在花括号中,数值之间用逗号分开。
例如:
int a[10]={4};float r[20]={0.1, 5.1};double d[3]={10.0,5.0,1.0};
需要注意以下两点:
- 如果初始值的数目小于数组元素的数目,数组剩余的元素被自动初始化为 0。
例如:
int n[5]={0}; //将数组 n 的所有数组元素都初始化为 0
注意:初始值的数目不能超过数组中元素的数目。
- 声明数组时可以省略数组元素的数目,这时系统会根据初始值的数目来确定数组元素的数目。
例如:
int x[]={ 1, 2, 3, 4, 5 };
实际上声明了一个包含了5个整型元素的数组 x :x[0] …… x[4] ,其值分别被初始化为 1 ,…… ,5。
这里再强调一下:我们不能直接操作某个数组,只能对数组中的某一个元素进行操作。也就是说,数组需要“拆开来用”,每次只能操作一个数组元素,操作数组元素的方法和操作普通变量的方法相同,“拆开数组”的方法就是数组名加下标访问数组元素的方式。
例如:
a[7]= 4; // 给数组元素 a[7] 赋值x = 2 * a[i+2]; // 数组元素作表达式的运算量
数组的遍历
对于数组而言,最常见的用法是使用循环语句来操作数组,对数组元素进行遍历和处理。
例如下面的程序对数组 n 中的元素求和:
int n[10] = {12,34,55,71,1,65,423,19,540,10}; // 声明数组n并初始化int i, sum = 0; // 定义循环变量和累加和变量// 循环遍历数组并求和for (i = 0; i <= 10-1; i++){sum += n[i];}cout << "The summary is: " << sum << endl; // 输出求和结果
编程要求
在右侧编辑器中的Begin-End之间补充代码,程序给出计算几天的销售额分并给出这些天的额分(数据由平台提供,已获取,直接使用即可),统计并输出销售的波动情况,即计算每天相对于前一天的销售额的增减情况(即后项减前项的差值)。
温馨提示:这里要求输出的每个数字之间用一个空格隔开,最后一个数字后面没有空格。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:8 34 56 234 87 43 98 109 234(第一个数据表示有 8 天的销售额分,剩下的数据为具体额分) 预期输出:22 178 -147 -44 55 11 125
测试输入:4 0 89 190 289 预期输出:89 101 99
开始你的任务吧,祝你成功!
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int n, a[30], i; // 定义变量及数组,n-销售额个数,a-销售额
cin >> n; // 输入销售额数量,n <= 30
// 输入n个销售额,分别存入a[0]到a[n-1]
for(i = 0; i < n; i++)
cin >> a[i];
// 请在此添加代码,计算并输出销售额的波动情况
/********** Begin *********/
for(i = 1; i < n; i++)
{
int delta = a[i] - a[i-1];
if(i > 1)
{
cout << " ";
}
cout << delta;
}
/********** End **********/
return 0;
}
第2关:最大销售增幅
200
- 学习内容
- 参考答案
- 记录
- 评论
任务描述
本关任务:编写函数 maxIncrease,用于计算一个销售额序列中的最大销售增幅并返回。这里的销售额都是非负整数。
对于给定的销售额序列 A,假设序列 A 的长度为 n( n >= 2 ),最大销售额增幅是指满足0 <= x <= y < n的A[y] - A[x]的最大值。
例如,销售额序列11,3,5,7,9,2,4,6,8,10的最大增幅为8(在 x=5 , y=9 时)。
相关知识
数组作为函数的参数
由于数组的存储是内存中一块连续的单元,数组元素的个数也是不确定的(不同的数组可能包含不同个数的数组元素),因此函数传递数组需要传递两个信息,一个是数组的地址(数组名就是数组地址),告诉被调用函数该数组存放在内存什么地方,另一个是数组元素个数,告诉被调用函数访问该数组时允许的下标范围(防止访问越界)。
参数传入一个整型数组的函数的函数原型如下:
void convertScores(int a[], int len);
-
第一个参数 a 是一个数组类型的形式参数。该参数 a 接收传入数组的数组名,也就是数组的首地址,其后的方括号中的数组长度不需要,即使有,编译器也会将其忽略;
-
第二个参数 len 是整型参数。该参数 len 传入数组 a 的长度,即 a 有 len 个数组元素,访问 a 的元素的下标范围就是 0 到 len-1。
例如:下面的程序将一个整型数组中存放的10名同学的百分制成绩转换为5分制,并输出。
#include <iostream>using namespace std;// 分数转换函数的函数原型,其中:s-学生成绩数组名,len-学生成绩个数void convertScores(int s[], int len);int main(){// 定义学生成绩数组并初始化int scores[10] = {85, 63, 72, 52, 95, 82, 77, 69, 88, 73};convertScores(scores, 10); // 调用分数转换函数convertScores// 转换完成后输出分数数组中的分数for(int i = 0; i < 10; i++)cout << "scores["<<i<<"] = " << scores[i] << endl;return 0;}// 函数convertScoresvoid convertScores(int s[], int len){// 逐个访问数组中的每个元素,并做转换for (int i = 0; i < len; i++)s[i] = s[i]/20; // 修改 s[i] 实际上就是修改 main 函数中的 scores[i],因为 s 和 scores 拥有相同的地址值}
程序的输出为:
scores[0] = 4scores[1] = 3scores[2] = 3scores[3] = 2scores[4] = 4scores[5] = 4scores[6] = 3scores[7] = 3scores[8] = 4scores[9] = 3
上述示例中函数调用convertScores(scores, 10);导致数组 scores 中的每个元素都被转换了。也就是说,在被调用函数体内对数组 s(形式参数)的元素进行的修改操作实际上作用在了数组 scores(实在参数)的元素上,这是否就是传引用呢?
实际上,C 和 C++ 在处理数组参数时是严格地采取了传值方式。
参数传递数组的方式有比较特殊的地方,要理解传递数组的机制,首先要明确下面两点:
-
和一般变量一样,数组名也是有值的,数组名的值就是数组的第一个元素的地址(首地址);
-
和一般变量一样,数组作为函数参数进行传递时,传递的也是数组变量的值,即数组第一个元素的地址。
由于数组名的值就是数组的第一个元素的地址,而访问数组元素的方式是数组名加下标(也就是首地址加下标),才使得尽管采取的是传值方式,但在被调用函数 convertScores 中,通过 s 加下标的方式访问数组元素,实际上访问的就是 main 函数中定义的数组 scores 的数组元素,因为 s 和 scores 代表了同样的地址位置。
编程要求
在右侧编辑器中的Begin-End之间补充代码,计算一个销售额序列中的最大销售增幅并返回。具体要求如下:
-
如对于销售额序列 A ,假设序列 A 的长度为 n( n >= 2 ) ,最大销售额增幅是指满足 0<=x<=y<n 的
A[y] - A[x]的最大值; -
函数 maxIncrease 需要将数组作为参数传入,在该数组中计算最大销售额增幅并返回。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:6 12 34 78 45 10 23(第一个数据表示有6天的销售额分,剩下的数据为具体额分) 预期输出:最大销售增幅为:66
测试输入:9 90 2 80 3 70 6 50 7 40 预期输出:最大销售增幅为:78
开始你的任务吧,祝你成功!
#include <iostream>
using namespace std;
// 函数maxIncrease:计算销售额增幅
// 参数:s-销售额数组,n-销售额数组长度,n>1
// 返回值:销售额最大增幅
int maxIncrease(int s[], int n);
int main()
{
int n, a[30], i; // 定义变量及数组,n-销售额个数,a-销售额数组
cin >> n; // 输入销售额数量,n>1
// 输入n个销售额,分别存入a[0]到a[n-1]
for(i = 0; i < n; i++)
cin >> a[i];
i = maxIncrease(a,n);
cout << "最大销售增幅为:" << i << endl;
return 0;
}
int maxIncrease(int s[], int n)
{
//请在此添加代码,实现函数maxIncrease
/********** Begin *********/
int min_val = s[0];
int max_gain = 0;
max_gain = s[1] - s[0];
for(int i = 1; i < n; i++)
{
if(s[i] - min_val > max_gain)
max_gain = s[i] - min_val;
if(s[i] < min_val)
min_val = s[i];
}
return max_gain;
/********** End **********/
}
第3关:猴子选大王
300
- 学习内容
- 参考答案
- 记录
- 评论
任务描述
本关任务:编写一个函数 king,实现猴子选大王的功能。
新猴王的选择方法是:让 N 只候选猴子围成一圈(最多100只猴子),从某位置起顺序编号为 1 ~ N 号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。
相关知识
针对上述任务的描述,我们假设 N 只猴子分别占据数组 a 的下标从 1 ~ N 的位置(0号位置空着),从序号为1的猴子开始报数。返回值为猴王的序号。
本关可以把数组当作循环表来看,即第 N 个猴子的下一个猴子是第1个猴子。每次选出一个猴子,则对该位置进行标注,下次报数的时候跳过这些标注的位置即可。
在这里,我们假设 k 是当前报数猴子的序号,则下一个报数猴子的序号可以用如下程序求得:
k++;if(k == N + 1)k = 1;
当有些猴子出局后,报数时就需要跳过空位。所以可以对每个位置进行标注,以区分有没有猴子。
例如为0时表示没有猴子,否则就是有。当有很多空位时,可以使用如下程序获得下一个猴子的位置:
// nx 是当前报数的序号,如果为 0 则找后面不为 0 的,否则就是它了while(a[nx]==0){ // 为0时nx++; // 看下一个位置的猴子if(nx == N + 1) // 到尾部了,再回到头部nx = 1;}
编程要求
在右侧编辑器中的Begin-End之间补充代码,输出 N(数据由平台提供,已获取,直接使用即可) 只猴子中谁是猴子大王的。具体要求如下:
-
让 N 只候选猴子围成一圈(最多100只猴子),从某位置起顺序编号为 1 ~ N 号;
-
从第 1 号开始报数,每轮从 1 报到 3 ,凡报到 3 的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数;
-
如此不断循环,最后剩下的一只猴子就选为猴王。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:5 预期输出:4号猴子是大王。
测试输入:18 预期输出:14号猴子是大王。
开始你的任务吧,祝你成功!
#include <iostream>
using namespace std;
// 函数king:猴子选大王
// 参数:a-猴子数组n-1个猴子分别占据下标为~n-1的位置,n-数组长度
// 返回值:新猴王的下标序号
int king(int a[], int n);
int main()
{
int n, a[1000], i; // 定义变量及数组,n-猴子数量,a-猴子数组
cin >> n; // 输入猴子数量,n>0
// 初始化猴子数组,n 个猴子分别占据 n 个位置
a[0] = 0; // 0号位置没有猴子
for(i = 1;i <= n; i++)
a[i] = i;
// 选大王啦
i = king(a, n );
cout << i << "号猴子是大王。" << endl;
return 0;
}
int king(int a[], int n)
{
// 请在此添加代码,实现函数king
/********** Begin *********/
int left = n;
int pos = 0;
int call = 0;
while (left > 1) {
pos++;
if (pos > n) {
pos = 1;
}
if (a[pos] != 0) {
call++;
if (call == 3) {
a[pos] = 0;
left--;
call = 0;
}
}
}
for (int i = 1; i <= n; i++) {
if (a[i] != 0) {
return a[i];
}
}
return 0;
/********** End **********/
}
第4关:犯二的程度
200
- 学习内容
- 参考答案
- 记录
- 评论
任务描述
本关任务:编写函数 silly,计算整数(不多于100位)犯二的程度并返回。
数字也可以“犯二”,一个整数“犯二的程度”定义为:该数字中包含2的个数与其位数的比值,如果这个整数是负数,则程度增加0.5倍,如果还是个偶数,则再增加1倍。
例如,数字−56782223456是个11位数,其中有3个2,是负数,也是偶数,则它的犯二程度为:3/11×1.5×2,约为0.818182。
相关知识
由于 C 和 C++ 中 int 类型的表示范围有限,为−2147483648~2147483647,所以超过10位的整数就会溢出。
例如下面的程序:
int a;cin >> a;cout << a << endl;
测试输入:77777777777
输出结果:-858993460
很显然整型变量 a 无法表示超出范围的数。
字符串数组
在 C 和 C++ 中,一个字符串就是用一对双引号括起来的一串字符。字符串的存储是利用一维字符数组来实现的,该字符数组的长度为待存字符串的长度加1。即如果一个字符串的长度为 n ,则用于存储该字符串的数组的长度应为 n+1。
当字符串存入数组时,是把每个字符依次存入到数组的对应元素中,即把第一个字符存入到下标为0的元素中,第二个字符存入到下标为1的元素中,依次类推,最后会把一个空字符 ′\0′ 存入到下标为 n 的元素中(这里假定字符串的长度为 n)。字符存储的是它的 ASCII 码或区位码。
例如用一维字符数组 a[12] 来存储字符串 ″Strings.\n″ 时,数组 a 中的内容参见下图:

接下来,我们可以利用字符串来初始化字符数组,如:
char a[10] = ″array″;char b[20] = ″This is a pen. ″;char c[8] = ″″;
-
第一条语句定义了字符数组 a[10] 并被初始化为“array”,其中 a[0] ~ a[5] 元素的值依次为字符‘a’, ‘r’,‘r’,‘a’,‘y’和‘\0’;
-
第二条语句定义了字符数组 b[20] ,其中 b[i] 元素( 0 ≤ i ≤ 13 )被初始化为所给字符串中的第 i+1 个字符,b[14] 被初始化为字符串结束标志符‘\0’;
-
第三条语句定义了一个字符数组 c[8] 并初始化为一个空串,此时它的每个元素的值均为‘\0’。
我们可以看到对于字符串而言,它的存储总是以 '\0' 结尾。
例如下面的程序可以计算并输出字符串的长度:
char s[1000]; // 定义一维字符数组cin >> s; // 输入一个字符串存入字符数组s中int i = 0;// 逐个判断字符数组的某一位是否是'\0',该字符意味着字符串的结束while(s[i] != '\0')i++;cout << i << endl; // 输出字符串的长度
获取字符对应的整数
由于使用字符形式存储数字时,存储的是数字对应的 ASCII 码,由于在 ASCII 码表中字符‘0’到字符‘9’是连续存放的,所以下面的程序可以获得字符对应的数字:
char c = '2'; // c 中存储的是字符 '2' 的ASCII码int k = c - '0'; // k 即为字符 '2' 对应的整数 2
编程要求
在右侧编辑器中的Begin-End之间补充代码,计算整数(不多于100位,数据由平台提供)犯二的程度并返回。具体“犯二的程度”定义如下:
-
该数字中包含 2 的个数与其位数的比值;
-
如果整数是负数,则程度增加 0.5 倍;
-
如果整数是偶数,则再增加 1 倍。
提示:对于本关要求计算不超过100位的整数,很显然不能使用 int 类型,但可以把输入的一串数字当做字符串处理,使用字符数组来接收输入的整数。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:-13142223336 预期输出:0.818182
测试输入:122335468912334612 预期输出:0.444444
开始你的任务吧,祝你成功!
#include <iostream>
using namespace std;
// 函数silly:计算数值有多二
// 参数:a-存储数值的字符数组,以'\0'结束,所以不需要另一个参数告诉函数数组有多长
// 返回值:数值犯二的程度
double silly(char a[]);
int main()
{
char s[102]; // 定义存储数值的数组
cin >> s; // 输入不超过位的整数
double sy = silly(s); // 计算犯二的程度
cout << sy << endl; // 输出犯二的程度
return 0;
}
double silly(char a[])
{
// 请在此添加代码,实现函数silly
/********** Begin *********/
int len = 0;
while (a[len] != '\0') len++;
int start = 0;
if (a[0] == '-') start = 1;
int digits = len - start;
int count2 = 0;
for (int i = start; i < len; i++) {
if (a[i] == '2') count2++;
}
double degree = (double)count2 / digits;
if (start == 1) {
degree *= 1.5;
}
int last = a[len - 1] - '0';
if (last % 2 == 0) {
degree *= 2.0;
}
return degree;
/********** End **********/
}
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/King____1/article/details/170735117



