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语句实现了螺旋编码

posted @ 2019-11-17 21:46  甘津津  阅读(743)  评论(1编辑  收藏  举报