C语言学习笔记5—— 数组

0.越不越界是对写程序的人说的,因为内存堆栈静态区各种段每种都是一块内存区域,本块内存内部无差异,只要程序员保证在本区域内每个变量有各自领地,不会写越界相互篡改,甚至跨区篡改即可。读写越界只是读写到不是预先分配的地方内存区域了,那就出现意想不到的错误

1.数组名是表示地址的常量,也是数组的起始位置

2.数组赋初值时元素数量小于元素总数时部分初始化,如int a[3] ={1};只给首元素赋值,其他元素都是0;

3.数组不初始化元素值随机,部分初始化时未被初始化的变为0而非随机值

4.数组越界:由于对数组元素操作时实际是数组地址常量+下标的,所以对三个元素数组进行a[3]操作时,真的有a[3]这个地址,语法不报错,只是和程序员期望不符

5.数组实现冒泡排序:每次排序都是将剩余的数中最大或者最小值沉到后面或者浮到后面

冒泡排序相邻两个逐个比较大小,按照小到大或者大到小的要求依次得到最大或者最小的排于最后,次大或者次小的排在倒数第二个,依次类推。

由于每次排序确定一个次大或者次小值,N个数的话,排第N-1次时得到了最大或者最小的N-1个值,那最小或最大的值也就确定了,所以一共需要排N-1次。两层循环,外层控制循环次i∈[0, N-1),内层由于是a[j]、a[j+1]相比,故内层循环控制是j∈[0, N-1-i)。

6.选择排序:相邻比较,记录较大或较小值的位置,但是不交换,直到全部比较完,才将最后记录的值放到指定顺序大小的位置。同样外层循环i∈[0,N-1)次,内层j∈[i+1, N-1)。每次内循环开始记录第i个位置做初始位置,结束判断是否需要交换位置

7.冒泡和选择的区别在于是否相邻比较完满足大小要求的话是否交换

8.删除法求质数:

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

int main()
{
        //1000以内的素数,巧妙用下标代表自然数,0~1000共1001个数,故下标1001
        //定义时用了部分初始化只赋值第一个元素,其他自动为0,方便高效
        //元素的值只用于表示对应下标也就是自然是是否为素数,0位素数,非素数置为-1
        int num[1001] = {0};
        int i=0, j=0;

        for(i=2;i<1001;i++)
        {
                if(-1 != num[i])
                {
                        #if 0 //方法1
                        for(j = i+1; j<1001;++j)
                        {
                                if(-1 != num[j])
                                        if( 0 == j%i)
                                                num[j] = -1;
                                        
                        }
                        #else //方法2.
                       //方法2比1好,1还用取模判断是否素数,2直接认定素数的整数倍都是非素数
                        for(j = i*2; j < 1001; j += i)
                                if(0 == num[j])
                                        num[j] = -1;
                        #endif
                }
        }

        for(i = 2; i < 1001; ++i)
        {
                if(num[i] != -1)
                        printf("%d ", i);
        }
        printf("\n");
        exit(0);
}

9.求二位数组每行每列的和,非常妙的一点是多定义一行和一列数组,每行最后和每列最后一个元素用于保存求和的结果。最后一个元素可以放原数组所有元素之和。如求a[3][4]各行各列的和,定义a[4][5]。

10.二维数组求矩阵相乘,用到了三层循环以相乘的结果数组行列号作为第一层第二层,最内层循环作为得到res[i][j]两矩阵相乘的变量控制。

11.二维数组其实就是一个一维的元素为一维数组的数组,所有的元素都以行为单位在内存里线性顺序排列。如int a[2][3]就是2个一维数组a[0]和a[1],a[0]是第一个一维数组的数组名,a[0]数组有三个元素(a[0])[0],(a[0])[1],(a[0])[2],a[1]数组同理。a是二维数组名,它直接对两个一维数组a[0]、a[1]负责,a+1是从&a[0]到&a[1],跳过了一个一维数组a[0]的大小;而不是跳过一个int的大小从a[0][0]到a[0][1]的。

12.字符数组初始化:(部分初始化时,其他自动补空字符)

1)单个字符初始化,不用考虑尾零的问题,可以字符数等于元素数

char str[3] = {'h', 'e', 'y'};

2)字符串初始化,最后加个尾零'\0',元素数要大于字符数

char str[4] = "hey"; 

3)gets():man得到的解释是将一个标准输入获取的字符串放入一个buffer中,遇到换行符或者EOF后将其自动替换为空字符,然后赋给str

获取标准输入时要慎用,它不检查溢出情况。有可能get的数据量加上空字符大于str空间,就有可能把内存中str后面的东西给踩了,导致段错误

char str[3];
gets();
puts();

12.strlen()获得字符串第一个尾零之前字符的个数,空字符之后的不统计。sizeof()运算符获取整个字符串在内存中的大小

13.strcpy和strncpy

strcpy拷贝时是将srcbuffer中的第一个尾零前字符串加上该尾零一起拷贝到destbuffer中。

strncpy中的字节数n一般是dest的大小,因为src已经成型了不会存在问题,唯一存在风险的是dest的空间是否够,因此n为dset大小

14.strcat和strncat

strcat是从将src字符串中第一个尾零之前的子串,从dest字符串第一个尾零处往后覆盖,并在结束后添加尾零

*15.涉及到这种“”字符串操作的,都要考虑到尾零,且是第一个尾零。但实际上内存里还保存了第一个尾零之后的、不会被打印出来的数据

16.strcmp可以用来计算字符ASCII之间的差值

17.n维数组是对n-1维数组的封装,即n维数组是一个一维的n-1维数组。三维数组是对二维数组的封装,是一个一维的二维数组。int a[2][3][4]可理解为a[2]([3][4]),a是有2个元素的一维数组,每个元素是一个二维数组,每个二维数组有三个一维数组,每个一维数组有4个int元素。所以a每增加1是跳过了一个二维数组。

int a[2][3][4][5]  a有2个三维数组a[3][4][5] ,每个三维数组有3个二维数组a[4][5] ,每个二维数组有4个一维数组a[5],每个一维数组有5个int值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值