C语言博客作业04--数组
0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
1.1.1一维数组
-
①一维数组的定义格式:类型名 数组名 [数组长度];
-
②一维数组的引用形式:数组名 [下标]
-
③下标的取值范围:[0,数组长度-1]
-
④只能引用单个的数组元素,不能一次引用整个数组
-
⑤引用数组元素时,方括号内是表达式,代表下标,也可以是变量,而定义数组时方括号内是常量表达式,可以包括常量和符号常量,但不能包含变量
-
⑥对数组元素赋初值格式:类型名 数组名 [数组长度] = {初值表};
可对全部元素赋值,如 int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
也可对部分元素赋值,如 int b[20] = {0,1};//表示对b数组的前两个元素赋初值
-
⑦静态储存的数组如果没有初始化,系统将自动给所有元素赋0
1.1.2二维数组
-
①数组的定义格式:类型名 数组名 [行长度][列长度];
-
②二维数组的引用形式:数组名 [行长度][列长度]
-
③二维数组先存放第0行的元素,再存放第1行的元素...每一行元素再按照列的顺序的存放
-
③二维数组的分行式赋初值格式:类型名 数组名 [行长度] [列长度] = {{初值表0},...,{初值表k},...};
可对全部元素赋值,如 int a[2][3] = { {1,2,3},{4,5,6},{7,8,9} };
也可对部分元素赋值,如 int b[4][3] = {{1,2,3},{},{4,5} };//表示对b数组的第0行和第2行的前两个元素赋初值
1.1.3一维字符数组
- 一维字符数组的定义、初始化和引用与其他类型的一维数组一样
1.1.4字符串
-
①字符串常量就是用一对双引号括起来的字符序列,即一串字符,如“happy”
-
②字符串有一个结束标志'\0',如“happy”由六个字符组成即'h','a','p','p','y','\0',前五个是字符串的有效字符,'\0'是字符串结束符
-
③将字符串存入字符数组时,由于'\0'的存在,数组的长度至少是字符串的有效长度+1
-
④字符串的存储——数组初始化
字符数组的初始化还可用字符串常量,如 static char s [6] = {"happy"};或 static char s [6] = "happy";
还可以采用赋值和输入的方法,如 static char s [6]; s[0] = 'a'; s[1] = '\0';
-
区分"a"和'a',"a"是字符串常量,包括'a'和'\0'两个字符,而'a'是字符常量,只有一个字符,可以赋给字符变量
所以 static char s [6]; s[0] = 'a'; s[1] = '\0';等价于 static char s [6] = “a”;
-
在程序中要将结束符'\0'存入字符数组,否则字符串就不能正常结束,影响后面操作
1.1.5在数组中查找数据
①遍历法,即挨个找,找到就输出该数在数组中的下标
void arrayFind(int a[MAX], int n, int number) //传入数组、数组长度和要找的数
{
int i;
for (i = 0; i < n; i++)
{
if (a[i] == number)
{
printf("%d\n", i); //找到元素,打印下标
}
}
return 0;
}
②二分法,即将要找的数与数组的中间数比较,如果相同就输出中间数的下标,否则将要找的区间压缩
void arrayFind(int a[MAX], int n, int number) //传入数组、数组长度和要找的数
{
int left = 0;
int right = a[n];
int mid;
while (left <= right)
{
mid = (left + right) / 2;
{
if (number == a[mid])
{
printf("%d", mid); //找到元素,打印下标
return 0;
}
else if (number < a[mid])
{
right = mid - 1;
}
else if (number > a[mid])
{
left = mid + 1;
}
}
}
return 0;
}
1.1.6在数组中插入数据
int main()
{
int i;
int j;
int a[MAX+1]; //先假定该数组已按从小到大排列,且该数组长度为插入后的长度
int number;
用循环给数组赋值
输入要插入的数
for(i=0;i<MAX;i++)
{
找到比该数大的数组元素的下标
break;
}
for(j=MAX-1; j>=i; j--)
{
将该下标(包括其本身)后面的元素下标加一
将该数插入该下标所在位置
}
输出插入后的数组
return 0;
}
1.1.7删除数组中的数据
①一般法
int main()
{
int i;
int j;
int a[MAX];
int number;
用循环给数组赋值
输入要删除的数
for (i = 0; i <= MAX - 1; i++)
{
找到要删除的数,记录下标
{
for (j = i; j <= MAX - 2; j++)
{
将该下标后面的元素向前移一位,实现覆盖
}
}
跳出循环
}
输出删除后的数组
return 0;
}
②记录下标法
int main()
{
int a[MAX];
int number;
int delectIndex;
用循环给数组赋值
输入要删除的数
for (i = 0; i <= MAX - 1; i++)
{
找到要删除的数的下标
{
delectIndex=i;
}
}
for(i=delectIndex;i<=MAX-2;i++)
{
将该下标后面的元素向前移一位,实现覆盖
}
输出删除后的数组
return 0;
}
1.1.8数组排序
①冒泡法
相邻元素两两比较,每趟将最值沉底即可确定一个数在结果的位置,确定元素位置的顺序是从后往前,其余元素可能作相对位置的调整。可以进行升序或降序排序。
int main()
{
int a[10];
int i;
int j;
int temp;
for (i = 0; i < 10; i++)
{
scanf("%d", &a[i]);
}
for (j = 0; j < 9; j++) /*外循环控制排序趟数,n个数排n-1趟*/
{
for (i = 0; i < 9 - j; i++) /*内循环每趟比较的次数,第j趟比较n-j次*/
{
if (a[i] > a[i + 1]) /*相邻元素比较,逆序则交换*/
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
for (i = 0; i < 10; i++)
{
printf("%d", a[i]);
}
return 0;
}
②选择法
每趟选出一个最值和无序序列的第一个数交换,n个数共选n-1趟。第i趟假设i为最值下标,然后将最值和i+1至最后一个数比较,找出最值的下标,若最值下标不为初设值,则将最值元素和下标为i的元素交
换。
int main()
{
int a[10];
int i;
int j;
int k;
int temp;
int n = 10;
for (i = 0; i < 10; i++)
{
scanf("%d", &a[i]);
}
for (i = 0; i < n - 1; i++) /*外循环控制趟数,n个数选n-1趟*/
{
k = i; /*假设当前趟的第一个数为最值,记在k中 */
for (j = i + 1; j < n; j++) /*从下一个数到最后一个数之间找最值*/
{
if (a[k] < a[j]) /*若其后有比最值更大的*/
{
k = j; /*则将其下标记在k中*/
}
}
if (k != i) /*若k不为最初的i值,说明在其后找到比其更大的数*/
{
temp = a[k];
a[k] = a[i];
a[i] = temp;
} /*则交换最值和当前序列的第一个数*/
}
for (i = 0; i < 10; i++)
{
printf("%d", a[i]);
}
return 0;
}
③插入法
将序列分为有序序列和无序列,依次从无序序列中取出元素值插入到有序序列的合适位置。初始是有序序列中只有第一个数,其余n-1个数组成无序序列,则n个数需进n-1次插入。寻找在有序序列中插入位
置,可以从有序序列的最后一个数往前找,在未找到插入点之前可以同时向后移动元素,为插入元素准备空间。
int main()
{
int a[10];
int i;
int j;
int temp;
for (i = 0; i < 10; i++)
{
scanf("%d", &a[i]);
}
for (i = 1; i < 10; i++) /*外循环控制趟数,n个数从第2个数开始到最后共进行n-1次插入*/
{
temp = a[i]; /*将待插入数暂存于变量t中*/
for (j = i - 1; j >= 0 && temp > a[j]; j--) /*在有序序列(下标0 ~ i-1)中寻找插入位置*/
{
a[j + 1] = a[j]; /*若未找到插入位置,则当前元素后移一个位置*/
}
a[j + 1] = temp; /*找到插入位置,完成插入*/
}
for (i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
1.1.9数组做枚举用法的案例
-
①在课本例题“调查电视节目收欢迎程度”中,将节目编号1~8作为数组下标进行计数操作
-
②在PTA“找重复数据I”一题中,用hush数组的下标对应每个数据,最后对hush数组进行遍历查重
-
③在PTA“阅览室”一题中,用数组下标存放书号
1.1.10哈希数组用法案例
- ①在PTA“找重复数据I”一题中,先定义一个静态储存的数组hush,然后遍历原数组,当原数组中的元素与hush数组的下标相等时,hush数组该下标所对应的值变为1,之后若再遇到hush的值为1的,即表示有重复数据
1.2 本章学习体会
1.2.1学习感受
做数组PTA时,一维数组倒是还好,二维数组我感觉比较棘手的是内外两层循环与行列的结合运用,而字符数组就有点难办了,对字符数组的赋值跟输出的认识还是有点模糊。另外,总感觉自己写的代码的行数总会比其他人要多。
1.2.2代码量
两周代码量大约1016行
2.PTA实验作业
2.1出生年
2.1.1伪代码
int main()
{
int n; //目标年份中不同数字的个数
int i; //循环用的
int j; //循环用的
int year; //出生年份
int flag = 0; //记录有几个不同数
int count = 0; //年纪
static int b[10]; //将年份分拆成4个后,存入该数组
输入出生年份和目标年份中不同数字的个数
while (1)
将年份拆分成4个后,按下标存入b数组
for (i = 0; i < 10; i++)
{
遍历b数组,有元素不为0的,flag加一
}
当flag达到n时,输出结果,并结束程序
若flag没达到要求,将flag和b数组清零
count++;
year++; //年份与年纪都加一
end while
return 0;
}
2.1.2代码截图
2.1.3造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
2000 4 | 13 2013 | 正常数据 |
6666 4 | 35 6701 | 正常数据 |
11111 3 | 9 11120 | 正常数据 |
9999 3 | 13 10012 | 正常数据 |
9999 4 | 无 | 程序炸了 |
666 5 | 无 | 程序炸了 |
2.1.4PTA提交列表及说明
-
选这题是因为我觉得这题挺好玩的,做的过程中也换了不少思路,虽然现在看当时的想法很笨(可能现在也是,哈哈哈),但终归是有了一些收获的。
-
另外我有个小毛病,我无论有没有修改后都会习惯地就点PTA的提交来看各个测试的情况,所以有些错误其实是重复的,因此我会适当跳过一些。
-
Q1:编译错误
-
A1:单纯的语法错误。
-
Q2:部分正确
-
A2:同时出现了运行超时、段错误,经分析,是发生了数组越位,导致循环不能正常退出,我于是选择用下标的方法处理拆分后的年份数据。
-
Q3:多种错误
-
A3:有点尴尬,换了一套算法后就全错了(哈哈哈),经分析,是在flag没达到要求时没有将flag和b数组清零,导致运行结果出错,在多了清零语句后,就通过所有测试点了。
2.1找鞍点
2.1.1伪代码
int main()
{
int n; //表示几阶的数组
int i; //循环用的
int j; //循环用的
int m; //循环用的
int lineMax; //行最大的数
int rowMin; //列最小的数
int lineDate; //行最大的数的下标
int rowDate; //列最小的数的下标
int a[N][M]; //数组
输入阶数
当阶数为1时,直接输出0 0
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
给数组赋值
}
for (i = 0; i < n; i++)
{
rowDate = 0;
for (j = 0; j < n; j++)
{
每行找出列最小的数,记录其数值跟下标
}
for (m = 0; m < n - 1; m++)
{
找该列行最大的数,记录其数值跟下标
}
若两次查找出的数相同,表示该数符合条件,输出其行列下标,结束程序
}
printf("NONE"); //找不到输出NONE
return 0;
}
2.1.2代码截图
2.1.3造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
4 1 7 4 1 4 8 3 6 1 6 1 2 0 7 8 9 | 2 1 | 正常数据 |
3 2 5 6 A 4 1 0 8 5 6 | 1 2 | 有非数字 |
3 -1 -5 -6 -2 -5 -1 -3 -6 -10 | 2 0 | 全负数 |
2.1.4PTA提交列表及说明
-
我无论有没有修改后都会习惯地就点PTA的提交来看各个测试的情况,所以有些错误其实是重复的,因此我会适当跳过一些。
-
Q1:部分正确
-
A1:经分析,没有考虑n=1的情况,补充了几条语句后就通过了“n最小”的测试点。
-
Q2:部分正确
-
A2:经过几次调试都没过“最大规模,有并列极值元素,最后一个是鞍点”这一测试点,看了超新星平台后,就全过了。
2.3IP地址转换
2.1.1伪代码
#include <stdio.h>
int main()
{
int i; //循环用的
char a[35]; //存放字符
int number1 = 0; //地址数1
int number2 = 0; //地址数2
int number3 = 0; //地址数3
int number4 = 0; //地址数4
输入字符
for (i = 0; i < 8; i++)
{
将前八个数值转换成十进制
}
for (i = 8; i < 16; i++)
{
将第二个的八个数值转换成十进制
}
for (i = 16; i < 24; i++)
{
将第三个的八个数值转换成十进制
}
for (i = 24; i < 32; i++)
{
将后八个数值转换成十进制
}
输出结果
return 0;
}
2.1.2代码截图
2.1.3造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
11001100100101000001010101110010 | 204.148.21.114 | 正常数据 |
110011001001010000010101011100101 | 204.148.21.114 | 超出32位的数据 |
1100110010010100000101010111001 | 204.148.21.76 | 小于32位的数据 |
11001100100101000001010101110018 | 204.148.21.122 | 有非二进制的数据 |
1100110010010100000101010111001A | 204.148.21.131 | 有非数字的数据 |
2.1.4PTA提交列表及说明
-
我无论有没有修改后都会习惯地就点PTA的提交来看各个测试的情况,所以有些错误其实是重复的,因此我会适当跳过一些。
-
Q1:答案错误
-
A1:在设置了多个printf语句后,发现最后一个字符并没有进入程序,经排查,最终发现是在定义数组长度时只设置了32个,无法达到题目要求,在扩大数组长度后,就全过了。
3.阅读代码
-
代码功能:将输入的一段文字沿着矩阵按一定的规则进行编码加密
-
优点一:用getchar();语句吸收换行符
-
优点二:用isRow = !isRow;使程序能进入if语句跟下面的else语句
-
优点三:通过记录下标达到对每一行或每一列的数据处理,并且通过多个if else语句实现了螺旋编码