欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > C语言第八章,链表

C语言第八章,链表

2024/10/27 13:24:29 来源:https://blog.csdn.net/qq_63279386/article/details/143167836  浏览:    关键词:C语言第八章,链表

#define _CRT_SECURE_NO_WARNINGS//所有代码之前都要写一个这个
第八章 指针

概念

指针:就是地址
&变量名:获取该变量的地址(指针),&称为取地址符,%p:输出地址(指针),以十六进制输出
指针变量:保存指针(地址)的变量,(int 型指针变量)
int *p=&a;//一个int型的地址赋值给int指针变量,定义
p=&b,跟上面一个意思,使用

/*char c;
* char *p1=&c;
* double d;
* double *p2=&d;指针类型必须匹配
*      *p的含义访问p所指向的变量,解引用,间接访问符
* 输出p和&p含义不同,前者输出指向变量的地址,后者输出p自己的地址
而*p输出的是所指变量的内容
p里的内容是a的地址,p指向的内容是a的内容
*/

用指针加函数交换两个数的值


#include<stdio.h>
void Swap(int* p1, int* p2) {
    int temp;
    temp = *p1;//交换的是数不是地址,*p才是指向数
    *p1 = *p2;
    *p2 = temp;
}
int main() {
    
    /*int a, b;
    scanf("%d%d", &a, &b);
    Swap(&a, &b);
    printf("%d %d", a, b);
    return 0;*/
    int a, b;
    int* p1=&a, * p2=&b;//把地址给人家,这步很重要,先加上人家微信啊
    scanf("%d%d", p1, p2);
    Swap(p1, p2);//传的是a,b的地址
    printf("%d %d\n", a, b);
    printf("%d %d", *p1, *p2);//两种输出方式都对
    return 0;    
}

c语言只能返回0个或1个值
用指针解决多个返回值


指针求方程的根


#include<stdio.h>
#include<math.h>
int Fun(int a, int b, int c, double* x1, double* x2) {
    int d = b * b - 4 * a * c;
    *x1 = (-b + sqrt(d)) / (2 * a);//*x1才是指数
    *x2 = (-b - sqrt(d)) / (2 * a);
    return 2;//两个根
}
int main() {
    double x1, x2;
    Fun(3, 5, 1, &x1, &x2);//传地址
    printf("%lf %lf", x1, x2);
    return 0;
}

指针指向数组
int *p=&arr[0]   等于  int*p=arr//都是指向第一个元素的地址

用指针输出一个数组


#include<stdio.h>
int main() {
    int arr[] = { 1,3,5,7 };
    int n = sizeof(arr) / sizeof(arr[0]);//求数组长度
    //从前往后输出
    //int* p = &arr[0];//指针指向数组的第一个地址
    //for (int i = 0; i < n; i++) {
    //    printf("%d ", *p);//输出指针指向的内容
    //    //printf("%d ",*(p+i));//这么写也行,但我觉得还是地址往后走比较好理解
    //    p++;//地址往后走一位
    //}
    //从后往前输出
    int* p = &arr[n - 1];
    for (int i = 0; i < n; i++) {
        printf("%d ", *p);
        p--;
    }

    return 0;
}

指针的关系运算,前提必须在同一个数组,>,<等,两个单独的变量或两个不同的数组不可以比较大小


从头到尾输出数组


#include<stdio.h>
int main() {
    //int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    //指针输入
    int arr[10];
    int* p = &arr[0];
    //int*p=arr;(同理)
    for (int i = 0; i < 3; i++) {
        scanf("%d", p);
        p++;
    }
    p = &arr[0];//重新回到第一个元素位置
    //p=arr;同理
    for (int i = 0; i < 3; i++) {
        printf("%d ", *p);
        p++;
    }
    //for (int* p = arr; p != &arr[10]; p++) {//就是10,这叫尾后指针
    //    printf("%d ", *p);
    //}
    或者
    //for (int* p = arr; p < &arr[10]; p++) {//就是10,这叫尾后指针
    //    printf("%d ", *p);
    //}
    return 0;
}

数组作为参数传递,数组名仅仅只是表示数组首元素的地址
传数组要加长度


传整个数组到函数中


#include<stdio.h>
void Show(int* p, int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", *p);
        //高级版本
        //printf("%d", p[i]);//这么写有点6
        p++;
    }
}
int main() {
    int arr[] = { 1,2,3,5 };
    int n = sizeof(arr) / sizeof(arr[0]);
    Show(arr,n);
    return 0;
}

将数组中的n个整数按相反顺序存放


数组,函数,指针,他们仨才是真玩,跟别人都是假玩
#include<stdio.h>
void Inv(int* p, int n) {
    int temp;
    for (int i = 0, j = n - 1; i < j; i++, j--) {//一个指前一个指后,错位则停止
        temp = p[i];
        p[i] = p[j];
        p[j] = temp;
        //用指针的方式写
        /*temp = *(p+i);
        *(p+i) = *(p+j);
        *(p+j) = temp;*/
    }
}
void Show(int* p, int n) {//输出交换后的结果
    for (int i = 0; i < n; i++) {
        printf("%d ", *p);
        p++;
    }
}
int main() {
    int arr[] = { 1,2,3,4,5,6 };
    int n = sizeof(arr) / sizeof(arr[0]);
    Inv(arr, n);//传的是首地址和长度
    Show(arr, n);//同上
    return 0;
}

用指针法对十个整数选择法从大到小排序


找到最大的数与最左边交换
#include<stdio.h>
void Pai(int* p, int n) {
    //用数组下标做其实更好,道理都一样,写成数组形式就可以了
    int i, j;
    int index;
    int temp;
    for (i = 0; i < n - 1; i++) {
        index = i;
        for (j = i + 1; j < n; j++) {
            if (*(p + index) < *(p + j)) {//看好了跟谁比,不是ij比,很重要,但我不明白为啥i不行
                index = j;//道理我懂,但我想不通i也是最左边的数啊,也没变过啊
            }
        }
        if (index != i) {//最小的下标变了则交换数
            temp = *(p + i);
            *(p + i) = *(p + index);
            *(p + index) = temp;
        }
    }
}
void Show(int* p, int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", *p);
        p++;
    }
}
int main() {
    int arr[] = { 11,96,48,63,5,4,69,74,56 };
    int n = sizeof(arr) / sizeof(arr[0]);
    Pai(arr, n);
    Show(arr, n);
    return 0;
}

通过指针引用多维数组


#include<stdio.h>
int main() {
    int arr[3][4];
    int(*p)[4] = arr;//3行4列  /*1*/
    int* p2 = arr[0];            /*2*/
    p = arr + 1;//加一类型不改变    /*3*/
    p2 = arr[0] + 1;            /*4*/
    int x = arr[0][0];            /*5*/
    x = arr[0][0] + 1;            /*6*/
    return 0;//13,24,56三种不同的类型
}

调用函数,输出二维数组


#include<stdio.h>
void Show(int(*p)[4]) {//这个类型记好
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }
}
int main() {
    int arr[3][4] = { 1,2,3,4,5 };//后面会自己补0
    Show(arr);
}

通过指针引用字符串
const:不允许修改(其修饰的)内容
const 只能修饰直接右边,eg:const int *p;  p可以变,*p不可以

用函数调用实现字符串的复制


字符串和普通数组的区别:字符串可以通过‘\0’判断结尾,所以字符串不需要传长度
#include<stdio.h>
#include<string.h>
void Mystrcpy(const char* first, char*end) {//const加不加都可以,加了之后不能修改他的值
    int i;                                    //其实就是相当于粘贴而不是剪切
    for (i = 0; first[i] != '\0'; i++) {//字符串结束标志'\0'
        end[i] = first[i];
    }
    end[i] = '\0';//给结尾加个末尾标识符,必须加,要不然会输出后面的未赋值的数
}
int main() {
    char arr[10] = "abcde";
    char brr[10];
    Mystrcpy(arr, brr);
    //strcpy(brr, arr);(直接用人家写好的就行,把后面的赋值给前面的,加个头文件)
    printf("%s", brr);//字符串%s输出就行
    return 0;
}

指向函数的指针


函数名相当于函数地址 Max=&Max
#include<stdio.h>
int Max(int a, int b) {
    return a >= b ? a : b;//公式,求最大值的意思
}
int main() {
    int(*pfun)(int, int);//pfun是指针,函数参数为int,int
    pfun = Max;
    pfun = &Max;//与上一句同含义
    int a, b;
    scanf("%d%d", &a, &b);
    printf("%d", pfun(a, b));
    return 0;
}

指向函数的指针排序,整的挺复杂的,正经复杂


#include<stdio.h>
#include<stdlib.h>
int Cmp_int(const void* vp1, const void* vp2) {//如果是>0,返回前面,<0返回后面
    return *(int*)vp1 - *(int*)vp2;//还原本质
}
int Cmp_double(const void* vp1, const void* vp2) {//必须是int型
    double tmp= *(double*)vp1 - *(double*)vp2;//因为返回int型,所以要分情况讨论
    if (tmp > 0) {
        return 1;
    }
    else if (tmp < 0) {
        return -1;
    }
    else {
        return 0;
    }
}

int main() {
    int str[] = { 2,65,3,8,96 };
    double str2[] = { 34.2,34.3,34.4,65.9 };
    int len = sizeof(str) / sizeof(str[0]);
    int len2 = sizeof(str2) / sizeof(str2[0]);
    qsort(str, len, sizeof(str[0]), Cmp_int);//排序函数四个参数:数组,长度,单个元素长度,比较标准
    qsort(str2, len2, sizeof(str2[0]), Cmp_double);
    for (int i = 0; i < len; i++) {
        printf("%d ", str[i]);
    }
    printf("\n");
    for (int i = 0; i < len2; i++) {
        printf("%lf ", str2[i]);
    }
    
    return 0;
}

#include<stdio.h>
#include<stdlib.h>
int main() {
    动态内存分配:数组里的容量<1024*1024=1M,很小
     void*:没有类型信息的指针,仅仅是记录地址
    使用场景:1.需要大容量内容2.在一个函数创建的内存在别的函数中还需要使用时
    malloc:创建内存,需引用stdlib.h,失败返回NULL,成功返回地址
     /*   *void *p=malloc(1024*1024*10);
    * if (p == NULL) {
        *printf("申请失败了");
    }
    *printf("给一个地址");
    */
    /*calloc:创建内存,参数有长度和大小,会把每个元素初始化为0
    int* arr = (*int)calloc(n, sizeof(int));//100个整型单元
    for (int i; i < n; i++) {
        arr[i] = i;
    }
    */
    /* realloc:修改动态内存大小
    int n = 10;
    int* arr = (int*)malloc(n*sizeof(int));
    arr = (int*)realloc(arr, 2 * n * sizeof(int));
    for (int i = 0; i < 2 * n; i++) {
        arr[i] = i;
    }*/
        free:释放内存,动态内存申请,用完要释放掉,要不然内存泄漏,可用的内存越来越少,v变慢
        return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com