C语言_0304笔记_数组:数组运算/初始化/sizeof/数组里有几个数/新素数判断/二维数组/3*3井字棋

8.2.1 数组运算

数组集成初始化

  • 数组定义和初始化有两种方式:

  1. 确定大小的数组

int number [100] ;//定义数组 数组大小为100
number [cnt] = x;//对数组里的元素赋值:number数组里面的第cnt个元素赋值为x
  1. 不确定大小的数组

int a[] = {2,4,6,7,1,3,5,9,11,13,23,14,32};
  • 第二种方式, 没有给出数组大小,直接用大括号给出了数组的所有元素的初始值,这种定义方法不需要给出数组的大小,让编译器替你数数填入。

  • 相反的,如果定义了数组的大小,在大括号内录入了少于数组大小-1的数据,则编译器会替你将剩余的单元填上0.

int a[13]={2};     //2 0 0 0 0 0 0 0 0 0 0 0 0 

数组初始化【改进】

int main(void)
{
    int x;
    const int NUMBER = 10;//定义数组大小
    int count[NUMBER]={0};//定义数组并初始化
    int i;
//for(i=0;i<NUMBER;i++)
//{
//    count[i]=0;
//} 
这段注释掉的代码与初始化为0的语句作用相同

初始数据稀疏的数组C99

//集成初始化的定位

数组里面有几个数 sizeof

  • sizeof:可以给出整个数组占据的内容大小,单位是字节

int a[ ]={1,2,3,4,5,6,7,8,9,10,11,12,13}

对于数组a,sizeof(a)=52 sizeof(a[0])=4

  • 然后除以类型的字节单位(可以用数组单个元素大小代替),就可以得到数组大小

  • sizeof(a)/sizeof(a[0])

//这个代码的好处是当我们修改数组中初始数据时,不需要改动遍历代码

数组的赋值

int a[]={2,4,6,8,10};
int b[]=a;//不可以!!!!

可以这样将数组a赋值给b数组吗?完全不能~

因为数组是特殊的变量(实际上是const)

要想将一个数组的元素赋值给另一个数组,必须采用遍历

遍历数组for

  • 通常我们使用for循环遍历数组,当设置循环变量 (i>0;i<数组长度/13;i++),这样的话循环体内最大的i正好是数组最大的有效下标 /12

  • 常见错误:

  • 循环条件错误设置为:<=数组长度

  • 离开循环之后用i值做数组元素下标//此时i的值是数组无效的下标/13

注意:

  • search函数中,数组作为函数参数时候,因为不能在[]中给出数组的大小

  • 不能利用sizeof计算数组元素个数

  • 所以需要用另一个参数来传入数组大小。而且在函数头中输入数组大小也是没有意义的

int search(int key,int a[10])//这样的定义是没有意义的

8.2.2素数表+判断素数

用比x小的素数来测试x是否为素数。需要一张已有素数的表,因为素数比起全体数字来说是稀有的。如果要构造这样一张表,假如是100个素数的表,程序如下

#include<stdio.h>
int isPrime(int x, int knownPrimes[], int numberofKnownPrimes);
int main()
{
    const int NUMBER = 10;//定义数组大小10
    int prime[NUMBER] = { 2 };//初始化为2,为第一个素数
    int count = 1;//计数变量为1,已经有一个素数2了
    int i = 3;//从3开始测试
 
    while (count<NUMBER)
    {
        if (isPrime(i,prime,count))//如果用函数判定i是素数
        {
            prime[count++] = i;//将i添加到素数数组中,并且计数变量增1,作为prime的下标
        }
    //调试代码 
        {
            printf("i=%d \tcnt=%d\t",i,count);
            int i;//局部变量,仅在这个大括号内生效
            for(i=0;i<NUMBER;i++)
            {
                printf("%d\t",prime[i]);
            }
            printf("\n");
        }
    //tiaoshi        
        i++;//数字步进1
    }
    
    for ( i    = 0; i < NUMBER; i++)
    {
        printf("%d", prime[i]);
        if ((i+1)%5)
        {
            printf("\t");
        }
        else
        {
            printf("\n");
        }
        return 0;
    }
}
int isPrime(int x, int knownPrimes[], int numberofKnownPrimes)
{
    int ret = 1;
    int i;
    for ( i = 0; i < numberofKnownPrimes; i++)
    {
        if (x%knownPrimes[i]==0)
        {
            ret = 0;
            break;
        }
    }
    return ret;
}

要点:

  1. prime[count++] = i;//

  1. 此时cnt不再是“计数器”,不能理解为计数已经找到的素数个数,而是一种“指针”类似,依次指向数组的下标。

  1. cnt++是先取值后自增

  1. ++a:先自增后取值;a++:先取值后自增

  1. 将第i添加到下标为cnt的素数数组中,然后cnt自增,指向数组的下一个位置

  1. 调试代码,要加{ 大括号 }

  1. 大括号中可以定义自己的局部变量 i ,仅在这个大括号内生效

  1. 也可以先使用外面的变量的值,然后再重新定义

//调试代码 
        {
            printf("i=%d \tcnt=%d\t",i,count);
            int i;//局部变量,仅在这个大括号内生效
            for(i=0;i<NUMBER;i++)
            {
                printf("%d\t",prime[i]);
            }
            printf("\n");
        }

新思路的素数表

  • 前几种方案都是不断遍历数字,判断是否是素数。那么思考一下如果我们是直接构造一张表,最后留下来的数都是素数。算法如下:

  • 这种方法是遍历倍数。简单来说,第一个数是2,是素数,删去2的倍数。然后下一个数字是3,是素数,删去3的倍数。下一个是5,是素数,删去5的倍数。然后是7,删去7的倍数。然后是11...依次类推,最后留在这个表里的数字就都是素数了。

  • 伪代码如图:(n以内素数)

具体做法

  1. 开始将所有数字都赋值1,

  1. 然后从2开始判断素数,将素数倍数的下标赋值0(也就意味着不是素数),

  1. 并且作为筛选的条件,所以当其不作为素数时不会计数。

  1. 在最后的循环会遍历输出全部素数。

  1. 25以内的素数,不会判断25是不是素数,只能数到23是素数。

PS:算法不一定和人的思考方式相同~

8.2.3二维数组

二维数组的概念

int a[3][5] ;  //可以理解为3行5列的矩阵。a00 - a24

二维数组的遍历

与一维数组不同,此遍历需要用到两重循环

  • a[i][j]是一个int型变量,表示第i行第j列

  • a[i,j]什么意思?//逗号运算符右边的作为结果,因此相当于a[j]

二维数组的初始化

(定位就是从半中间开始定义)

二维数组例子:井字棋

#include <stdio.h>
 
int main()
{
    const int SIZE = 3;
    int board[SIZE][SIZE];
    int i,j;
    int num0fX;//X
    int num0f0;//O
    int result = -1;//-1平局 1是X赢 0是O赢
 
    //读入矩阵
    for ( i = 0; i < SIZE; i++)
    {
        for ( j = 0; j < SIZE; j++)
        {
            scanf("%d", &board[i][j]);
        }
    }
 
    //检查行
    for ( i = 0; i < SIZE; i++)
    {
        num0f0 = num0fX = 0;
        for ( j = 0; j < SIZE; j++)
        {
            if (board[i][j]==1)
            {
                num0fX++;
            }
            else
            {
                num0f0++;
            }
        }
        if (num0f0==SIZE)
        {
            result = 0;
        }
        else if (num0fX == SIZE) {
            result = 1;
        }
    }
 
    //检查列
    for (j = 0; j < SIZE; j++)
    {
        num0f0 = num0fX = 0;
        for (i = 0; i < SIZE; i++)
        {
            if (board[i][j] == 1)
            {
                num0fX++;
            }
            else
            {
                num0f0++;
            }
        }
        if (num0f0 == SIZE)
        {
            result = 0;
        }
        else if (num0fX == SIZE) {
            result = 1;
        }
    }
    //正对角线
    num0f0 = num0fX = 0;
    for (i = 0; i < SIZE; i++)
    {
            if (board[i][i] == 1)//a11 a22 a33
            {
                num0fX++;
            }
            else
            {
                num0f0++;
            }
        }
        if (num0f0 == SIZE)
        {
            result = 0;
        }
        else if (num0fX == SIZE) {
            result = 1;
        }
    }
//副对角线
 
    num0f0 = num0fX = 0;
    for (i = 0; i < SIZE; i++)
    {
        if (board[i][SIZE-i-1] == 1)
        {
            num0fX++;
        }
        else
        {
            num0f0++;
        }
    }
    
    return 0;
 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值