Linux和C语言(Day06)

一、学习内容

  1. 数组

    • 什么是数组?

      连续存储[内存连续] 多个 类型相同的 数据的容器
  2. 一维数组

    1. 概念

      由一个下标定义的数组
    2. 语法格式

      1. 定义数组 数据类型 数组名[常量表达式];
      2. 分析
        1. 数据类型——int float double char 结构体 共用体 指针 空void……

        2. 数组名——符合命名规范

        3. []——数组的标志

        4. 常量表达式——数组的长度

      3. 注意
        1. 定义时,[]里面四不准——不为0,不为空,不为小数,不为变量(C99标准之前)

      4. C99标准下
        1. 第一种情况

          1. int n=10; int a[n]; //变长数组 编译不报错

        2. 第二种情况

          1. int n=10; int a[n]={1,2,3}; //变长数组初始化 编译报错【variable-sized object may not be initialized】

    3. 初始化/赋初始值

      1. 数组初始化
        1. 全部初始化 int a[5] = {1 , 2 , 3 , 4 , 5};

        2. 部分初始化 int a[5] = {1 , 2}; //未被初始化的默认为0

        3. 特殊初始化 int a[] = {1 , 2 , 3 , 4 , 5 , 6 , 7}; //根据赋值元素的个数,确定长度 int len = sizeof(a)/sizeof(int);

        4. 错误初始化 int a[5]; a[5]={1 , 2 , 3 , 4 , 5}; float b[5]; float b[5];//数组不能整体赋值

        5. 单个元素赋值 int a[5]; a[0] = 1; //给第一个元素赋值为1 a[1] = 20; //给第二个元素赋值为20 其他没有赋值的元素是一个随机值

        6. 关于数组清0,全部赋值为0

          1. 第一种:int a[5] = {0}; //此处的0放在第一个房间,其他房间没有放,默认是0

          2. 第二种:库函数 memset

            1. 功能:给字符串清空 或者 给整数赋值为0或-1 头文件:#include <string.h>

            2. 函数原型:void *memset(void *s, int c, size_t n); int arr[5]; memset(arr , 0 , sizeof(arr)); memset(arr , -1 , sizeof(arr));

          3. 第三种:库函数 bzero

            1. 功能:归0 头文件:#include <strings.h>

            2. 函数原型:void bzero(void *s, size_t n); int barr[5]; bzero(barr , sizeof(barr));

    4. 数组的引用/使用

      1. int arr[5]; 表示定义了一个长度为5 的整型数组,里面包含5个元素(整数)
      2. 数组的输出
        1. 方式1

          1. printf("%d %d %d %d %d\n" , arr[0] , arr[1] , arr[2] , arr[3] , arr[4]);

        2. 方式2

          1. 使用循环
            for(i=0; i<5; i++){
            printf("%d ",arr[i]);
            } //循环中 i 表示下标 arr[i]表示元素

          2. 注意定义时在C99标准之前[]不为变量引用数组元素是[]可以为常量、变量、表达式 arr[i] arr[1] arr[i+1]

  3. 二维数组

    • 概念

      • 两个下标定义的数组

    • 语法格式

      • 数据类型 数组名[常量表达式1][常量表达式2];

      • 分析

        • 常量表达式1 代表 第一维长度 【行数】

        • 常量表达式2 代表 第二维长度 【列数】

    • 初始化

      • 全部初始化 int a[2][3] = {1 , 2 , 3 , 4 , 5 , 6}; int a[2][3] = {{1 , 2 , 3} , {4 , 5 , 6}};

      • 部分初始化 int a[2][3] = {1 , 2 , 5 , 6}; //1 2 5 , 6 0 0 int a[2][3] = {{1} , {3 , 4}}; //1 0 0 , 3 4 0

      • 特殊初始化【可以省略行不可省略列】 int a[ ][3] = {1 , 2 , 3 , 4 , 5 , 6}; 》》 int a[2][3]; int a[ ][3] = {1 , 2 , 3 , 4}; 》》 int a[2][3]; int a[ ][3] = {{1 , 2 } , {3} , {4,5 , 6}}; 》》 int a[3][3];

      • 错误初始化 int a[2][ ]={1 , 2 ,3}; int a[2][3] = {{1 , 2} , {3 , 4} , {5 , 6}};

      • 如何计算行数和列数 int a[ ][3] = {1 , 2 , 3 , 4}; int sum = sizeof(a); //计算总字节数 int count = sizeof(a)/sizeof(int); //计算总元素个数 int rows = sizeof(a) / sizeof(a[0]); //计算行数 int cols = sizeof(a[0]) / sizeof(a[0][0]); //计算列数

    • 数组的引用

      • int a[2][3]; 定义2行3列的数组,存储6个整型数据。

        • 此处有两个下标——行下标 列下标 行下标范围[0 , 1]列下标范围[0 , 2]

        •                第一列 第二列 第三列
          第一行:a[0][0] a[0][1] a[0][2]
          第二行:a[1][0] a[1][1] a[1][2]

          循环输入: for(i=0; i<行数; i++){ //外行
                                     for(j=0; j<列数; j++){ //内列
                                                printf("a[%d][%d]=%d " , i , j , a[i][j]);
                                       }
                                       printf("\n");
                       }
  4. 脑图
     

二、作业

  1. 编写一个程序。输出以下形式的前五行杨辉三角图案 (石峰)

思路提示:注意拼凑

 代码解答:

#include <stdio.h>

#define ROWS 5  // 输出前五行
#define WIDTH  4 // 每个数字的宽度

int main() {
    int triangle[ROWS][ROWS];  // 存储杨辉三角形的数组

    // 初始化杨辉三角形的所有元素为0
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j <= i; j++) {
            triangle[i][j] = 0;
        }
    }

    // 构建杨辉三角形
    for (int i = 0; i < ROWS; i++) {
        triangle[i][0] = 1;  // 每行的第一个元素为1
        triangle[i][i] = 1;  // 每行的最后一个元素为1
        for (int j = 1; j < i; j++) {
            triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j];
        }
    }

	for (int i = 0; i < ROWS; i++){
		  for (int k = 0; k < (ROWS - i - 1); k++) {
            printf("  ");
        }
		for (int j = 0; j <=i; j++){
			printf("%4d",triangle[i][j]);
		}
		printf("\n");
	}
    return 0;
}

成果展现:

        2.编写一个程序。请用 C、JAVA、C# 任一种语言,对数组 {3, 2, 10, 1, 23, 15, 82} 进行由小到大的排序。(安在软件)

思路提示:

int a[]={3, 2, 10, 1, 23, 15, 82};

int n=sizeof(a)/sizeof(int);

要求使用冒泡排序 简单选择排序实现

代码解答:

简单选择排序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main(int argc, const char *argv[])
{
	int a[]={3,2,10,1,23,15,82};
	//计算数组长度
	int n=sizeof(a)/sizeof(int);
	int i , j ,t;
	//进行简单选择排序
	for(int i=0;i<n-1;i++){
		int min = i;
		for(int j=i+1;j<n;j++){
			if(a[j]<a[min]){
				min = j;
			}
		}
		if(i != min){
			t=a[i],a[i] = a[min],a[min]=t;
		}
	}
	printf("排序后的数组为:");
	for(i=0;i<n;i++){
		printf("%4d",a[i]);
	}
	printf("\n");
	return 0;
}

冒泡排序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
	int a[]={3,2,10,1,23,15,82};
	int len;
    //计算数组长度
	len	= sizeof(a)/sizeof(int);
	int i ,j,temp;
	temp = 0;
    //进行冒泡排序,从小到大
	for(i=0;i<len-1;i++){
		for(j=0;j<len-i-1;j++){
			if(a[j]>a[j+1]){
				temp=a[j],a[j]=a[j+1],a[j+1]=temp;
			}
		}
	}
	for(i=0;i<len;i++){
		printf("%4d",a[i]);
	}
	return 0;
}

3.编写一个程序。假设你有一只刚出生的母兔,母兔第3年开始生小兔,以后每年生一只。如果生出的都是母兔,请代码实现:输入你拥有该母兔后的第几年,输出该年你拥有的兔子数。(北京信果科技)

思路提示:1  1  2  3  5   8   13   21

代码解答:

#include <stdio.h>

int main(int argc, const char *argv[]) {
    int year;
    printf("请输入你拥有母兔的第几年:\n");
    scanf("%d", &year);

    int n = 1;  // 初始的母兔数量
    int rabbits[100] = {0};  // 数组存储每年母兔数量
    rabbits[0] = 1;  // 第1年有1只兔子

    // 从第2年开始计算兔子数量
    for (int i = 1; i < year; i++) {
        if (i >= 2) {
            // 从第3年开始,每年新增的兔子为3年前出生的兔子数
            rabbits[i] = rabbits[i - 1] + rabbits[i - 2];
        } else {
            // 第1到第2年,兔子数量保持不变
            rabbits[i] = rabbits[i - 1];
        }
    }

    // 输出第year年拥有的兔子总数
    printf("第%d年你拥有%d只兔子\n", year, rabbits[year - 1]);

    return 0;
}

4.编写一个程序。输入两个n行m列的矩阵A和B,输出他们的和A+B(小孩哥)

思路提示:定义两个二维数组 int a[10][10] , b[10][10];输入行数列数;然后对a数组元素和b数组元素对应求和【可以赋值给c数组】。最后输出求和后的结果

 代码解答:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
	int a[10][10]={0};
	int b[10][10]={0};
	int c[10][10]={0};
	int m,n;//列数和行数
	int i,j;
	printf("请输入矩阵的行数和列数\n");
	scanf("%d %d",&m,&n);
	printf("请输入a行列式内的值\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			scanf("%d",&a[i][j]);
		}
	}
	printf("请输入b行列式内的值\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			scanf("%d",&b[i][j]);
		}
	}
	printf("a行列式为:\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			printf("%4d",a[i][j]);
		}
		printf("\n");
	}
	printf("b行列式为:\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			printf("%4d",b[i][j]);
		}
		printf("\n");
	}
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			c[i][j]=a[i][j]+b[i][j];
		}
	}
	printf("a和b的行列式和为:\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			printf("%4d",c[i][j]);
		}
		printf("\n");
	}
	
	return 0;
}

结果展示:

 

5.编写一个程序。一个长度为10的数组中重复数据,现要求相同数据只保留一份,其他的用0来代替,被替换的数据移到数组末尾。(数组内容自定) (富士安全,云尖软件开发)

int a[]={3, 2, 10, 1, 23, 15, 82,1,2,78};

提示思路:

第一步:重复数组用0代替

for(i=0; i<10; i++){

for(j=i+1; j<10; j++){

if(a[i]==a[j]){

a[j] = 0;

}

}

}

第二步:从大到小排序 输出

代码解答:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
	int a[]={3,2,10,1,23,15,82,1,2,78};
	int i,j;
	int len = sizeof(a)/sizeof(int);
	for(i=0;i<len;i++){
		for(j=i+1;j<len;j++){
			if(a[i] == a[j]){
				a[j]=0;
			}
		}
	}
	for(i=0;i<len-1;i++){
		int temp=0;
		for(j=0;j<len-i-1;j++){
			if(a[j]<a[j+1]){
				temp = a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			}
		}
	}	
	for(i=0;i<len;i++){
		printf("%4d",a[i]);
	}
	return 0;
}

成果展示:

6.【选做题】编写一个程序。给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值的那两个整数,并输出它们的数组下标。输入: nums = [3,2,4],target = 6 输出:[1,2]。(郎宁电力)

代码解答:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[]) {
    int n;  // 数组的大小
    printf("请输入数组的长度: ");
    scanf("%d", &n);  // 输入数组长度

    int nums[n];  // 动态定义数组大小
    printf("请输入整数数组 nums[%d]:\n", n);

    int i, j;
    // 输入数组元素
    for (i = 0; i < n; i++) {
        scanf("%d", &nums[i]);
    }

    int target;
    // 输入目标值
    printf("请输入目标值:\n");
    scanf("%d", &target);

    // 查找和为目标值的两个数的下标
    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            // 如果找到两个数的和等于 target,打印它们的下标
            if (nums[i] + nums[j] == target) {
                printf("找到的下标为: [%d, %d]\n", i, j);
                return 0;  // 找到后直接结束程序
            }
        }
    }



    return 0;
}

结果展示:

 

三、总结

1.学习内容概述:

二维数组和一维数组是本次学习的重点。

通过学习,掌握了数组的声明、初始化、内存分配及基本的遍历操作方法。理解了数组在C语言中的内存结构和常见的应用场景。

二维数组学习的重点在于如何声明、初始化和访问其元素,特别是在多维数组中如何理解和操作其不同维度的索引。

常用函数:

比如`memset`、`bzero`等函数在处理数组初始化时的用法。

 2. 学习难点:

二维数组的内存结构

二维数组的内存是连续分配的,学习时需要注意二维数组和一维数组的转换方式,以及不同情况下如何正确地索引到指定元素。

数组长度的动态化

学习中提到的变量长度数组(VLA),比如`int n=10; int arr[n];`,这种数组长度是动态指定的,较为难理解。特别是在某些编译器中会存在不同的支持问题。

内存操作函数的使用

函数如`memset`和`bzero`在初始化数组时比较常见,但它们的参数和用法需要特别留意,否则容易造成未预期的行为。

 3. 注意事项

数组的边界问题

在遍历数组时,特别要注意数组的边界,不要越界访问。这不仅会导致程序的逻辑错误,还可能会产生运行时的崩溃或不稳定性。

二维数组的行列索引顺序

在访问二维数组元素时,要分清楚`arr[i][j]`中`i`代表行,`j`代表列。访问时顺序不同可能导致结果与预期不符。

数组初始化问题

声明数组后,如果没有立即初始化,数组中的值是未定义的。初始化数组时,可以使用`{0}`等方式初始化为0或使用`memset`等函数进行内存清零。

4. 未来学习的重点

动态内存分配和释放

目前的学习主要集中在静态数组上,接下来可以学习使用`malloc`、`calloc`等动态分配内存的方式,处理动态数组的创建与释放问题。

数组与函数结合使用

理解如何将数组作为参数传递给函数,以及在函数中如何操作数组,将是未来学习的重点之一。

更复杂的数据结构

在掌握数组的基础上,未来可以扩展到更复杂的数据结构,如链表、队列、栈等,以便处理更复杂的数据操作。

算法与数组的结合

在学习基本数组操作后,可以继续学习数组排序、查找等算法的实现,如快速排序、二分查找等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值