0
点赞
收藏
分享

微信扫一扫

python核心语法

boom莎卡拉卡 2024-11-21 阅读 11

https://www.bilibili.com/video/BV1cx4y1d7Ut?spm_id_from=333.788.videopod.episodes&vd_source=e8984989cddeb3ef7b7e9fd89098dbe8&p=107
本篇为贺宏宏老师C语言教程指针部分笔记整理

//.c文件

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>

//8-1 什么是指针
//指针:就是地址!
//指针:就是地址!
//指针:就是地址!

int main()
{
    int a = 10; //4个字节    
    int b = 20;

    &a; //获取a的地址
    &b; //获取b的地址

    //printf("a的地址=%p,b的地址=%p\n",&a,&b);//%p:输出地址(指针),以16进制进行输出
    printf("a的地址=%d,b的地址=%d\n",&a,&b);

    return 0;
}

// 8-2 指针变量

int main()
{
    int a = 10;
    int b = 20;
    int *p = &a; //一个int地址(指针)赋值给一个int指针变量
    //获取a的地址,int &p = &a;(int &p C++引用) int *p = &a;
    p = &b; //把b的地址赋值给p //此处不能用*p了,*p的含义是引用,一词多义
    char c;
    double d;
    char *p1 = &c;
    double *p2 = &d;//指针的类型要根据变量的类型进行匹配
    return 0;
}

// 8-3 使用指针变量

int main()
{
    int a = 10;

    printf("%d,%d\n",a,&a);//a的值,a的地址
    int *p = &a;
    printf("%d,%d,%d\n",*p,p,&p);//p指向的变量a的值,a的地址,p的地址

    return 0;
}

// 8-4 &的多个作用
// &的作用:1.按位与 例如4&3 2.取地址 例如 &a 3.C++的引用
//&变量名:获取该变量的地址(指针),&:取地址符(号);这里的&是个单目运算符
//4&3:按位与,这里的&是个双目运算符,有两个变量

int main()
{
    int a = 10;
    int b = 20;
    int c = 4 & 3;//按位与 100 & 011 = 000

    printf("%d\n",c);
    printf("%p,%p,%p\n",&a,&b,&c);
    printf("%p,%p,%p\n",&a&b);//按位与

    int& d = a;//C++的引用,相当于a有一个别名叫d了;与其他两种用法的不同在于这个&前面有数据类型

    return 0;
}

//8-5 指针应用(指针最重要的部分) Swap交换数据(两个错误示例)

//交换两个变量的值(写成函数)

void Swap_err1(int a, int b)//没有交换成功,错误
{
    int tmp = a;
    a =  b;
    b = tmp;
    printf("%d %d",&a,&b);
}

void Swap_err2(int *p1, int *p2)//没有解引用,交换失败
{
    int *tmp = p1;
    p1 = p2;
    p2 = tmp;
}

在这里插入图片描述

//8-6 指针应用 Swap交换数据2
//总结:一个函数A通过调用函数B,来修改A中变量的值:
//: 1.必须传指针; 2.B中必须解引用

void Swap(int *p1,int *p2)
{
    int tmp;
    tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d %d",&a,&b);
    printf("交换前=%d,%d\n",a,b);

    Swap(&a,&b);//交换a,b两个值

    printf("交换后=%d,%d\n",a,b);
    return 0;
}

在这里插入图片描述

// 8-7 通过指针返回多个值
//C语言怎么返回两个值?

double Fun(int a, int b, int c)
{
    int d = b * b - 4 * a * c;
    double x1, x2;
    x1 = (-b + sqrt(d))/(2 * a);
    x2 = (-b - sqrt(d))/(2 * a);

    return x1; // C语言一般只能返回0个或1个值
}


double Fun(int a, int b, int c, double *x1,double *x2)
{
    int d = b * b - 4 * a * c;
    double x1, x2;
    *x1 = (-b + sqrt(d))/(2 * a);
    *x2 = (-b - sqrt(d))/(2 * a);

    return 2; //2个根
}

int main()
{
    double x1;
    double x2;
    Fun(4,5,1,&x1,&x2);
    printf("%lf,%lf\n",x1,x2);

}

//8-9 指针指向数组元素
//问题1:指针如何指向这个数组的元素

//问题2:arr名字
//一维数组arr的名字arr表示整个数组只在如下情况:
//1.在定义数组的同一个函数中求sizeof.例如int arr[10]; sizeof(arr) -> 40,因为int是4个字节
//2.在定义数组的同一个函数中&arr+1表示&arr的地址加一整个数组的大小,例如int arr[10],&arr,&arr+1 = &arr+40
//其他情况,arr都表示数组的起始地址

int main()
{
    int arr[10] = {1,3,5,7,9,11,13,15,17,19}; 
    
    //int* p = &arr[0];//第一个元素int的地址
    int *p = arr;//和上一行等价

    printf("%d,\n%d\n",*p,arr[0]);
    printf("%d,\n%d,\n%d\n",&arr,sizeof(arr),&arr+1);

    return 0;
}

//8-10 指针的加法运算
//指针的算数运算:前提是这个指针指向一个数组,同时程序应该保证不越界
//p+整数,p++,++p合法

int main()
{
    int arr[10] = {1,3,5,7,9,11,13,15,17,19};
    
    //int* p = &arr[0];//第一个元素int的地址
    int *p = arr;//和上一行等价
    printf("%d ",*p);

    //通过指针输出(访问)数组的所有元素
    for(int i = 0; i < 10; i++, p++)
    {
        printf("%d ",*p);
    }
    return 0;
}

//8-11指针的减法运算
//指针的算数运算:前提是这个指针指向一个数组,同时程序应该保证不越界
//p+整数,p++,++p合法

int main()
{
    int arr[10] = {1,3,5,7,9,11,13,15,17,19};
    
    //int* p = &arr[0];//第一个元素int的地址
    int *p = &arr[9];//和上一行等价
    int num = sizeof(arr);
    printf("%d\n",num); // sizeof(arr)可是40哦,不是10哦,因为int表示4个字节哦。
    for(int i = 0; i < 10; i++)//所以这里不能写成i < sizeof(arr),这样就循环40次了。超过10就越界,要出错了
    {
        printf("%d ",*p--);
    }
}

//8-12通过指针引用数组元素

int main()
{
    int a[10];
    int i;
    int *p = a;
    printf("please enter 10 integer numbers:");
    for(i = 0; i < 10; i++)
        scanf("%d", &a[i]);
    for(i = 0; i < 10; i++)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}

//8-13 指针的关系运算
//<,> >= , <=, !=,前提是必须指向同一个数组,绝对不可以操作不同的数组

// 错误用法:在不同的数组了,返回值为0

int main()
{
    int a = 10;
    int b = 20;
    int *p = &a;
    printf("%d\n",*(p+1));//错误的应用
    int *q = &b;
}

//从头到尾输出数组

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    
        for(int *p = arr;p!= &arr[10];p++)//标准规定可以使用尾后(尾巴的后面:此处是指数组最后一位的下一处地址)地址(指针)
            printf("%d ",*p); //输出1 2 3...
    //或者
    /*
        for(int *p = arr; p != &arr[10]; p++)
            printf("%d ",*p);    
    */

    //或者
    /*
        for(int *p = arr; p <= &arr[9]; p++)
            printf("%d ",*p);    
    */
      return 0;
}

//8-15 指针在数组中的错误应用
//常见的错误:越界错误

int main()
{
    int a[10];
    int i;
    int *p;
    p= a;
    printf("please enter 10 integer numbers:");
    
    for(i = 0; i < 10; i++)
        scanf("%d", p++); //这里p的指针已经到数组的最后了(p已经到达a的尾后指针),改进办法:p = a;(把p重新赋值),下一行
    
    p = a;
    
    for(i = 0; i < 10; i++,p++)//这里p指针再往后就不是数组内的数了,就是空的地方了,输出的数为随机的数值
        printf("%d ",*p);
    printf("\n");
    return 0;
}

8-16
//8-16 数组作为参数传递:数组名仅仅表示数组首元素的地址
//传数组名+数组长度

//示例1.输出数组的所有元素
//p:数组的起始地址,n:元素的个数

void Show (int *p, int n)
{
    for(int i = 0; i < n; i++)
    {
        printf("%d ",p[i]);
    }
}

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    Show(arr,sizeof(arr)/sizeof(arr[0]));//数组元素个数=数组长度/数组每一个元素的长度(这里用第一个元素的长度指代了)
    return 0;
}

//示例2.将数组a中n个整数按相反顺序存放

void inv(int *x, int n) //x数组的起始地址,n元素个数
{
    int tmp;
    //把x当作数组名来操作:(更推荐使用这种方法)
    
    // for(int i = 0, j = n-1; i < j; i++, j--)//i往后走,j往前走
    // {
    //     tmp = x[i];
    //     x[i] = x[j];
    //     x[j] = tmp;
    // }
    

    //把x当作指针来操作:
    for(int i = 0, j = n-1; i < j; i++, j--)
    {
        tmp = *(x+i);
        *(x+i) = *(x+j);
        *(x+j) = tmp;
    }    

}

void Show (int *p, int n)
{
    for(int i = 0; i < n; i++)
    {
        printf("%d ",p[i]);
    }
}

int main()
{
    int arr[] = {1,3,5,7,9,11,13,15,17,19};
    inv(arr,sizeof(arr)/sizeof(arr[0]));
    Show(arr,sizeof(arr)/sizeof(arr[0]));
    return 0;
}

把x当作数组名来操作:
在这里插入图片描述
把x当作指针来操作:
在这里插入图片描述

示例3
在这里插入图片描述
5个数字至少需要4次遍历:

第一次:
将第一个数字与剩下的最小值进行比较:
如果第一个数字小于剩下数字的最小值,顺序不变;
如果第一个数字大于剩下数字的最小值,将剩下数字的最小值与第一个数字进行交换。

第二次:
将第二个数字与剩下的最小值进行比较:
如果第二个数字小于剩下数字的最小值,顺序不变;
如果第二个数字大于剩下数字的最小值,将剩下数字的最小值与第二个数字进行交换。

第三次:
将第三个数字与剩下的最小值进行比较:
如果第三个数字小于剩下数字的最小值,顺序不变;
如果第三个数字大于剩下数字的最小值,将剩下数字的最小值与第三个数字进行交换。

第四次:
将第四个数字与剩下的最小值进行比较:
如果第四个数字小于剩下数字的最小值,顺序不变;
如果第四个数字大于剩下数字的最小值,将剩下数字的最小值与第四个数字进行交换。

第五次:
将第五个数字与剩下的最小值进行比较:
如果第五个数字小于剩下数字的最小值,顺序不变;
如果第五个数字大于剩下数字的最小值,将剩下数字的最小值与第五个数字进行交换。

//示例3.用指针方法对10个整数按由大到小顺序排序(选择排序法)

//选择法排序:每次从待排序的数中找最小值和待排序的第一个值进行交换,直到全部有序
//arr:数组起始地址,n:元素个数

//下标法。优先推荐使用下标法,指针法容易出错

void SelectSort1(int* arr, int n)
{
    int k;
    int tmp;
    for(int i = 0; i < n-1; i++)
    {
        k = i;//这里要提前给k赋值一下
        for(int j = i+1; j < n; j++)
        {
            if(arr[j] < arr[k]) //指针方式:*(arr+j) < *(arr+k)
            {
               k = j; 
            }
        }
        if(arr[k] != arr[i])//这里写k!=i就行了
        {
            tmp = arr[i];//指针方式:*(arr+i)
            arr[i] = arr[k];//指针方式:*(arr+i) = *(arr+k)
            arr[k] = tmp;//指针方式:*(arr+k) 
        }
    }
}

//指针方式:

void SelectSort(int* arr, int n)
{
    int k;
    int tmp;
    for(int i = 0; i < n-1; i++)
    {
        k = i;//这里要提前给k赋值一下
        for(int j = i+1; j < n; j++)
        {
            if(*(arr+j) < *(arr+k))
            {
               k = j; 
            }
        }
        if(k != i)
        {
            tmp = *(arr+i);
            *(arr+i) = *(arr+k);
            *(arr+k)  = tmp;
        }
    }
}

void Show (int *p, int n)
{
    for(int i = 0; i < n; i++)
    {
        printf("%d ",p[i]);
    }
}

int main()
{
    int arr[] = {10,3,65,7,69,181,193,15,157,19};
    Show(arr,sizeof(arr)/sizeof(arr[0]));
    printf("\n");
    SelectSort(arr,sizeof(arr)/sizeof(arr[0]));
    Show(arr,sizeof(arr)/sizeof(arr[0]));
    return 0;
}
举报

相关推荐

0 条评论