C语言之数组 -----Day12

一.知识点整理

1.一维数组

1.1 基本概念和注意事项

  • 定义方法:数据类型 数组名[常量表达式];
  • 注意的点:

1.再给数组的每一项赋值的时候,不能够越界;
如 int a[3]={6,2,3,5,1}; 是错误的
2.必须先定义,后使用!
3.数组在定义的时候不能这样: int a[];
4.char ch[10] = “Hello”,是错误的,因为char[10]是常量,不能被定义。

1.2 数组的几种排序方法

1.2.1 冒泡排序
  • 冒泡排序

1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

#include<stdio.h>
//冒泡排序
int main()
{
    int t,a[5] = {0};//定义中间变量t、和初始化一个长度为5的一维维数组用来存储,并清零
    printf("请输入你要排序的5个数字\n");
    for (int i = 0; i < 5; i++)//输入5个要排序的数字
    {
        scanf("%d",&a[i]);
    }
    for (int j = 0; j < 5; j++)//第一次遍历,先以第一个数为主,依次递增
    {
        for (int k = 0; k < 5; k++ )//实现第一个数遍历到最后一个数
        {
            if (a[k] > a[k+1])//判断第一个和第二数的关系,大了交换,小了直接进行下一步
            {
                t = a[k];
                a[k] = a[k+1];//实现交换功能
                a[k+1] = t;
            }
        }
    }
    for (int m = 0; m < 5; m++)
    {
        printf("%d\n",a[m]);//将排序好的数字进行输出
    }
}

1.2.2 选择排序
  • 选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完
第一趟排序,找出待数组中最小的一个元素和第一个元素进行交换
第二趟排序,找出待数组中最小的一个元素和第一个元素进行交换

#include<stdio.h>
int main()
{
    int t,Min,num[5] = {0};//定义存放数字的数组、中间变量、最小值
    printf("请输入你要排序的5个数字:\n");
    for(int i = 0; i < 5; i++)
        scanf("%d",&num[i]);
    for (int i = 0; i < 5; i++)
    {
        Min = i;//将最小值的下标标记
       for (int j = i; j < 5; j++)
       {
           if (num[Min] > num[j])//用第一个数开始进行比较,将最小值的下标找出来
           {
               Min = j;
           }
       }
            if(Min != i)//判断该最小值是不是本身,如果不是则进行交换
            {
                t = num[Min];
                num[Min] = num[i];
                num[i] = t;
            }
    }
     for(int i = 0; i < 5; i++)
    {
        printf("%d\n",num[i]);//输出排序后的数字
    }
    return 0;
}
1.2.3 插入排序
  • 插入排序

将一组数据分成两组,分别将其称为有序组与待插入组。每次从待插入组中取出一个元素,与有序组的元素进行比较,并找到合适的位置,将该元素插到有序组当中。就这样,每次插入一个元素,有序组增加,待插入组减少。直到待插入组元素个数为0。当然,插入过程中涉及到了元素的移动。

#include<stdio.h>
int main()
{
    int t,n,j,num[5] = {0};//定义数组并进行初始化长度为5,清零
    printf("请输入你要排序的5个数字\n");
    for(int i = 0; i < 5; i++)
        scanf("%d",&num[i]);//输入排序的数字
    for(int i = 0; i < 5; i++)
    {
       t = num[i];//将待插入数组的第一个值赋予变量t
       j = i-1;//j为有序组中的最后一个数组坐标
       while (j >= 0 && t < num[j])//判断有序数列最大的坐标j是否越界;以及判断即将
       {							//插入的值与已经排序好的值的大小是否满足关系
           num[j+1] = num[j];//若符合判断条件,则将已经在有序数组中的值右移
           j--;//最大的坐标自减,再次进行判断,直到j<0,跳出循环
       }
       num[j+1] = t;//将满足条件的元素插在它应该在的地方
    }
    for(int i = 0; i < 5; i++)
       printf("%d\n",num[i]);//输出排序好的数字
    return 0;
}

1.2.4 二分查找

适应情况:在有序的数据中查找某数

基本思想:选定这批数中居中间位置的一个数与所查数比较,看是否为所找之数,若不是,利用数据的有序性,可以决定所找的数是在选定数之前还是在之后,从而很快可以将查找范围缩小一半。以同样的方法在选定的区域中进行查找,每次都会将查找范围缩小一半,从而较快地找到目的数。

#include<stdio.h>
int main()
{
    int num[13] = {5,7,9,15,17,24,28,30,31,38,42,47,51};//定义了一个长度为13的有序数组
    int max,min,mid,which_num,length = 13;//定义了数组的长度给length
    max = length - 1; min = 0;//将数组的最大和最小坐标表示出来
    mid = (max + min)/2;//定义数组中间的值的坐标
    printf("请输入你要查找的数字:\n");
    scanf("%d",&which_num);

    while(1)//设置一个循环,条件可以自己添加
    {
        if(which_num == num[mid] )//判断中间的值是否为寻找的值
        									   //或者最大值与最小值重合
        {
            printf("你要找的数在该数组的%d位!\n",mid+1);//输出寻找的值的位置
            break;							//此处必须加break循环跳出,不然会一直死循环
        }
        else if(which_num > num[mid])		//判断寻找的值与中间值的关系
        {
            min = mid + 1;
            mid = (max + min) /2;
        }
        else if(which_num < num[mid])	//同理,判断寻找的值与中间值的关系
        {
            max = mid - 1;
            mid = (max + min) /2;
        }
        else
        {
        	printf("该值不存在于该数组中!\n");//这里有点异常,回头我重新调试一下
        	break;
        }
    }
    return 0;
}

2.二维数组

2.1 基本概念和注意事项

  • 定义方法:数据类型 数组名[常量表达式1] [常量表达式2] = {初始化数据]
  • 注意的点

1.int a[][] = {1,2,3,4,5,6,7,8,9};对于数组a中,其第一维长度可以省略,但是二维长度不能省略;

2.2 数组的行指针和列指针

  • 拿 int a[][3] = {1,2,3,4,5,6,7,8,9};为例

a:a在这里表示的是行指针,是二级地址,整个一行的地址;
a + 1 :a + 1在这里表示行指针加上1,则转到第二行;
a[0] :表示第一元素的地址,是列指针;
a[0] + 1 :表示列指针加上1,则就是本行的下一个元素。

  • 二维数组与一维数组比较
  • 拿 int a[n];为例

a :表示列指针
&a:一级地址再取地址就是二级地址

  • 问题:&a + 1会偏移几个字节?

由于int型是4个字节,所以会偏移4n个字节!

3.字符数组

3.1 基本概念和注意事项

  • 模型char ch[n]; char str[n1][n2];
  • 注意事项

1.char ch[3] = {‘b’,‘o’,‘y’};的表示是正确的的。而char str[3] = “boy”;的表示是错的,因为在字符串数组中的最后一位是’\0’,不可以省略!所以它的长度应该为4

4.字符串处理函数

4.1 gets(s)函数

gets(s)函数总能获得一行,并放到s指向的内存,还会把结尾的’\n’转换成’\0’

4.2 字符串连接函数——strcat 和 strncat

  • strcat(str1,str2);

表示将str2的字符串连接到str1字符串的尾部,并且覆盖掉’\0’;

  • strncat(str1,str2,n);

表示将str2的第n个字符串(包含’\0’)连接到str1字符串的尾部,并且覆盖掉str1的’\0’;

  • 注意事项

str1的容量必须要满足str2,否则会出现越界的问题;

4.3 字符串拷贝函数——strcpy 和 strncpy

  • strcpy(str1,str2);

将字符串str2,拷贝到str1的内容中;

  • strncpy(str1,str2,n);

将字符串str2的n个字符,拷贝到str1的内容中;

  • 注意事项
  1. 字符数组str1的容量必须足够大
  2. 拷贝时‘\0’一同拷贝,并且str1的内容随着str2的’\0’被阻断到内存。
  3. 不能使用赋值语句为一个字符数组赋值

4.4 字符串比较函数——strcmp 和 strncmp

  • strcmp(str1,str1);

对两个字符串从左至右逐一比较(ASCLL),直到遇到不同字符或者’\0’
若str1>str2:返回1;若str1<str2,返回-1;相等返回0

  • strncmp(str1,str2,n)

对两个字符串从左至右的前n个字符逐一比较(ASCLL),直到遇到不同字符或者’\0’
若str1>str2:返回1;若str1<str2,返回-1;相等返回0

4.5 字符串长度函数——strlen(字符数组)

  • strlen(字符数组)

返回字符串长度,不包括’\0’

4.6字符串比较函数——strcasecmp 和 strncasecmp

  • strcasecmp(str1,str2)

同strcmp函数一样,不同的是strcasecmp不区分大小写的比较

  • strncasecmp(str1,str2,n)

同strncmp函数一样,不同的是strcasecmp不区分大小写的比较

5.内存管理函数

int a[100] = {1,2,3};
int b[5];
int c = 2016int ch[] = "asdad";
float f = 4.56;
char buf[20] = {0};

5.1 内寸字符拷贝函数——memcpy

  • memcpy(b,a,sizeof(a))

将a内存中的内容拷贝到b;

5.2 内存比较函数——memcmy

  • memvmy(a,b,sizeof(a))

比较两个地址的大小,前面大返回1,后面大返回-1,相等返回0;

5.3 ssprintf()函数

  • 问题:上述代码想输出://buf = 2016=asd=4.5
sprintf(buf,"$d=%.3s=%.lf",c,ch+2,f); // 系统会自动四舍五入!
printf("%s\n",buf);

5.4 字符分割函数——sscanf()

  • 输入char buf [] = “2020/03/04”,输出2020 03 04分别给y,m,d
char buf[] = "2020/03/04"
int y,m,d;
scanf(buf,"%d%d",src1,scr2);// 不加取地址符号;
printf("%s",buf);
sscanf(buf,"%[^=]=%s");
  • 注意——[^=]表示遇到 ‘=’ 停止;

二.疑难问题与难点

1.在对未初始化的数组定义时需要进行什么?怎么进行?

在对未初始化的数组定义是需要进行清零操作。具体操作如下:

char B[10] = {0};
char C[10] = {'\0'}; 
char A[10] = {'0'};//这里是字符0,所以不是清零操作

2. 数组越界的危害都有哪些?

1.会覆盖其他变量的值;
2.越界过长会出现段错误;越界短会覆盖其他值;
3.超界过长时,系统会kill掉该进程

3. 关于二维数组里面的行指针和列指针怎么理解?

假定二维数组 int ch[2][2] = {1,2,3,4};二维数组里面的行指针指的是就是a,在进行操作的时候,行指针a+1表示表示a[1][0],直接跳过了a[0][1];而列指针的表示为a[0],其操作为a[0]+1表示的是该行的下一个元素,a[0]+1表示a[0][1];
补充:*(a + n) == a[n]

三.课上练习

1.用数组求Fibonacci数列前40项。

在这里插入图片描述

#include<stdio.h>
int main()
{
       int a[40];
       for (int n = 0;  n < 40 ; n++)
       {
           if (n <2)
           {
              a[n] = 1;
          }
          else if(n >= 2)
          {
              a[n] = a[n-1] + a[n-2];
          }
      }
      for (int j = 0; j < 40; j++)
      {
          printf("%d\n",a[j]);
      }

  return 0;
  }

2.

四.自我总结

今天数组的学习,整体的难度有了增加,自己的挑战也越来越大;自己在课上的练习做的整体不好,原因是自己做题的时候思路太过奇葩,偏离了题意,导致了自己的速度和节奏没有跟上,但是在课下,我还是会花时间解决遗留的问题。
越来越感觉到自己像一个初入战场的战士,任重而道远!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值