C语言-8.数组

63 阅读12分钟

@TOC

8.1数组

8.1.1初试数组

如何写一个程序计算用户输入的数字的平均数?

#include<stdio.h>
int main()
{
    int digit;//输入要求平均数的数字
    double sum=0;//记录输入数字的和
    int count=0;//记录输入数字的个数
    printf("请输入一组数字,用来求平均数,以-1结束\n");
    scanf("%d",&digit);
    while(digit!=-1)//使用while循环将数字累加到sum中,直到输入-1结束循环
    {
        sum+=digit;
        count++;
        scanf("%d",&digit);
    }
    printf("平均数为%f\n",sum/count);
}

这个代码不需要记录用户输入的每一个数。 如何写一个程序计算用户输入的数字的平均数,并输出所有大于平均数的数? 必须先记录每一个输入的数字,计算平均数之后,再检查记录下来的每一个数字,与平均数比较,决定是否输出 如何记录很多事? sum1,sum2,sum3... 数组 int number[100]; scanf("%d",&number[i]); 数组

#include<stdio.h>
int main()
{
    int digit;//输入要求平均数的数字
    int Arr[100];//将输入的数字存入数组
    int a = 0;//记录输入的数字个数
    double sum =0;//记录输入数字的和
    printf("请输入一组数字,用来求平均数,以-1结束\n");
    for(int i=0;i<100;i++)
    {
        scanf("%d",&digit);
        if(digit==-1)//输入-1结束循环
            break;
        Arr[a]=digit;
        a++;//记录输入数字个数
        sum+=digit;//记录输入数字的和
        
    }
    printf("平均数为%f\n",sum/a);//输出平均数
    for(int b=0;b<a;b++)//使用for循环遍历数组
    {
        if(Arr[b]>sum/a)//输出大于平均数的数字
        {
            printf("大于平均数的数字有%d ",Arr[b]);
        }
    }
    return 0;
}

int Arr[100];//定义数组 Arr[a]=digit;//对数组中的元素赋值 Arr[b]>sum/a//使用数组中的元素 printf("大于平均数的数字有%d ",Arr[b]);//遍历数组

8.1.2数组的使用:如何定义和使用数组,数组的下标和下标的范围

定义数组 <类型>变量名称[元素数量] int grades[100]; double weight[20]; 元素数量必须是整数 C99之前:元素数量必须是编译时刻确定的字面量,在C99可以使用变量来确定元素数量 数组 是一种容器(放东西的东西),特点是: 其中所有的元素具有相同的数据类型; 一旦创建,不能改变大小 *(数组中的元素在内存中是连续依次排列的) int [10]

一个int数组 十个单元:a[0],a[1]...a[9] 每个单元就是一个int类型的变量 可以出现在赋值的左边或右边: a[2]=a[1]+6; *在赋值左边的叫做左值 数组的单元 数组的每个单元就是数组类型的一个变量 使用数组时放在[]中的数字叫做下标或索引,下标0开始计数: grades[0] grades[99] average[5] 有效的下标范围 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元做读还是写 一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃 SEGMENTATION FAULT 但是也可能运气好,没造成严重的后果 所以这是程序员的责任来保证程序只使用有效的下标值:[0,数组的大小-1] 计算平均数 在C99中可以先让用户输入有多少数字要计算,来确定数组的大小 长度为0的数组? int a[0] 可以存在,但是无用

8.1.3数组的例子:统计个数

#include<stdio.h>
int main()
{
    const number =10;//定义数组的大小
    int Arr[number];//定义数组
    int x;//输入要求统计的数字
    for(int i=0;i<number;i++)//将数组元素初始化为0
    {
        Arr[i]=0;
    }
    printf("请输入一组数据,用来统计每一个数字出现的个数:");
    scanf("%d",&x);//输入数字
    while(x!=-1)//使用while循环将数字出现的个数存入数组中
    {
        Arr[x]++;//将数字出现的个数存入数组中
        scanf("%d",&x);//输入数字
    }
    for(int j=0;j<number;j++)//使用for循环遍历数组
    {
        printf("%d:%d\n",j,Arr[j]);//输出数字出现的个数
    }
    return 0;

}

8.2数组运算

8.2.1数组运算

在一组给定的数据中,如何找出某个数据是否存在?

#include<stdio.h>
int find(int x,int Arr[],int len);
int main()
{
    int x;//要查找的数字
    int Arr[]={1,4,2,3,5,0,8,6,7,12,25,47,84,32};//定义数组
    int len=sizeof(Arr)/sizeof(Arr[0]);//计算数组的长度
    printf("请输入要查找的数字:");
    scanf("%d",&x);//输入要查找的数字
    int index=find(x,Arr,len);//调用函数
    printf("%d在第%d位",x,index+1);
}

int find(int x,int Arr[],int len)//定义一个寻找数字的函数
{
    for(int i=0;i<len;i++)//使用for循环遍历数组
    {
        if(Arr[i]==x)//如果找到了数字
        {
            return i;//返回数字的下标
        }
    }
    return 0;
}

数组的集成初始化 int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32}; 直接用大括号给出数组的所有元素的初始值 不需要给出数组的大小,编译器替你数数 int b[20]={2}; 如果给出了数组的大小,但是后面的初始值数量不足,则其后的元素被初始化为0 集成初始化时的定位 int a[10]={ [0]=2,[2]=3,6, }; 用[n]在初始化数据中给出定位 没有定位的数据接在前面的位置后面 其他位置的值补零 也可以不给出数组大小,让编译器算 特别适合初始数据稀疏的数组 数组的大小 sizeof给出整个数组所占据的内容的大小,单位是字节 sizeof(a)/sizeof(a[0]) sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数 这样的代码,一旦修改数组中初始的数据,不需要修改遍历的代码 数组的赋值 int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32}; int b[]=a;是错误的数组赋值 数组变量本身不能被赋值 要遍历一个数组的所有元素交给另一个数组,必须采用遍历

for(i=0;i<length;i++)
{
	b[i]=a[i];
}

遍历数组 通常都是使用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标 常见错误是: 循环结束条件是<=数组长度,或离开循环后,继续用i值来做数组元素的下标!

==数组作为函数参数时,往往必须再用另一个参数来传入数组的大小== 数组作为函数的参数时: 不能在[]中给出数组的大小 不能再利用sizeof来计算数组的元素个数!

8.2.2数组的例子:素数

判断素数 简单版本

#include<stdio.h>
int Prime(int x);
int main()
{
    int x;//输入一个整数,判断是不是素数
    printf("请输入一个整数");
    scanf("%d",&x);
    if(Prime(x))//调用Prime函数,如果返回值为1则是素数,否则不是素数
    {
        printf("是素数");
    }
    else
    {
        printf("不是素数");
    }
}
int Prime(int x)//判断是否为素数的函数
{
    int temp=1;//定义一个临时变量,1为素数,0为不是素数
    for(int i=2;i<x;i++)
    {
        if(x%i==0);
        {
            temp=0;
            break;
        }
    }
    return temp;
}

去掉偶数后,从3到x-1,每次加2

#include<stdio.h>
int main()
{
    int x;//输入一个整数,判断是不是素数
    printf("请输入一个整数");
    scanf("%d",&x);
    if(Prime(x))//调用Prime函数,如果返回值为1则是素数,否则不是素数
    {
        printf("是素数");
    }
    else
    {
        printf("不是素数");
    }

}
int Prime(int x)//判断是否为素数的函数
{
    int temp=1;//定义一个临时变量,1为素数,0为不是素数
    if(x==1 || x%2==0 && x!=2)//排除1不是素数,2的倍数不是素数,2是素数
    {
        temp=0;
    }
    else
    {
        for(int i=3;i<x;i+=2)//从3开始,排除偶数,排除偶数后,只需要判断奇数是否能被整除即可,
        {                    //因为偶数除以奇数的余数一定是1,所以只需要i从3开始,每次加2即可
            if(x%2==0)
            {
                temp=0;
            }
        }
    }
    return temp;
}

因为偶数一定不是素数 无需到x-1,到sqrt(x)就够了

#include<stdio.h>
#include<math.h>
int main()
{
    int x;//输入一个数判断是否为素数
    printf("请输入一个数");
    scanf("%d",&x);
    if(isPrime(x))//使用isPrime函数判断
    {
        printf("是素数");
    }
    else
    {
        printf("不是素数");
    }
}
int isPrime(int x)//判断是否为素数的函数
{
    int temp=1;//定义一个临时变量temp如果这个数是素数则temp等于1,否则等于0
    if(x==1 || x%2==0 && x!=2)//排除1不是素数,2的倍数不是素数,2是素数
    {
        temp=0;
    }
    else
    {
        for(int i=3;i<=sqrt(x);i+=2)//从3开始,排除偶数,排除偶数后,只需要判断奇数是否能被整除即可,
        {                           //因为偶数除以奇数的余数一定是1,所以只需要i从3开始,每次加2即可
                                    //判断结束的标志是小于等于根号x
            if(x%i==0)
            {
                temp=0;
            }
        }
         
    }
    return temp;
}

sqrt是开根号 判断是否能被已知的且<x的素数整除

#include<stdio.h>
int isPrime(int x,int prime[],int count);
#define number 10
int main()
{
    int prime[number]={2};//定义一个数组存储小于number的素数
    int count =1;//数组的下标,也就是存储素数的位置
    int x=3;//每一个数字
    while(x<number)
    {
        if(isPrime(x,prime,count))//调用isPrime函数判断素数
        {
            prime[count++]=x; //如果这个数是素数,就将这个数存储在数组的相应位置上
        }
        
        {
            printf("x=%d \tcount=%d\t",x,count);//每一次存储都将数组里的数字输出打印出来
                for(int i=0;i<number;i++)
            {
                printf("%d ",prime[i]);
            }
            printf("\n");
        }
        x++;
    }
    for(int i=0;i<count;i++)//遍历打印数组里的数字
    {
        printf("%d ",prime[i]);
    }

    
}
int isPrime(int x,int prime[],int count)
{ 
    int temp=1;
    for(int i=0;i<count;i++)//使用循环判读x是否为素数
    {
        if(x%prime[i]==0)//判断素数的方法是除以数组中已经有的素数,看是否能整除
        {
            temp=0;
            break;
        }
    }
    return temp;
}

构造素数表 欲构造n以内的素数表 1.令x为2 2.将2x,3x,4x直至ax<n的数标记为非素数 3.令x为下一个没有被标记为非素数的数,重复2;直到所有的数都已经尝试完毕

#include<stdio.h>
#define number 30//判断0到number减一的素数
int isPrime(int x);
int main()
{
    int prime[number];//定义一个数组存放是否为素数的标志
    for(int j=0;j<number;j++)//将数组中所有的元素都赋值为1
    {
        if(j==0 || j==1)//将特殊的0和1提前赋值为0
        {
            prime[j]=0;
        }
        else
        {
            prime[j]=1;
        }
        
    }
    int a;//每一个数字
    for(a=2;a<number;a++)//循环的将每一个数字交给isPrime函数
    {
        if(isPrime(a))//如果这个数是素数,则他的倍数一定不是素数
        {
            for(int i=a*2;i<number;i=i+a)//将a的倍数的数组下标里的值都赋值为0
            {
                prime[i]=0;
            }
        }
        else//如果a不是素数则a的数组的下标里的值直接为0
        {
            prime[a]=0;
        }

    }
    for(int k=0;k<number;k++)//输出时的表头
    {
        printf("%3d",k);
    }
    printf("\n");
    for(int i=0;i<number;i++)//输出数组
    {
        printf("%3d",prime[i]);
    }
    
}
int isPrime(int x)//判断是否为素数的函数
{
    int temp=1;
    for(int i=2;i<x;i++)
    {
        if(x%i==0)
        {
            temp=0;
            break;
        }
    }
    return temp;
}

8.2.3二维数组

int a[3][5]; 通常理解为a是一个3行5列的矩阵 在这里插入图片描述 二维数组的遍历 在这里插入图片描述

  • a[i][j]是一个int
  • 表示第i行第j列上的单元
  • a[i,j]是什么? 因为逗号也是一个运算符,逗号运算符会先对左侧的表达式进行计算,接着计算右侧的表达式,最终整个逗号表达式的结果是右侧表达式的值。也就是说a[i,j]相当于a[j] 二维数组的初始化
int a[][5] = {
	{0,1,2,3,4},
	{2,3,4,5,6},
};
  • 列数是必须给出的,行数可以由编译器来数
  • 每行一个{},逗号分隔
  • 最后的逗号可以存在,有古老的传统
  • 如果省略,表示补零
  • 也可以用定位 tic-tac-toe游戏 代码如下
#include<stdio.h>
int hang(int board[][3]);
int lie(int board[][3]);
int zuo(int board[][3]);
int you(int board[][3]);

int result =-1;//-1表示平局,1表示叉赢,0表示圈赢
int main()
{
    int board[3][3];
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            printf("请输入第%d行%d列",i+1,j+1);
            scanf("%d",&board[i][j]);
        }        
    }
    int hang_result=hang(board);
    int lie_result=lie(board);
    int zuo_result=zuo(board);
    int you_result=you(board);
    if(hang_result==1 || lie_result==1 || zuo_result==1 || you_result==1)
    {
         result=1;
    }
    else if(hang_result==0 || lie_result==0 || zuo_result==0 || you_result==0)
    {
        result=0;
    }
    else
    {
        result=-1;
    }
    if(result==1)
    {
        printf("叉获胜");
    }
    else if(result==0)
    {
         printf("圈获胜");
    }
    else if(result==-1)
    {
        printf("平局");
    }
}
//检查行
int hang(int board[][3])
{
    int A1;//表示叉
    int A0;//表示圈
    for(int i=0;i<3;i++)
    {
        A1=A0=0;
        for(int j=0;j<3;j++)
        {
            if(board[i][j]==1)
            {
                A1++;
            }
            else
            {
                A0++;
            }
        }
        if(A0==3)
        {
            return 0;
        }
        else if(A1==3)
        {
            return 1;
        }
    }
    return -1;
}
//检查列
int lie(int board[][3])
{
    int A1;//表示叉
    int A0;//表示圈
    for (int j=0;j<3;j++)
    {
        A0=A1=0;
        for(int i=0;i<3;i++)
        {
            if(board[i][j]==1)
            {
                A1++;
            }
            else if(board[i][j]==0)
            {
                A0++;
            }
        }
        if(A1==3)
        {
            return 1;
        }
        else if(A0==3)
        {
            return 0;
        }
    }
    return -1;
}
//检查左线
int zuo(int board[][3])
{
    int A1=0;//表示叉
    int A0=0;//表示圈
    for (int i=0,j=0;i<3 && i<3;i++,j++)
    {
        if(board[i][j]==1)
        {
            A1++;
        }
        else if (board[i][j]==0)
        {
            A0++;
        }
    }
    if(A1==3)
    {
        return 1;
    }
    else if(A0==3)
    {
        return 0;
    }
    return -1;
}
//检查右线
int you(int board[][3])
{
    int A1=0;//表示叉
    int A0=0;//表示圈
    for(int i=0,j=2;i<3 && j>-1;i++,j--)
    {
        if(board[i][j]==1)
        {
            A1++;
        }
        else if(board[i][j]==0)
        {
            A0++;
        }
    }
    if(A0==3)
    {
        return 0;
    }
    else if(A1==3)
    {
        return 1;
    }
    return -1;
}