【c语言跟练】笔记5-数组

引言

1.什么是数组

  • 数组就是一次性定义了一群变量,没有变量名,但可以根据位置放,like home。

//输入1 2 3 4 5 6 7 8 9 10 -1
#include <stdio.h>
int main()
{
    int num;
    int sum = 0;
    int count = 0;
    int home[100]; //加入存100数以内

    //求和,计数,以求平均数
    do {
        scanf("%d", &num);
        if (num != -1) {
            sum += num;
            count++;
            home[count] = num; //数组home中第count个位置存入此时的num
            //* 为了观察数组存储数的方式
            {
                int i;
                printf("count = %d, \thome: \t", count);
                for (i = 1; i <= count; i++) {
                    printf("%d\t", home[i]);
                }
                printf("\n");
            }
        }
    } while (num != -1);
    //求平均数
    double aver = 1.0 * sum / count;
    printf("aver = %f\n", aver);
    
    printf("平均数以上的数:\n");
    //输出平均数以上的数
    int i;
    for (i = 1; i <= count; i++) {
        if (home[i] > aver) {
            printf("%d\n", home[i]);
        }
    }

    return 0;
}

BUG:数组可能越界

  • 解决方案1:数超过100个,就不再计入了

  • 解决方案2:提前告诉计算机将要输入的数个数,直接定好home[数量]

第八章 数组

1.数组简介

1.数组的定义

一般格式:<类型> 变量名称[元素数量];

int grades[100];
double weight[20];

注意事项:

  • 元素数量必须是整数

  • c99前编译器要求元素数量是字面常量,但之后的编译器也可以用变量,PTA系统建议字面常量

2.数组的特点

  • 数组一种容器

  • 数组一旦创建,不能改变大小

  • 其中所有的元素具有相同的数据类型

  • 数组中的元素再内存中是连续依次排列的

  • 数组可以出现在赋值符的左边或右边;右边读取值(右值),左边往里写东西(左值)

a[2] = a[1] + 6

3.数组的单元

  • 数组的每个单元就是数组类型的变量

4.数组的下标

  • 使用数组时放在[]中的数字叫下标或索引,从0开始计数,范围是0 ~元素变量-1

  • 编译器不会检查数组下标是否越界——编程习惯,自己注意别越界

越界可能会出现:segmentation fault报错

总结:数组的使用

其他:长度为0的数组

int a[0];
  • 可以存在,但没必要

  • 任何一个数都会越界,所以这个数组无用

课堂练习1:数量不确定

//stu
// 输入1 2 3 4 5 9 8 7 5 2 4 5 6 5 0 1 0 0 0 1 5 2 4 5 6 9 8 7 8 5 5 5 -1
#include <stdio.h>
int main()
{
    int home[500];

    // 挨个读数,存入数组
    int num = 0;
    int count = 0;
    if (count <= 500) {
        while (num != -1) {
            scanf("%d", &num);
            if (num != -1) {
                home[count] = num;
                count++;
            }
        }
    }

    //10次遍历,每次用一个数去比较
    int j;
    for (j = 0; j <= 9; j++) {
        int i;
        int cnt = 0;
        for (i = 0; i <= (count - 1); i++) {
            if (home[i] == j) {
                cnt++;
            }
        }
        printf("%d:%d个\n", j,cnt);
    }

    return 0;
}

tea:不用每个数都存,计数就行,所以需要十个变量

// tea-stu
// 输入1 2 3 4 5 9 8 7 5 2 4 5 6 5 0 1 0 0 0 1 5 2 4 5 6 9 8 7 8 5 5 5 -1
#include <stdio.h>
int main()
{
    int home[10];

    {
        int i;
        for (i = 0; i <= 9; i++) {
            home[i] = 0;
        }
    }

    int num = 0;
    while (num != -1) {
        scanf("%d", &num);
        if (num != -1) {
            home[num]++;
        }
    }

    int i;
    for (i = 0; i <= 9; i++) {
        printf("%d: %d\n", i,home[i]);
    }

    return 0;
}
//tea 与我不一样的地方1
if (num >= 0 && num <= 9) {
    home[num]++;
}

//tea 与我不一样的地方2
const int end = 10;
// tea
// 输入1 2 3 4 5 9 8 7 5 2 4 5 6 5 0 1 0 0 0 1 5 2 4 5 6 9 8 7 8 5 5 5 -1
#include <stdio.h>
int main()
{
    const int begin = 0;    
    const int end = 10;
    int home[end];

    {
        int i;
        for (i = begin; i < end; i++) {
            home[i] = 0;
        }
    }

    int num = 0;
    while (num != -1) {
        scanf("%d", &num);
        if (num >= begin && num < end) {
            home[num]++;
        }
    }

    int i;
    for (i = begin; i < end; i++) {
        printf("%d: %d\n", i,home[i]);
    }

    return 0;
}

2.数组运算

思考:在一组给定的数据中,如何找到某个数据是否存在?

1.集成初始化

int a[] = { 1,2,3,4,5,6 };

{
    int i;
    for (i = 0; i < 6; i++) {
        printf("%d\t", a[i]);
    }
}

↑ 6个数,索引0~5,a[0] = 1,a[5] = 6

int a[6] = {2};

↑ 6个数,索引0~5,a[0] = 2,其余a[……] = 0

int a[6] = { [0] = 2,[2]=2,3};//用的编译器不识别
课堂练习:数组集成初始化为0
int a[6] = {0};

2.数组大小——知道有多少数

int a[] = { 1,2,3,4,5,6 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[1]));

热知识:数组一个单元占据4个字节

课堂练习:统计数组内有多少数
sizeof(a)/sizeof(a[0]);

3.数组赋值

  • 数组变量本身不能被赋值

  • 不能整体赋值,只能遍历

int a[] = { 1,2,3,4,5,6 };
// int b[] = a;// 错误!!!!!
for (i=0;i<length;i++){
    b[i] = a[i];
}

4.数组遍历

  • 通常都是使用for循环,让循环变量从0开始到<length,这样循环体内最大的i正好是数组最大的有效下标

  • 常见错误:①循环结束条件是<length,而不是<=;②循环结束,继续用i的值作数组元素下标❌

int i;
for (i = 0; i < 7; i++) {
}

printf("i = %d", i); // 最后i=7

int j;
for (j = 0; j <= 6; j++) {
}

printf("j = %d", j);// 最后j=7

5.数组作函数参数

#include <stdio.h>
/*
* 函数search用于找出数key在数组a中的位置
* @param key 要找的数
* @param a 要遍历的数组
* @param length 要遍历的数组长度
* @return 如果找到,返回其在a中的位置,如果找不到,返回值-1
*/
int Search(int key, int a[], int length);

int main()
{
    int a[] = { 1,2,3,4,5,6 };
    int x;
    printf("请输入一个数字:");
    scanf("%d", &x);
    int len = sizeof(a) / sizeof(a[0]);

    int loc = Search(x,a,len);//注意数组,直接用a,而不是a[]
    if (loc != -1) {
        printf("%d在数组a中%d位置\n",x,loc);
    }
    else {
        printf("%d不在数组a中\n",x);
    }

    return 0;
}

int Search(int key, int a[], int length)
{
    int ret = -1;
    int i;
    for (i = 0; i < length; i++) {
        if (a[i] == key) {
            ret = i;
            break;//自己写没想到这步
        }
    }
    return ret;
}

注意事项:

  • 数组作为函数参数,必须再用另一个参数传入数组大小

  • 数组作为函数参数,不能在声明中给出数组大小,只能a[],不能a[number]

  • 数组作为函数参数,不能再定义中用sizeof来计算数组的元素个数(别问为什么,就这样吧

课堂练习2:素数

#include <stdio.h>
int isPrime(int x)
{
    int ret = 1;
    int i;
    if (x == 1) {
        ret = 0;
    }
    for (i = 2; i < x; i++) {
        if (x % i == 0) {
            ret = 0;
            break;
        }
    }
    return ret;
}

int main()
{
    int x = 11;
    if (isPrime(x)) {
        printf("Yes!");
    }

    return 0;
}

简化isPrime函数:减少循环次数,提高效率

简化思路:

方案一:先判断是不是偶数,在奇数范围内寻找

#include <stdio.h>
int isPrime(int x)
{
    int ret = 1;
    int i;

    if (x == 1|| (x%2==0 && x!=2)) {
        ret = 0;
    } 

    for (i = 2; i < x; i++) {
        if (x % i == 0) {
            ret = 0;
            break;
        }
    }

    return ret;
}

方案二:在一基础上,缩小结束条件,缩到为根号

#include <math.h>
int isPrime(int x)
{
    int ret = 1;
    int i;
    if (x == 1|| (x%2==0 && x!=2)) {
        ret = 0;
    } 
    for (i = 2; i < sqrt(x); i++) {//基于数学原理
        if (x % i == 0) {
            ret = 0;
            break;
        }
    }
    return ret;
}

方案三:和素数表对照——先得到素数对照表

没明白没明白没明白没明白(已解决)

  • isPrime函数怎么判断素数的没明白,为什么关键条件是 x % a[] == 0,就不是素数——不能被1和本身以外的数整除,数= 素数 * 非素数 = 素数 * 素数 *素数,所以可以素数锁定范围

为啥这样次数就少了?

  • 每个数要判断是不是素数

  • 小于它的所有数去除→小于它的所有素数去除

巧妙的地方

  • 构造素数数组的方法,从2开始一个一个去除,前面的数没有因子(不精准的表述,方便个人理解

#include <stdio.h>
/*
* isPrime函数用来和素数表对照,判断一个数是不是素数
* @param x,输入的数
* @param home,素数表(数组)
* @param len,素数表长度
*/
#include <stdio.h>
int isPrime(int x, int home[], int len)
{
    int ret = 1;
    int i;
    for (i = 0; i < len; i++) {
        if (x % home[i] == 0) { //看能不能被已有素数整除,不能则为素数
            ret = 0;
            break;
        }
    }
    return ret;
}

//总体思路是一边构造表,一边判断是不是
int main()
{
    const int len = 5;
    int primeHome[len] = { 2 };//

    int count = 1;//角标
    int i;

    printf("\t\t");
    int k;
    for (k = 0; k < len; k++) {
        printf("%d\t", k);
    }
    printf("\n");

    for (i = 3; count < len; i++) {//从i=3开始判断是不是素数
        if (isPrime(i, primeHome, count)) {
            primeHome[count++] = i; //是素数,放到素数数组里
        }
        {
            printf("i=%d\tcount=%d\t", i, count);
            int j;
            for (j = 0; j < len; j++) {
                printf("%d\t", primeHome[j]);
            }
        }
        printf("\n");
    }

    printf("素数:\n");
    int j;
    for (j = 0; j < len; j++) {
        printf("%d", primeHome[j]);
        if ((j + 1) % 5 != 0) {
            printf("\t");
        }
        else {
            printf("\n");
        }
    }

    return 0;
}

方案四:删去倍数

//stu1
#include <stdio.h>
int isPrime(int x);
int main()
{
    // 1.创建数组
    const int LEN = 10;
    int prime[LEN];
    int i;

    // 2.漂亮的题头
    for (i = 0; i < LEN; i++) {
        printf("%d\t", i);
    }
    printf("\n");
        
   // 3.假设都为素数,为1
    for (i = 0; i < LEN; i++) {
        prime[i] = 1;
    }

    // 4.已知0不是先排除
    prime[0] = 0;
    //printf("\n");

    // 5.对素数x倍数位置的元素赋0
    int x;
    for (x = 2; x < LEN; x++) {
        if (isPrime(x)) {
            int j;
            for (j = 2; x * j < LEN; j++) {
                prime[x * j] = 0;
            }
        }
    }

    // 6.查看数组
    for (i = 0; i < LEN; i++) {
        printf("%d\t", prime[i]);
    }
    printf("\n");

    return 0;
}

int isPrime(int x)
{
    int i;
    int ret = 1;
    for (i = 2; i < x; i++) {
        if (x % i == 0) {
            ret = 0;
            break;
        }
    }
    return ret;
}
//stu2
#include <stdio.h>
int isPrime(int x);
int main()
{
    // 1.创建数组
    const int LEN = 10;
    int prime[LEN];
    int i;

   // 2.假设都为素数,为1
    for (i = 0; i < LEN; i++) {
        prime[i] = 1;
    }

    // 3.对素数x倍数位置的元素赋0
    int x;
    for (x = 2; x < LEN; x++) {
        if (isPrime(x)) {
            for (i = 2; x * i < LEN; i++) {
                prime[x * i] = 0;
            }
        }
    }

    // 4.查看素数
    for (i = 2; i < LEN; i++) {
        if (prime[i]) {
            printf("%d ", i);
        }
    }
    printf("\n");

    return 0;
}

int isPrime(int x)
{
    int i;
    int ret = 1;
    for (i = 2; i < x; i++) {
        if (x % i == 0) {
            ret = 0;
            break;
        }
    }
    return ret;
}

方案五:在四基础上,循环构建素数表

//tea
#include <stdio.h>
int main()
{
    // 1.创建数组
    const int LEN = 10;
    int prime[LEN];
    int i;

   // 2.假设都为素数,为1
    for (i = 0; i < LEN; i++) {
        prime[i] = 1;
    }

    // 3.对素数x倍数位置的元素赋0
    int x;
    for (x = 2; x < LEN; x++) {
        if (Prim[x]) {//注意这里!!!!!!
            for (i = 2; x * i < LEN; i++) {
                prime[x * i] = 0;
            }
        }
    }

    // 4.查看素数
    for (i = 2; i < LEN; i++) {
        if (prime[i]) {
            printf("%d ", i);
        }
    }
    printf("\n");

    return 0;
}

感想:循环构造素数表的思想,没想到,不是很理解,双线程工作

其他:

primeHome[count++] = i;
primeHome[count++] = i;

//即
primeHome[count] = i;
count++;

//再次理解a++值是a,++a值是a+1,但经历过这个语句后,a值为a+1

怎么查一个函数

了解函数,unix系统man ,win直接百度

3.二维数组

1.一般格式

int a[3][5];

至少给出列

2.二维数组遍历

int i, j;
int a[3][5];
for (i = 0; i < 3; i++) {
    for (j = 0; j < 5; j++) {
        a[i][j] = i * j;
        printf("%d ", a[i][j]);
    }
    printf("\n");
}
a[i][j] & a[i,j]
  • a[i][j]表示第i行第j 列的变量

  • a[i,j]表示a[j],表示第j个变量

课堂练习3:3×3棋盘格

1.读入矩阵

注意:a[i][j]是一个变量,可以直接赋值,格式化输入、输出等

const int size = 3;//这里没想到用一个const
int a[size][size];
int i, j;

// 0.读入矩阵
// 输入1 0 1 0 1 0 1 1 1
for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
        scanf("%d", &a[i][j]);
    }
}

// 查看数组
for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
        printf("%d", a[i][j]);
    }
    printf("\n");
}
// 错误程序,试了一下,这样不可以!!!!
for (i = 0,j = 0; i < 3 && j < 3; i++,j++) {
    printf("%d", a[i][j]);
    printf("\n");
}

2.检查行/列

// 1.检查行
// 利用ret 成行时ret=3
for (i = 0; i < 3; i++) {
    int ret = 0;
    for (j = 0; j < 3; j++) {
        if (a[i][j]) {
            ret++;
        }
    }
    if (ret == 3) {
        printf("Bingo!\n");
    }
}

// 2.检查列
for (j = 0; j < 3; j++) {
    int ret = 0;
    for (i = 0; i < 3; i++) {
        if (a[i][j]) {
            ret++;
        }
    }
    if (ret == 3) {
        printf("Bingo!\n");
    }
}

3.检查对角线

// 3.检查左上-右下对角线
// 11 22 33都为1
{
    int ret = 0;
    for (i = 0; i < 3; i++) {
        if (a[i][i]) {
            ret++;
        }
    }
    if (ret == 3) {
        printf("Bingo!\n");
    }
}

// 4.检查右上-左下对角线
// 13 22 31
{
    int ret = 0;
    for (i = 0; i < 3; i++) {
        if (a[i][4-i]) {
            ret++;
        }
    }
    if (ret == 3) {
        printf("Bingo!\n");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值