第三周课程学习总结【关于数组、指针、函数的部分内容】

前言

本周主要学习了数组和指针,还学习了函数的部分内容,下面是对本周内容的总结,大多以程序为例。

数组

数组的概念

  • 由相同类型的多个元素所组成的一种复合数据类型
  • 在工程中同时定义多个相同类型的变量时,重复定义,可以使用数组
#include <stdio.h>

int main()
{
    // 申请4块连续的空间取名ch存放"ABC\0"
    // 把这4块空间称为数组
    char ch[4] = "ABC";
    printf("c[0]=%c\n",ch[0]);// 将ch第0块空间的内容输出
    printf("c[1]=%c\n",ch[1]);// 将ch第1块空间的内容输出
    printf("c[2]=%c\n",ch[2]);// 将ch第1块空间的内容输出

    // 将数组ch的第二块内存的数据给c
    char c = ch[2];
    printf("%c\n",c);

    char buf[5];

    // %p为输出地址
    printf("buf addr : %p\n",buf);
    printf("buf[0] addr : %p\n",&buf[0]);
    
    buf[0] = 'r';
    buf[1] = 'o';
    buf[2] = 's';
    buf[3] = 'e';
    buf[4] = '\0';
    // %s是输出字符串
    printf("%s\n",buf);

    return 0;
}
  • 数组定义
#include <stdio.h>

int main(int argc, char const *argv[])
{
    // 申请5块连续的空间,将a称为数组
    int a[5];
    // 将这5块空间逐一赋值,注意,数组下标从0开始
    a[0] = 1;
    a[1] = 20;
    a[2] = 30;
    a[3] = 40;
    a[4] = 50;
    //a[5] = 60; // 越界,无法使用
    printf("%d\n",a[4]);

    // 循环给数组a赋值
    for(int data = 10,i = 0; i < 5; i++,data+=10)
    {
        a[i] = data;
    }

    // 遍历输出
    for(int i = 0; i < 5; i++)
    {
        printf("%d\n",a[i]);
    }
    return 0;
}

  • 初始化:在定义的时候赋值,称为初始化
// 正常初始化
int a[5] = {100,200,300,400,500};

int a[5] = {100,200,300,400,500,600}; // 错误,越界了
int a[ ] = {100,200,300}; // OK,自动根据初始化列表分配数组元素个数
int a[5] = {100,200,300}; // OK,只初始化数组元素的一部分
// 不能在使用变长数组的情况下初始化数组
int a[size] = {1,2,3};//编译出错
// 变长数组只能先定义再使用
int a[size]; // 正确的
a[0] = 10;
#include <stdio.h>

int main(int argc, char const *argv[])
{
    // 定义数组并初始化
    int Array[5] = {10,25,31,48,60};
    printf("%d\n",Array[2]);

    // 初始化的时候确定数组空间大小
    int Array0[] = {10,20,39};
    printf("%d\n",Array0[2]);
    
    // 初始化一部分空间,剩余的空间默认初始化为0
    int Array1[10] = {68,70};

    // 定义数组并清空数组
    int Array2[10] = {0};

    // 变长数组
    int len = 3;
    // 错误,初始化的时候,数组大小必须为常量
    //int Array3[len] = {100,200,300}; 
    // 哪怕不确定len的大小,但是可以确定Array3的空间最小值为一个
    // int类型的空间,所以至少可以存放一个int类型的数据
    int Array3[len];
    Array3[0] = 100;
    printf("Array3[0] = %d\n",Array3[0]);
    return 0;
}
  • 如果是定义的时候初始化,但是初始化列表个数小于数组的大小,那么无论这个数组是全局变量还是局部变量,没有赋值的成员都是0
int array[3];// 局部变量为随机数,全局变量为0
int array[3] = {0};//清空数组
测量数组的总大小:sizeof(array)
测量数组元素个数:sizeof(array)/sizeof(array[0])

数组元素的引用

int a[5]; // 有效的下标范围是 0 ~ 4
a[0] = 1;
a[1] = 66;
a[2] = 21;
a[3] = 4;
a[4] = 934;

a[5] = 62; // 错误,越界了
a    = 10; // 错误,不可对数组名赋值 

字符数组

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char str1[4] = {'a','b','c','\0'};
    char str2[4] = {"abc"};
    char str3[4] = "abc"; //常用
    str1[1] = 'd';
    printf("%s\n",str1);
    printf("%s\n",str2);
    printf("%s\n",str3);

    return 0;
}

练习:

定义一个char str[6] = {‘h’,‘e’,‘I’,‘l’,‘o’};/把这个数组的内存图画出来,并且把数组的名字的地址,还有每个元素的地址都打印出来,每个元素的地址相差几个字节?

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char str[6] = {'h','e','l','l','o','\0'};

    printf("str addr %p\n",str);
    printf("str[0] addr %p\n",&str[0]);
    printf("str[1] addr %p\n",&str[1]);
    printf("str[2] addr %p\n",&str[2]);
    printf("str[3] addr %p\n",&str[3]);
    printf("str[4] addr %p\n",&str[4]);
    printf("str[5] addr %p\n",&str[5]);

    printf("%c\n",*(str+0));
    printf("%c\n",*(str+1));
    printf("%c\n",*(str+2));
    printf("%c\n",*(str+3));
    printf("%c\n",*(str+4));
    printf("%c\n",*(str+5)); // 0
    return 0;
}

数组偏移量

int Array[6] = {10,20,30,40,50,60};
// 数组地址偏移量
// 000000000061FE04,000000000061FE04
printf("%p,%p",&Array[1],&Array[0]+1);

数组元素地址解引用

int a = 10;
    printf("%d\n",a);

    printf("%p\n",&a);
    // * 表示将地址里面的内容取出,我们把它称为解引用
    printf("%d\n",*(&a));

    //--------------------------
    char Array[5] = {'j','a','c','k'};
    printf("%c\n",Array[0]);
    printf("%c,%c\n",*(Array+0),*(&Array[0]));
    printf("%c,%c\n",*(Array+1),*(&Array[1]));
    printf("%c,%c\n",*(Array+2),*(&Array[2]));
    printf("%c,%c\n",*(Array+3),*(&Array[3]));
    

练习2:

定义一个整型数组,存储从键盘上获取的多个整型数据(比如输入 10 40 23 13),输入-1输入完成,并打印出这一排数据的最小值和最大值

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int array[100] = {0};
    int count = 0;
    while (1)
    {
        scanf("%d",&array[count]);
        if(array[count] == -1)
        {
            break;
        }
        count++;
    }
    // 将-1从数组剔除
    // i--是将i所指向的空间压缩一个类型空间
    array[count] = 0;

    // 找最大值和最小值
    // 假设array[0]最大值与最小值
    int max_value = array[0];
    int min_value = array[0];

    // 遍历比较替换
    for(int i = 0; i < count; i++)
    {
        if(max_value < array[i])
        {
            max_value = array[i];
        }
        if(min_value > array[i])
        {
            min_value = array[i];
        }
    }

    printf("max_value : %d\n",max_value);
    printf("min_value : %d\n",min_value);
    return 0;
}

字符串常量

printf("%s\n","hello");
printf("'h' addr:%p\n","hello");
printf("'e' addr:%p\n","hello" + 1); //地址+1

printf("'o' addr:%p value:%c\n","hello" + 4,*("hello" + 4)); //地址+1
printf("%d\n", sizeof("abcd")); // 此处 "abcd" 代表整个数组
printf("%p\n", &"abcd");        // 此处 "abcd" 代表整个数组

printf("%c\n", "abcd"[1]); // 此处 "abcd" 代表匿名数组的首元素地址

匿名数组

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

int main(int argc, char const *argv[])
{
    char array[5] = "jack";
    char array1[5] = "rose";
    printf("%c\n",array[1]);
    // "jack"是匿名数组
    printf("%c\n","jack"[1]);
    printf("array addr : %p",array);
    printf("array1 addr : %p\n",array1);
    printf("jack addr : %p\n","jack");
    printf("array msg : %s\n",array);
    printf("jacl msg : %s\n","jack");

    printf("%c\n","rose"[0]);
    printf("%c,%c\n",*("rose"+1),"rose"[1]);
    printf("%ld\n",sizeof("rose"));
    printf("%d\n",strlen("rose"));

    char Array[10] = {0};
    // 计算实际空间的大小
    printf("%ld\n",sizeof(Array));
    // 计算数组里面的内容大小遇到'\0'结束
    // 计算时间的数组内容大小
    printf("%d\n",strlen(Array));
    
    return 0;
}

多维数组(二维数组)

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //只有一个【】的数组称为一维数组
    char name[5]= "jack";
    char name1[5] = "rose";
    char name2[5] = "ken";
    //有两个【】的数组称为二维数组
    //二维数组初始化
    //第一个【3】表示字符串的个数,表示这个数组能存放3个字符串
    //第二个【5】表示每个字符串最大的长度位5字节
    char Name[3][5] = {"jack","rose","ken"};

    //定义二维数组
    char buf[2][3];

    return 0;
}

二维数组解引用

// 二维数组初始化字符串
char buf1[2][5] = {"jack","rose"};
printf("%s,%s\n",&buf1[0][0],buf[0]);
printf("%s,%s\n",&buf1[1][0],buf[1]);

// 取二维数组中的某个字符
printf("%c,%c,%c,%c\n",buf1[0][1],*(&buf1[0][1]),*(buf1[0]+1),*(*(buf1+0)+1));
printf("%c,%c,%c,%c\n",buf1[1][2],*(&buf1[1][2]),*(buf1[1]+2),*(*(buf1+1)+2));

数组地址偏移

#include <stdio.h>

int main()
{
    char Names[3][5] = {"jack","rose","ken"};
    // printf("Names[0] %p,%p\n",Names[0],&Names[0][0]);
    // printf("Names[1] %p,%p\n",Names[1],&Names[1][0]);
    // printf("Names[2] %p,%p\n",Names[2],&Names[2][0]);
    
    // Names[0]相当于&Names[0][0]
    printf("Names[0]+1=%p,%p\n",Names[0]+1,&Names[0][1]);
    printf("Names[0][0]:%c,%c\n",Names[0][0],*(Names[0]+0));
    printf("Names[0][2]:%c,%c\n",Names[0][2],*(Names[0]+2));

    printf("&Names[0]+1=%p,%p\n",&Names[0]+1,&Names[1]);
    printf("*(&Names[0]+1)=%c,%c\n",*(&Names[0]+1)[0],*(&Names[1])[0]);
    printf("*(&Names[0]+1)=%c,%c,%c,%c\n",(*(&Names[0]+1))[1],(*(&Names[1]))[1], 
                                          *(*(&Names[0]+1)+1),*(*(Names+1)+1));
    
    printf("%c,%c,%c,%c\n",Names[2][2],*(Names[2]+2),(*(Names+2))[2],*((*(Names+2)+2)));

    return 0;
}

数组万能拆解法

int   a[4];       // 第2部分:a[4]; 第1部分:int
int   b[3][4];    // 第2部分:b[3]; 第1部分:int [4]
int   c[2][3][4]; // 第2部分:c[2]; 第1部分:int [3][4]
int  *d[6];       // 第2部分:d[6]; 第1部分:int *
int (*e[7])(int, float); // 第2部分:e[7]; 第1部分:int (*)(int, float)

指针

取址符

  • 每个变量都是一块内存,都可以通过取址符 & 获取其地址
#include <stdio.h>

int main(int argc, char const *argv[])
{
    int a = 10;
    printf("0x%p\n",&a);
    
    int buf[5] = {1,2,3,4,5};
    printf("0x%p\n",&buf); //&buf+1
    printf("0x%p\n",buf);  //buf+1,加1后不一样

    return 0;
}

指针基础

  • 指针:就是用于存放地址的变量
#include <stdio.h>

int main(int argc, char const *argv[])
{
    int a = 10;
    // 定义指针p指向a
    int *p = &a;
    printf("%p,%p\n",&a,p);

    //通过p将a的内容输出
    int data = *p;//*p是解引用
    //解引用的意思是获取p所指向的空间里面的内容
    printf("%d\n",data);
    
	char buf[] = "jack";
    char *ptr = buf;// &buf[0];
    printf("%s\n",buf);
    printf("%s\n",ptr);
    
    return 0;
}

指针尺寸

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int *int_porint;
    char *char_porint;
    printf("%ld,%ld\n",sizeof(int_porint),sizeof(char_porint));
    
    return 0;
}

野指针与空指针

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int *int_porint = NULL; //野指针,不能操作,NULL的类型是void*(0)
    
    char *char_porint = NULL;//如果定义的指针暂时不用应该指向NULL地址
    //printf("%d\n",*int_porint);//使用野指针会出现段错误,内存泄漏
    printf("%ld,%ld\n",sizeof(int_porint),sizeof(char_porint));
    
    return 0;
}

数组指针(二维数组指针)

#include<stdio.h>

int main(int argc, char const *argv[])
{
    int array[3][5] = {
                        {10,20,30,40,50},
                        {11,22,33,44,55},
                        {110,120,130,140,150}
                       };
    int (*p)[5]= array;
    printf("%d\n",p[1][2]);
    printf("%d\n",(*(p+1))[2]);
    printf("%d\n",*((*(p+1))+2));
    return 0;
}

指针数组

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //定义指针数组,数组存放的数据是地址
    int *buf[5];

    int a = 10;
    int a1 = 20;
    int a2 = 30;

    buf[0] = &a;
    buf[1] = &a1;
    buf[2] = &a2;

    printf("%d\n",*(buf[1]));
    return 0;
}

char型指针

定义:

char * = "abcd";// 不妥
const char *p = "abcd";//不能通过p修改字符串数据
char buf[10] = "jack";// 将jack内容放到buf这块空间
char *p = buf;// p存放buf的地址
char *p1 = "jack";//p1存放“jack”的地址,jack为常量

void//不确定类型

//void a = 10;
//auto是根据赋值的值,自动识别数据类型
auto a = 10;
printf("%ld\n",sizeof(a));
auto a1;// 不能确定a1的类型
printf("%ld\n",sizeof(a1));

练习:字符串逆序输出

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

int main(int argc, char const *argv[])
{
    char buf[] = "abcdef";
    //scanf("%s",ch);
    int len = strlen(buf);
    char temp[len];
    
    for(int i = 0,j = len -1;i<len;i++,j--)
    {
        temp[i] = buf[j];
    }
    printf("%s\n",temp);

    return 0;
}

const型指针

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //修饰p指针指向区域为字符串常量
    //不能通过p修改字符串里面的内容
    const char *p = "jack";
    //*p = 'r';
    char const *p1 = "jack";

    p1 = p;//正确
    printf("%s\n",p);

    char *const q = "jack";
    //*q = 'r';//不会报错
    //const修饰的是q本身,所以q不能指向其他地址
    //q = "rose"

    return 0;
}

函数

返回类型 函数名称(参数1,参数2,.......)
{
    函数体
    return 返回值;
}
#include <stdio.h>
/*
*swap:交换两个数值
*/
//形参的作用是接收实参数据
//实参是真实的数据,形参是一块空间,里面没有有效的数据
void swap(int *a,int *b)// 形参
{
    int temp = *a;
    *a = *b;
    *b = temp;
    printf("%d,%d\n",*a,*b);
}

int main(int argc, char const *argv[])
{
    int a = 10,b = 20;
    swap(&a,&b); // 实参
    printf("after(%d,%d)\n",a,b);
    return 0;
}
//字符串去空格
#include 
int main(int argc, char const *argv[]) 
{    
	char buf[100] = {0};    
	int len = 0;    // scanf遇到空格结束,不会拿空格 
   	while((buf[len++] = getchar()) != '\n');    
   	for(int i = 0; i < len; i++)   
   	{                             // 找空格 
       if(buf[i] == ' ')       
       {	
       		for(int j = i; j < len; j++)           
       		{	
       			buf[j] = buf[j+1];           	
       		}      
       	}   
    }    
    printf("%s",buf);    
    return 0; 
}

函数模块化处理

1.一个工程应该是有多个c文件以及头文件组成

2.c文件用于存放自己封装的函数接口或者动静态库

3.头文件用于存放函数的而声明以及各种结构体、宏、枚举的定义

冒泡函数的封装流程

1.创建工程文件目录用于存放项目

2.再在此工程目录下创建bubble.c main.c bubble.h

​ 1.bubble.c是存放冒泡算法

​ 2.main.c值函数实现

​ 3.bubble.h是冒泡算法的函数声明

3.在此工程创建bubble.c 添加以下内容

#include <stdbool.h>
#include <stdio.h>

bool bubble(int *array, int lenght)
{
    if(array == NULL || lenght <= 0)
   {
        return false;
   }
    for(int i = 0; i < lenght-1; i++)
   {
        for(int j = 0; j < lenght-i-1; j++)
       {
            if(array[j] > array[j+1])
           {
                int temp = array[j];
                array[j] = array[j+1];
                array[j+1] = temp;
           }
       }
   }
    return true;
}

4.创建main.c添加以下内容

#include <stdio.h>
#include <stdbool.h>
#include "bubble.h"

int main(int argc, char const *argv[])
{
    int array[] = {5,4,3,2,1};
    int len = sizeof(array) / sizeof(array[0]);
    bubble(array, len);
    for(int i = 0; i < len; i++)
        printf("%d\t",array[i]);
    printf("\n");
    return 0;
}

  1. 创建bubble.h添加以下的内容
bool bubble(int *array, int lenght);

  1. 编译成程序
编译程序不能使用快捷键,需要命令编译

gcc main.c bubble.c -o main.exe

执行程序

./main.exe

以上就是我对本周学习内容的总结,本周所学的知识对我来说还需要更多时间消化理解,对于指针部分的内容掌握还不是很牢固,需要多加练习才行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值