C语言 指针

1、C语言 指针基础

一、内存地址

一、内存含义数组

  • 存储器:计算机的组成中,用来存储程序和数据,辅助CPU进行运算处理的重要部分。
  • 内存:内部存贮器,暂存程序/数据——掉电丢失 SRAM、DRAM、DDR、DDR二、DDR3。
  • 外存:外部存储器,长时间保存程序/数据—掉电不丢ROM、ERRROM、FLASH(NAND、NOR)、硬盘、光盘。

二、内存是沟通CPU与硬盘的桥梁ide

  • 暂存放CPU中的运算数据
  • 暂存与硬盘等外部存储器交换的数据

三、物理存储器和存储地址空间函数

  • 有关内存的两个概念:物理存储器和存储地址空间

四、物理存储器:实际存在的具体存储器芯片编码

  • 主板上装插的内存条
  • 显示卡上的显示RAM芯片
  • 各类适配卡上的RAM芯片和ROM芯片

五、存储地址空间:对存储器编码的范围。咱们在软件上常说的内存是指这一层含义spa

  • 编码:对每一个物理存储单元(一个字节)分配一个号码
  • 寻址:能够根据分配的号码找到相应的存储单元,完成数据的读写

六、内存地址操作系统

  • 将内存抽象成一个很大的一维字符数组。
  • 编码就是对内存的每个字节分配一个32位或64位的编号(与32位或者64位处理器相关)。
  • 这个内存编号咱们称之为内存地址。

七、内存中的每个数据都会分配相应的地址指针

  • char:占一个字节分配一个地址
  • int: 占四个字节分配四个地址
  • float、struct、函数、数组等

二、指针变量

1、概述

  • 内存区的每个字节都有一个编号,这就是“地址”。
  • 若是在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并肯定它的内存地址(编号)
  • 指针的实质就是内存“地址”。指针就是地址,地址就是指针。
  • 指针是内存单元的编号,指针变量是存放地址的变量。
  • 一般咱们叙述时会把指针变量简称为指针,实际他们含义并不同。

2、数据存储格式

注:windos电脑在作数据存储时采用小端对齐。blog

注:Linux 电脑在作数据存储时采用大端对齐。排序

3、定义说明

  • 指针也是一种数据类型,指针变量也是一种变量
  • 指针变量指向谁,就把谁的地址赋值给指针变量
  • “*”操做符操做的是指针变量指向的内存空间

注意:&能够取得一个变量在内存中的地址。可是,不能取寄存器变量,由于寄存器变量不在内存里,而在CPU里面,因此是没有地址的。
注意:&是取地址符号是升维度的、*是取值符号是将维度的。
注意:在定义指针类型必定要和变量的类型对应上。内存

4、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 定义指针变量存储变量地址
    int a = 10;
    // 指针类型:数据类型*
    int* p;
    p = &a;
    // 经过指针间接改变变量的值
    *p = 100;
    printf("%p\n", &a);
    printf("%p\n", p);
    printf("%d\n", a);
    printf("%d\n", *p);
    return 0;
}
指针变量 使用案例:int类型指针修改值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    char ch = 'a';
    char* p = &ch;

    // 全部指针类型存储都内存地址,内存地址都是一个无符号十六进制整形数
    // 32位操做系统全部指针类型:内存占用4字节
    // 64位操做系统全部指针类型:内存占用8字节
    printf("%d\n", sizeof(int*));
    printf("%d\n", sizeof(char*));

    return 0;
}
指针变量 使用案例:指针在内存中占用字节大小
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    
    // P 和 arr 不一样点
    // 指向数组指针
    int* p = arr;

    // 相同点
    //p[i]
    //*(p+i)

    // 不一样点
    // p 是变量、arr是常量
    // p 是一个指针4个字节大小
    // arr 是一个数组是40个字节大小
    printf("指针类型大小%d\n", sizeof(p));
    printf("数组大小%d\n", sizeof(arr));
    
    // 数组做为函数参数会化为指针、丢失数组的精度
    // 经过 int* 将指针变为值
    // void BubbleSort(int arr[])
    // void BubbleSort(int* arr[],int len)

    return 0;
}
指针变量 使用案例:指针与变量不一样点

三、野指针

  指针变量也是变量,是变量就能够任意赋值,不要越界便可(32位为4字节,64位为8字节),可是,任意数值赋值给指针变量没有意义,由于这样的指针就成了野指针,此指针指向的区域是未知(操做系统不容许操做此指针指向的内存区域)。因此,野指针不会直接引起错误,操做野指针指向的内存区域才会出问题。野指针和有效指针变量保存的都是数值,为了标志此指针变量没有指向任何变量(空闲可用)

       int a = 100;
       int *p;
       p = a; //把a的值赋值给指针变量p,p为野指针, ok,不会有问题,但没有意义
 
       p = 0x12345678; //给指针变量p赋值,p为野指针, ok,不会有问题,但没有意义
 
       *p = 1000;  //操做野指针指向未知区域,内存出问题,err

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 野指针 -> 指针变量指向一个未知的空间
    // 不建议将一个变量的值直接赋值给指针
    // 程序中容许存在野指针
    int* p = 100;
    // 操做系统将0-255做为系统占用不容许访问操做
    // 操做野指针对应的内存空间可能报错
    printf("%d\n", *p);

    return 0;
}
野指针 使用案例

四、空指针

C语言中,能够把NULL赋值给此指针,这样就标志此指针为空指针,没有任何指针。

// 空指针
int *p = NULL;
 
// NULL是一个值为0的宏常量:
#define NULL    ((void *)0)

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 空指针是指内存地址编号为0的空间
    int* p = NULL;
    // 操做空指针对应的空间必定会报错
    *p = 100;
    printf("%d\n", *p);
    // 空指针能够用做条件判断
    if (p == NULL)
    {
        
    }
    return 0;
}
空指针 使用案例

五、万能指针

void *指针能够指向任意变量的内存空间。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int a = 10;
    // 万能指针能够接受任意类型变量的内存地址
    void * p = &a;
    // 再经过万能指针修改变量的值时,须要找到变量对应的指针类型
    *(int*)p = 100;
    printf("%d\n", a);
    printf("%d\n", *(int*)p);
    // printf("万能指针在内存占得字节大小:%d\n", sizeof(void*));
    return 0;
}
万能指针 使用案例

六、const 修饰指针

const 修饰能够约束指针类型或值得修改,但使用+1级别指针也可让const无效。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 一、
    // 常量:不容许修改
    // 存储空间:栈区(可指针间接修改)
    const int a = 10;

    // 指针间接修改常量值
    int* p = &a;
    *p = 100;
    printf("%d\n", a);

    // 二、
    // const 修饰指针类型(内存空间)
    int a = 10;
    int b = 20;
    const int* p = &a;

    // 能够修改指针变量的值
    // 不能够修改指针内存空间的值:*p = 100;
    p = &b;
    printf("%d\n", *p);

    // 三、
    // const 修饰指针变量
    int c = 10;
    int d = 20;
    int* const p = &c;

    // 能够修改指针类型(内存空间)的值
    // 不能够修改指针内存空间的值:p = &d;
    *p = 100;
    printf("%d\n", *p);


    // 四、
    // const 修饰指针变量、类型(内存空间)
    // 只读指针
    int e = 10;
    int f = 20;
    // 不能够修改指针内存空间的值:*p = 100;
    // 不能够修改指针内存空间的值:p = &f;
    const int* const p = &e;

    // 二级指针操做
    // 可经过二级指针修改一级指针内存空间的值:
    int** pp = &p;
    // *pp是一级指针的值(内存空间)
    *pp = &b;
    // **pp是变量的值、**表明将了一个维度
    **pp = 100;
    printf("%d\n", *p);


    return 0;
}
const修饰指针 使用案例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(void)
{
       //const修饰一个变量为只读
       const int a = 10;
       //a = 100; //err
 
       //指针变量, 指针指向的内存, 2个不一样概念
       char buf[] = "aklgjdlsgjlkds";
 
       //从左往右看,跳过类型,看修饰哪一个字符
       //若是是*, 说明指针指向的内存不能改变
       //若是是指针变量,说明指针的指向不能改变,指针的值不能修改
       const char *p = buf;
       // 等价于上面 char const *p1 = buf;
       //p[1] = '2'; //err
       p = "agdlsjaglkdsajgl"; //ok
 
       char * const p2 = buf;
       p2[1] = '3';
       //p2 = "salkjgldsjaglk"; //err
 
       //p3为只读,指向不能变,指向的内存也不能变
       const char * const p3 = buf;
 
       return 0;
}
const修饰指针 使用案例:2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 定义int类型
    const int a = 10;
    // 直接不能够修改
    // a = 100; //err
    // 经过一级指针修改
    int* p = &a;
    *p = 100;

    // 定义char类型
    char ch1[] = "hello";
    char ch2[] = "hello";
    // 指向常量指针:能够修改指针变量的值、不能够修改指针变量指向内存空间的值
    const char* p = ch1;
    // *p = 'm';//err
    // p = ch2;//ok
    // p[2] = 'm';//err

    // 定义char类型
    char ch3[] = "hello";
    char ch4[] = "hello";
    // 常量指针:能够修改指针变量指向内存空间的值、不能够修改指针变量的值
    char* const p = ch3;
    // p = ch4;//err
    // p[2] = 'm';//ok
    // *(p + 2) = 'm';//ok

    // 定义char类型
    char ch5[] = "hello";
    char ch6[] = "hello";
    // 不可修改变量与内存
    const char* const p = ch5;
    // p = ch6;//err
    // p[2] = 'm';//err
    // *p = 'm';//err
    // 二级指针
    char** p1 = &p;
    // *p1 = ch2;//ok
    // *(*p1+1) = 'm';//ok

    return 0;
}
const修饰指针 使用案例:3
2、C语言 指针使用

一、指针类型运算

  • 指针计算不是简单的整数相加
  • 若是是一个int *,+1的结果是增长一个int的大小
  • 若是是一个char *,+1的结果是增长一个char大小

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    
    // 数组名是一个常量 不容许赋值
    // 数组名是数组首元素地址
    // aar = 100; //err
    // 建立指针变量
    int* p;
    p = arr;
    printf("%p\n", p);

    // 打印数组第一个值
    printf("%d\n", *p);
    printf("%p\n", arr);

    // *取值(arr内存地址+1) 、至关于arr[1]
    printf("%d\n", *(arr + 1));

    // 指针类型变量+1:等同于内存地址+sizeof(类型)
    printf("%d\n", *(p + 1));

    // 指针p++:等同于内存地址+sizeof(类型)
    *p = 123;
    p++;
    printf("%p\n", arr);
    printf("%p\n", p);

    for (int i = 0; i < 10; i++)
    {
        // 打印数组值
        printf("%d\n", p[i]);
        printf("%d\n", *(p + i));

        // 打印数组值
        printf("%d\n", *p++);
    }

    // 两个指针相减 获得的结果是两个指针的偏移量(步长)
    // 全部的指针类型 相减结果都是int类型
    // 3c 40 +1 至关于 sizeof(int) 40/sizeof(int)
    int step = p - arr;
    printf("%d\n", step);


    return 0;
}
指针类型运算 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 方式一:数组方式实现
void my_strcpy01(char* dest, char* ch)
{
    int i = 0;
    // 非0为真值
    while (ch[i])
    {
        dest[i] = ch[i];
        i++;
    }
    dest[i] = 0;
}

// 方式二:以指针偏移量
void my_strcpy02(char* dest, char* ch)
{
    int i = 0;
    while (*(ch+i))
    {
        *(dest + i) = *(ch + i);
        i++;
    }
    *(dest + i) = 0;
}

// 方式三:以指针运算方式实现
void my_strcpy03(char* dest, char* ch)
{
    while (*ch)
    {
        *dest = *ch;
        // 指针+1至关于指向数组下一个元素 内存地址变化了sizeof(char)
        dest++;
        ch++;
    }
    *dest = 0;
}

// 方式四:以指针加运算方式实现
void my_strcpy04(char* dest, char* ch)
{
    // 第一步:*ch 取值 *dest 取值
    // 第二部:*dest = *ch 赋值
    // 第三部:判断 值是否非0
    // 第四部:ch++ dest++
    while (*dest++ = *ch++);
}

int main(void)
{
    // 指针运算、字符串拷贝
    char ch[] = "hello world";
    char dest[100];
    my_strcpy04(dest, ch);
    printf("%s\n", dest);

    return 0;
}
指针类型运算 使用案例:指针加法运算
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int* p = arr;
    
    // 指针的加减运算和指针的类型有关
    p = &arr[3];
    p--;
    p--;
    p--;

    // 内存地址相差:12 / sizeof(int) = 偏移量
    int step = p - arr;

    // 指针操做数组时下标容许时负数
    // p[-2] = *(p-2);
    printf("%d\n", p[-2]);
    printf("%p\n", p);

    return 0;
}
指针类型运算 使用案例:指针减法运算
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    // 指针和运算符的操做
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int* p = arr;

    // 野指针
    // p = p + arr; //err
    // p = p*arr; //err
    // p = p*4; //err
    // p = p/4; //err
    // p = p%4; //err

    // 指针判断可使用、> = < ? && || ...
    // p = &arr[3]
    // if (p > arr) { printf("真\n");}

    // 野指针能够相减
    // p = 100;
    // int step = arr - p;
    ///printf("%d\n",step)

    return 0;
}
指针类型运算 使用案例:指针符号运算

二、指针数组

指针数组,它是数组,数组的每一个元素都是指针类型。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    // 定义数组 数据类型 数据名[元素个数] = {值1,值2}
    // 定义指针数组
    int a = 10;
    int b = 20;
    int c = 30;
    int* arr[3] = { &a,&b,&c };

    // arr[0]:为指针数组地址
    // *arr[0]:为指针对应值
    printf("%d\n", arr[0]);
    printf("%d\n", *arr[0]);

    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        // 打印数组内每一个值
        printf("%d\n", *arr[i]);
    }

    // 指针数组大小 = 对应类型 * 元素个数 
    printf("指针数组大小:%d\n", sizeof(arr));
    printf("指针数组大小:%d\n", sizeof(arr[0]));

    return 0;
}
指针数组 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    // 指针数组里面元素存储的是指针
    int a[] = { 1,2,3 };
    int b[] = { 4,5,6 };
    int c[] = { 7,8,9 };

    // 指针数组时一个特殊的二维数组模型
    // 指针数组对应于二级指针
    int* arr[] = { a,b,c };

    // 打印内存地址
    // arr 是指针数组的首地址
    printf("%p\n", arr[0]);
    printf("%p\n", a);
    printf("%p\n", &a[0]);


    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            // 经过二维数组方式打印全部值
            printf("%d", arr[i][j]);
            // 经过偏移量方式打印
            printf("%d", *(arr[i]+j));
            // 经过偏移量与指针运算方式打印
            printf("%d", *(*(arr + i) + j));
        }
        puts("");
    }
    return 0;
}
指针数组 使用案例:2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
// 数组名作函数参数,函数的形参会退化为指针
// 经过数组写法实现
void my_strcat01(char* ch1, char* ch2)
{
    int i = 0;
    while (ch1[i] != '\0')
    {
        i++;
    }
    int j = 0;
    while (ch2[j] != '\0')
    {
        ch1[i + j] = ch2[j];
        j++;
    }
    ch1[i + j] = 0;
}

// 经过指针加偏移量方式实现1
void my_strcat02(char* ch1, char* ch2)
{
    int i = 0;
    while (ch1[i] != '\0')
    {
        i++;
    }
    int j = 0;
    while (*(ch2 + j) != '\0')
    {
        *(ch1 + i + j) = *(ch2 + j);
        j++;
    }
    ch1[i + j] = 0;
}

// 经过指针加偏移量方式实现2
void my_strcat03(char* ch1, char* ch2)
{
    while (*ch1)ch1++;
    while (*ch1++ = *ch2++);
}

int main(void)
{
    char ch1[100] = "hello";
    char ch2[] = "world";
    my_strcat02(ch1, ch2);
    printf("%s\n", ch1);

    return 0;
}
指针数组 使用案例:数组名做为函数参数

三、多级指针

  • C语言容许有多级指针存在,在实际的程序中一级指针最经常使用,其次是二级指针。
  • 二级指针就是指向一个一级指针变量地址的指针。
  • 三级指针基本用不着
int a = 10;
int *p = &a; //一级指针
*p = 100; //*p就是a
 
int **q = &p;
//*q就是p
//**q就是a
 
int ***t = &q;
//*t就是q
//**t就是p
//***t就是a

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


int main(void)
{
    int a[] = { 1,2,3 };
    int b[] = { 4,5,6 };
    int c[] = { 7,8,9 };
    int* arr[] = { a,b,c };

    // 指针数组和二级指针创建关系
    int** p = arr;

    // 对应:arr[0][0]、a[0]
    printf("%d\n", **p);

    // 二级指针加偏移量:至关于跳过了一个觉得数组大小
    // 一级指针加偏移量:至关于跳过了一个元素
    //对应:arr[0][1]、a[1]
    printf("%d\n", *(*p+1));
    //对应:arr[1][1]、b[1]
    printf("%d\n", *(*(p + 1) + 1));

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            // 经过偏移量与指针运算方式打印
            printf("%d", *(*(arr + i) + j));
        }
        puts("");
    }
    return 0;
}
多级指针 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{

    //*ppp==**pp==&p
    //**ppp==*pp=p==&a
    //***ppp==**pp==*p=a
    int a = 10;
    int b = 20;
    int* p = &a;
    int** pp = &p;
    int*** ppp = &pp;


    // pp:二级指针变量的值
    // *pp:一级指针的值
    // **pp:变量的值

    // 等价于:p=&b
    // *pp = &b;

    // 等价于:a = 100
    //**pp = 100;

    // 野指针
    // *p = 100;

    printf("%d\n", *p);
    return 0;
}
多级指针 使用案例:2

四、字符指针

字符指针经过指针处理字符

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 栈区字符串
    char ch[] = "hello world";
    
    // 数据区常量区字符串、不容许修改内容
    // hello world 对应内存地址为只读,大小相同
    char* p = "hello world";
    char* p1 = "hello world";

    // ch[2] = 'm'; // 可修改
    // p[2] = 'm'; //err

    return 0;
}
字符指针 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 样式一
    // 能够作修改
    // 指针数组
    char ch1[] = "hello";
    char ch2[] = "world";
    char ch3[] = "dabaobei";
    char* arr1[] = { ch1,ch2,ch3 };

    // 样式二
    // 不能作修改、但能够排序
    // 字符串数组
    char* arr2[] = { "hello","wojjrld","zzzzz" };

    // 字符串排序
    for (int i = 0; i < 3 - 1; i++)
    {
        for (int j = 0; j < 3 - 1 - i; j++)
        {
            // 找首字符进行比较
            if (arr2[j][0]>arr2[j + 1][0])
            {
                // 交换指针数组进行排序
                char* temp = arr2[j];
                arr2[j] = arr2[j + 1];
                arr2[j + 1] = temp;
            }
        }
    }

    // 打印
    for (int i = 0; i < 3; i++)
    {
        printf("%s\n", arr2[i]);
    }
    return 0;
}
字符指针 使用案例:2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 数组实现
int my_strlen01(char* ch)
{
    // 计算字符串有效长度
    int i = 0;
    while (ch[i] != '\0')i++;
    return i;
}

// 指针实现
int my_strlen02(char* ch)
{
    char* temp = ch;
    while (*temp != '\0')temp++;
    return temp - ch;
}

int main(void)
{
    char ch[] = "hello world";
    int len = my_strlen02(ch);
    printf("%d\n", len);
    return 0;
}
字符指针 使用案例:字符指针做为函数参数
3、案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 指针做为函数参数传递
void swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main(void)
{

    int a = 10;
    int b = 20;

    // 值传递
    // 形参不影响实参的值
    // swap(a, b);

    // 地址传递
    // 形参能够改变实参的值
    swap(&a, &b);

    printf("%d\n", a);
    printf("%d\n", b);

    return 0;
}
指针 使用案例:值传递和地址传递
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

void remove_space(char* ch)
{
    // 便利字符串有效个数
    char* ftemp = ch;
    // 记录非空格字符串
    char* rtemp = ch;
    while (*ftemp)
    {
        if (*ftemp != ' ')
        {
            *rtemp = *ftemp;
            rtemp++;
        }
        ftemp++;
    }
    *rtemp = 0;
}

int main(void)
{
    char ch[] = "  h  e  ll  o  w o r lld";
    remove_space(ch);
    printf("%s\n", ch);
    return 0;
}
指针 使用案例:字符串去空格
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 数组方式
char* my_strchr01(char* str,char ch)
{
    int i = 0;
    while (str[i])
    {
        if (str[i] == ch)
        {
            return &str[i];
        }
        i++;
    }
    return NULL;
}

// 指针方式
char* my_strchr02(char* str, char ch)
{
    while (*str)
    {
        if (*str == ch)
        {
            return str;
        }
        str++;
    }
    return NULL;
}

int main(void)
{
    char str[] = "hello world";
    char* p = my_strchr02(str,'w');
    if (p == NULL)
    {
        printf("未找到:");
    }
    printf("%s\n", p);
    return 0;
}
指针 使用案例:指针作为函数的返回值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

char* my_strchr(char* src, char* dest)
{
    // 用于循环便利源字符串指针
    char* fsrc = src;
    // 记录每次相同字符串首地址
    char* rsrc = src;
    char* tdest = dest;
    while (*fsrc)
    {
        rsrc = fsrc;
        while (*fsrc == *tdest && *fsrc!='\0')
        {
            fsrc++;
            tdest++;
        }
        if (*tdest == '\0')
        {
            return rsrc;
        }
        // 回滚
        // 目标字符串更新到起始位置
        tdest = dest;
        fsrc = rsrc;
        fsrc++;
    }
    return NULL;
}

int main(void)
{
    char src[] = "hello world";
    char dest[] = "llo";
    char* p = my_strchr(src,dest);
    printf("%s\n", p);
    return 0;
}
指针 使用案例:模糊查询
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 数组实现
int getstrcount01(char* ch)
{
    int i = 0;
    int count = 0;
    while (ch[i])
    {
        if (ch[i] != ' ')
        {
            count++;
        }
        i++;
    }
    return count;
}

// 指针实现
int getstrcount02(char* ch)
{
    int count = 0;
    while (*ch)
    {
        if (*ch != ' ')count++;
        ch++;
    }
    return count;
}

int main(void)
{
    char ch[] = "    hello world    ";
    int len = getstrcount(ch);
    printf("%d\n", len);
    return 0;
}
指针 使用案例:求非空字符串元素的个数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    //97+26 ASCLL码 
    // 统计字符串出现次数
    char ch[] = "helloworldfdjklfdjklfdsajklfdsa dsa";
    
    // 存储字符串出现次数
    int arr[26] = {0};
    
    for (int i = 0; i < strlen(ch); i++)
    {
        // ASCLL码 a - 字符、++:每找到一个相同就+1
        arr[ch[i] - 'a']++;
    }

    for (int i = 0; i < 26; i++)
    {
        if(arr[i])
            printf("字母:%c出现次数:%d\n", i + 'a', arr[i]);
    }
    return 0;
}
指针 使用案例:统计字符个数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 数组实现
void inverse01(char* ch)
{
    int i = 0;
    int j = strlen(ch) - 1;
    while (i < j)
    {
        char temp = ch[i];
        ch[i] = ch[j];
        ch[j] = temp;
        i++;
        j--;
    }
    return;
}

// 指针实现
void inverse02(char* ch)
{
    char* ftemp = ch;
    char* btemp = ch + strlen(ch) - 1;
    while (ftemp<btemp)
    {
        char temp = *ftemp;
        *ftemp = *btemp;
        *btemp = temp;
        ftemp++;
        btemp--;
    }
    return;
}

int main(void)
{
    char ch[] = "hello world";
    inverse02(ch);
    printf("%s\n", ch);
    return 0;
}
指针 使用案例:字符串逆质
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int symm(char* ch)
{
    char* ftemp = ch;
    char* btemp = ch + strlen(ch) - 1;
    while (ftemp < btemp)
    {
        if (*ftemp!=*btemp)
        {
            return 1;
        }
        ftemp++;
        btemp--;
    }
    return 0;
}

// 判断:回文字符串
int main(void)
{
    char ch[] = "abcba";
    int value = symm(ch);
    if (!value)
    {
        printf("相同\n");
    }
    else
    {
        printf("不相同\n");

    }
    return 0;
}
指针 使用案例:判断回文字符串
相关文章
相关标签/搜索