以史为鉴之C实践:一维数组的操作(初始化、计算长度、拷贝、删除、插入、排序)

程序效果分析

需求分析

这个程序主要实现的是数组初始化、计算数组长度、数组拷贝、数组打印、插入特定位置的元素、删除元素、排序的功能,主要函数如下:
int Initarray(int *array);//初始化数组
int length(int *array);//计算数组长度
int copyarray(int *src, int *dest);//复制数组
int printarray(int *array);//打印数组
int insert(int *array, int idx, int val);//插入
int deletearray(int *array, int idx);//删除
int sort(int *array, int size);//排序

效果分析

  1. 输出旧数组
    在这里插入图片描述
  2. 输入新数组
    在这里插入图片描述
    将会输出数组长度,以及复制成功的信息,输出复制的数组

在这里插入图片描述

  1. 对拷贝好的数组进行操作选择
    在这里插入图片描述

  2. 插入操作
    在这里插入图片描述

  3. 删除操作
    在这里插入图片描述

  4. 排序
    在这里插入图片描述

  5. 退出程序
    如果不输入q,则程序不会退出,将一直进行操作。

主要程序内容分析

主函数

  1. 定义操作的数组,旧数组array,开辟新数组new_array,以及函数当中将会使用的变量
 /******** 定义操作数组 ************/
 int array[] = { 5,3,4,1,2,-9999 };
 int new_array[1000]; //作用于new_array
 int inumber = 0;
 int dnumber = 0;
 int ival;
 char choice;//操作选择字符
  1. 输入新数组,计算数组长度,进行拷贝操作
 /********* 初始化并输出数组,计算数组长度 *********/
 printarray(array);
 Initarray(new_array);//数组初始化,输入目标数组
 copyarray(tempv, new_array);//将输入数组改为操作数组
 printarray(tempv);
 int n = length(tempv);//计算数组长度,并输出
 system("pause");
  1. 选择操作,一直到输入q为止(do…while…)
 /********* 选择数组操作内容 ************/
 do
 {
  choice = Choice();/*选择算法*/
  switch (choice)
  {
  case'i': //向数组插入新元素
   cout << "           *********   Inputing the Index number:   *********       " << endl;
   cin >> inumber;
   cout << "           *********  Inputing the content you want: *********       " << endl;
   cin >> ival;
   insert(tempv, inumber, ival);
   break;
  case'd': //删除数组元素
   cout << "           *********   Inputing the Index number:   *********       " << endl;
   cin >> dnumber;
   deletearray(tempv, dnumber);
   break;
  case's'://排序
   n = length(tempv);
   sort(tempv, n);
   break;
  case'q'://退出程序
   break;
  }
 } while (choice != 'q');

数组打印int printarray(int *array)

打印的时候遇到的主要问题还是,因为开辟的数组空间长,没有输出的限制,会导致访问越界。为此,在初始化数组的时候,以-9999作为结尾,一旦出现-9999,则停止输出,在后续长度估计也有应用。

int printarray(int *array)
{
 int j = 0;
 cout << "           ****************     The Array is:   *************         " << endl;
 while (array[j] != -9999)
 {
  cout << array[j] << "\t";
  j++;
  if (j % 5 == 0)cout << endl;
 }
 cout << endl;
 return 0;
}

数组长度估计int length(int *array)

数组长度估计,主要还是注意的是-9999作为结尾,n是从0开始估计的,只要未碰到-9999,n自加1。

int length(int *array)
{
 int n;
 for (n = 0; array[n] != -9999; n++);
 cout << endl;
 cout << "The length of the array is :" << n << endl;
 return (n);
}

数组初始化int Initarray(int *array)

数组初始化问题同上,开辟数组空间大,要有一个特定的结尾表示输入结束,此处建立ch标识,只要ch为回车输入,停止输入数组元素。同样,为了后续的长度估计以及输出数组操作,将结尾处设为-9999.

int Initarray(int *array) //初始化new_array
{
 cout << "           *******************************************************        " << endl;
 cout << "           *********First:You should Inpute the new array: *******        " << endl;
 cout << endl;
 int i = 0, j = 0;
 char ch = 0;
 while (ch != '\n')
 {
  cin >> array[i];
  ch = getchar();
  i++;
 }
 array[i] = -9999;//以-9999结束
 cout << endl;
 return 0;
}

数组拷贝int copyarray(int *src, int *dest)

数组拷贝遇到的问题,主要还是如果复制到的目的数组开辟空间不足够,将会遇到数组访问越界的问题,本来尝试开辟新空间,改变原数组地址等方法,但不了了之,还是空间够大比较好。

int copyarray(int *src, int *dest)
{
 //int *change_ptr(int *ptr, int *dest);
 int n = length(dest);
 //int m = length(src);
    //tempv = new int[n + 1];
 //if (m <= n)
 //{
  // tempv = new int[n + 1];//定义新数组,分配空间与dest相同
  //memcpy(tempv, src, m);//将旧数组复制到tempv当中
  //src = tempv;//地址改为tempv
 for (int i = 0; i < n+1 ; i++)
 {
  //*(src + i) = *(dest + i); 
  *(tempv + i) = *(dest + i);
  //src[i] = dest[i];
 }
  //src = change_ptr(src,tempv);//地址改为tempv
  cout << "   *************   Coping is successful!   *************   " << endl;
 // system("pause");
  return 0;
 //}
 /*else
 {
 int n = length(dest);
 int m = length(src);
  for (int i = 0; i < n; i++)
  {
   *(src + i) = *(dest + i);
  }
  for (int j = n; j < m; j++)
  {
   *(src + j) = *(dest + j);
  }
 }
 cout << "   *************   Coping the array is successful!   *************   " << endl;
 system("pause");
 return 0;*/
}

插入int insert(int *array, int idx, int val)

思路:和删除比较相像,当数组号大于所要插入位置时,所有元素向后挪,也就是:
在这里插入图片描述

删除int deletearray(int *array, int idx)

思路:

  1. 首先要对索引号是否合法进行判断,当是在数组长度n以内、刚好接在数组后的时候是合法的。如果输入的是其他情况,则会返回-1,数组索引不合法。
  2. 要对数组进行删除操作,并能够传递回主函数,那么函数传递的是数组的地址。
    数组进行移动的主要方法是:改变原数组指针指向。当数组大于要求删除的位置时,将把数组指向向后移动一个位置,也就是说,将利用指针向后一个指向,达到屏蔽掉对应元素。当然,在所要求的删除位置之前,不进行指向的改变。
    注意:其实内存中的索引号是比我们认为的位置多1的,所以判断的时候别忘记加上1;另外,指针应该从后往前,和插入是不同的,否则,会把-9999给前一个位置,然后又给前一个位置变成-9999.
    在这里插入图片描述

排序int sort(int *array, int size)

主要问题以及解决办法

在写的时候遇到的最大的问题还是在拷贝数组上,由于数组的静态空间导致越界、拷贝长度调整等问题,使得程序没能呈现意料中的效果。以史为鉴可以知兴衰,总结一下遇到的主要问题:

copyarray(int *src, int *dest); //将dest拷贝到src
  1. 开始的时候,拷贝函数还是比较简略的,是直接改变了src数组的指向,没有考虑过静态空间的问题,只要数组dest的长度大于src的长度,就会出现越界。
int copyarray(int *src, int *dest)
{
int n = length(dest);//计算dest数组长度,以便循环改变指向
for(int i = 0;i<n+1; i++)//n+1主要是因为结束是-9999,不能忽略了
{
*(src+i) = *(dest + i);
}
cout<<****   COPING THE ARRAY   *************   " << endl;
 printarray(src);//输出数组
 system("pause");
 return 0;
}
  1. 考虑到以上问题,为了避免越界问题,提出了以下重新分配空间的操作。(其实,这个函数实际上也不能真正拷贝数组,若dest长度大于src的时候,可以通过分配新空间,改变src指向的方法来实现,但原本src空间被摒弃。若dest长度小于src,可以说是用-9999这个标识来标志src的结束,实际上,src数组仍然有其他元素。)
  2. 但是,程序在运行时,只要输入的dest大于src,就会出现不复制的情况。估计是if条件出现了一些问题。
  • 循环处设置断点,发现在循环前,src的内容并没有被复制到tempv,反而两者都出现乱码,未知的分配

断点设置

  • 回溯思路,看是否有理解偏差
    首先int *tempv = new int[n+1]是为了分配新的存储空间,这个空间可以存储下dest的元素;
    其次,memcpy(temp,src,m);是为了实现元素的复制,将src前m个元素全部赋值给tempv。
    在这步进行操作的时候,发现根本没有把src数组值给到tempv。回头看的时候,发现src首地址根本没有发生改变,输出仍然是原数组。
  • 问题出在:函数内定义的tempv在函数结束之后被释放,不能传到主函数当中!
  • 解决问题的核心就是要解决地址传输的问题。我想要解决这个问题,思路如下:1.将tempv声明为全局变量,那么函数结束之后将不会释放建立好的tempv。——>2.将地址传输到主函数当中。但是这个办法是行不通的,因为,主函数中建立好的src其实是一个指针常量,没办法通过赋值的方式来改变。只能通过改变指针的指向。
  • 放弃从改变地址的方向来改变,后面还是直接用全局变量tempv来复制数组了。
int copyarray(int *src, int *dest)
{
 int n = length(dest);
 int m = length(src);
 if (m <= n)
 {
  int *tempv = new int[n + 1];//定义新数组,分配空间与dest相同
  memcpy(tempv, src, m);//将旧数组复制到tempv当中
  src = tempv;//地址改为tempv
  for (int i = 0; i < n+1; i++)
  {
   *(src + i) = *(dest + i);
  }
 }
 else
 {
  for (int i = 0; i < n; i++)
  {
   *(src + i) = *(dest + i);
  }
  for (int j = n; j < m; j++)
  {
   *(src + j) = *(dest + j);
  }
 }
 cout << "   *************   COPING THE ARRAY   *************   " << endl;
 printarray(src);//输出数组
 system("pause");
 return 0;
}

总结

总的来说,问题有以下几种:

  1. 基础知识:数组的理解不够透彻,编程思路不够清晰上面,在初步思考的时候,应该就要把一些可能有的问题写下来,然后在写代码的过程中考虑进去。
  2. 对于指针类容易出错的问题,可以在其中加入cout,打印出。只要是可能出现问题的地方
    都可以加入cout,进行一个问题回溯。
  3. 写完函数之后,对于每个函数的功能要进行一个彻底的检查,以免出现牵一发动全身的错误。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值