05_指针实战运用进阶之字符串操作

本文介绍了C语言中指针在字符串操作中的应用,包括动态内存分配、字符串长度计算、字符串比较与拼接以及大小写转换。通过实例展示了如何使用realloc调整内存大小,以及如何实现简单的字符串查找、包含判断和位置计算。此外,还手写了一个将字符串转为小写的函数。
摘要由CSDN通过智能技术生成

指针实战运用进阶之字符串操作

1. 上节课遗留点

在这里插入图片描述

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

// 动态开辟之realloc
int mainT0() {

    int num;
    printf("请输入个数");
    // 获取用户输入的值
    scanf("%d", &num);

    // 5个值
    int * arr = (int *) malloc(sizeof(int) * num);
    for (int i = 0; i < num; ++i) {
        arr[i] = (i + 10001); // arr[i]的内部隐士 == *(arr+i)
    }
    printf("开辟的内存指针: %p\n", arr);

    // 打印 内容
    for (int i = 0; i < num; ++i) {
        // Derry装B的打印
        // &取出内存地址 *然后去值
        // .....
        printf("元素的值:%d, 元素的地址:%p\n",*(arr + i),(arr + i));
    }

    // =================================   在堆区开辟新的空间  加长空间大小

    // 新增
    int new_num;
    printf("请输入新增加的个数");
    scanf("%d", &new_num);

    // 原来的大小4 + 新增加的大小4  =  总大小 8
    // void *realloc (void *前面开辟的指针, size_t总大小);
    int * new_arr = (int *) realloc(arr, sizeof(int) * (num + new_num));

    if (new_arr) { // new_arr != NULL 我才进if  【非0即true】
        int j = num; // 4开始
        for (; j < (num + new_num); j++) { // 5 6 7 8
            arr[j] = (j + 10001);
        }

        printf("新 开辟的内存指针: %p\n", new_arr);

        // 后 打印 内容
        for (int i = 0; i < (num + new_num); ++i) {

            printf("新 元素的值:%d, 元素的地址:%p\n",
                   *(arr + i),
                   (arr + i)
            );
        }
    }

    // 我已经释放
    /*free(new_arr);
    new_arr = NULL;*/

    // 1000行代码
    // 。。。

    //  重复释放/重复free VS会奔溃,   CLion会优化(发现不奔溃)   [错误的写法]
    /*free(new_arr);
    new_arr = NULL;*/

    // 必须释放【规则】
    /*if (arr) {
        free(arr);   // 如果不赋值给NULL,就是悬空指针了
        arr = NULL;
    }*/

    /*if (new_arr) {
        free(new_arr);   // 如果不赋值给NULL,就是悬空指针了
        new_arr = NULL;
    }*/

    // TODO ========================== 下面代码对我们上节课 遗留点 完成  末尾工作了
    if (new_arr) { // new_arr != NULL 进去if, 重新开辟的堆空间是成功的
        free(new_arr);
        new_arr = NULL;
        arr = NULL; // 他还在指向那块空间,为了不出现悬空指针,指向NULL的空间
    } else { // 重新开辟的堆空间是失败的
        free(arr);
        arr = NULL;
    }
    // 画图:内存的走向  1
    return 0;
}

2. 字符串两种形式

在这里插入图片描述

#include <stdio.h>

int mainT2(){
    char str[] = {'D', 'e', 'r', 'r', 'y', '\0'};
    str[2] = 'z'; // 这里能修改?
    printf("第一种方式:%s\n", str); // printf 必须遇到 \0 才结束

    char * str2 = "Derry"; // 隐士  Derry+\0
    //str2[2] = 'z'; 这样写是错误的,会奔溃,不允许访问,为什么 画图  原理图
    printf("第二种方式:%s\n", str2);
    return 0;
}

3. 指针挪动获取字符串信息(手写API)

在这里插入图片描述

// 3.指针挪动获取字符串信息
#include <stdio.h>

// 获取长度
/*int getLen(char * string) {
    int count = 0;
    // *string != '\0' 我就一直循环
    while (*string) {
        string ++;
        count++;
    }
    return count;
}

int mainT3() {
    char string[] = {'A', 'B', 'C', 'D', '0', '\0'}; // printf方法能够停下来,不要打印系统值
    int r =  getLen(string);
    printf("长度是:%d\n",r);
    return 0;
}*/

// C/C++编译器,数组作为参数传递,会把数组优化成指针(为了高效率)
//void getLen(int intarr[]) {
//数组作为参数传递,就不能这样写了
//sizeof(intarr)28/sizeof(int)4=7
//int len = sizeof(intarr)/sizeof(int);
//printf("getLen len长度是:%d\n", len);
//}
// 模仿了 strLen函数
void getLen(int * resultLen, int intarr[]) {
    //手动计算长度
    int count = 0;
    while (*intarr) {
        intarr++;
        count++;
    }
    *resultLen = count;
}
void doEngine(int len) {}

int mainT3(){
    // 数组中加‘\0’的原因是让printf方法能够停下来,不要打印系统值
    // char string[] = {'A', 'B', 'C', 'D', '0', '\0'};

    // 0, \0其他函数for其他调用判断的时候.这个有冲突【int类型数组】
    int intarr[] = {1, 2, 3, 4, 5, 6, 7, '\0'};
    //int类型使用这种方式【第一种方式】
    //sizeof(intarr)28 / sizeof(int)4 = 7;
    int len = sizeof(intarr) / sizeof(int);
    printf("len长度是:%d\n", len);

    int result; //&取出result遍历的地址值给函数
    getLen(&result, intarr);
    printf("getLen len长度是:%d\n", result);

    // strLen API 的用法太简单 【第二种方式】 尝试

    // 真实函数直接调用,可以这样,传递长度
    doEngine(len);
    return 0;
}

4. 字符串的比较

// 字符串查找,包含,拼接。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int mainT5() {

    char * text = "name is Derry";
    char * subtext = "D";

    char * pop = strstr(text, subtext);

    // 怎么去 字符串查找
    if (pop) { // 非NULL,就进入if,就查找到了
        printf("查找到了,pop的值是:%s\n", pop);
    } else {
        printf("没有查找到,subtext的值是:%s\n", subtext);
    }

    // 包含了D吗
    if (pop) {
        printf("包含了\n");
    } else {
        printf("没有包含\n");
    }

    // printf("pop地址%p, text地址:%p,\n", pop, text);

    // 求取位置?  数组是一块连续的内存空间,没有断层,所以可以-
    int index = pop - text; // pop="Derry" - text"name is Derry"
    printf("%s第一次出现的位置是:%d\n", subtext, index); // 我的D在第8个位置

    // 指针是可以:++ --  +=  -=

    // 拼接 ========================
    char destination[25]; // 容器 25的大小 已经写死了
    char * blank = "--到--", *CPP="C++", *Java= "Java";

    strcpy(destination, CPP); // 先Copy到数组里面去
    strcat(destination, blank); // 然后再拼接
    strcat(destination, Java); // 然后再拼接
    printf("拼接后的结果:%s\n", destination); // C++--到--Java

    return 0;
}

5. 字符串查找,包含,拼接

// 字符串查找,包含,拼接。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int mainT5() {

    char * text = "name is Derry";
    char * subtext = "D";

    char * pop = strstr(text, subtext);

    // 怎么去 字符串查找
    if (pop) { // 非NULL,就进入if,就查找到了
        printf("查找到了,pop的值是:%s\n", pop);
    } else {
        printf("没有查找到,subtext的值是:%s\n", subtext);
    }

    // 包含了D吗
    if (pop) {
        printf("包含了\n");
    } else {
        printf("没有包含\n");
    }

    // printf("pop地址%p, text地址:%p,\n", pop, text);

    // 求取位置?  数组是一块连续的内存空间,没有断层,所以可以-
    int index = pop - text; // pop="Derry" - text"name is Derry"
    printf("%s第一次出现的位置是:%d\n", subtext, index); // 我的D在第8个位置

    // 指针是可以:++ --  +=  -=

    // 拼接 ========================
    char destination[25]; // 容器 25的大小 已经写死了
    char * blank = "--到--", *CPP="C++", *Java= "Java";

    strcpy(destination, CPP); // 先Copy到数组里面去
    strcat(destination, blank); // 然后再拼接
    strcat(destination, Java); // 然后再拼接
    printf("拼接后的结果:%s\n", destination); // C++--到--Java

    return 0;
}

6. 大小写转换(手写API)

// 大小写转换(手写API)

#include <stdio.h>
#include <ctype.h>

// 指针的理解
void lower(char * dest, char * name) {
    char * temp = name; // 临时指针,你只能操作临时指针,不能破坏name指针
    while (*temp) {
        *dest = tolower(*temp);
        temp ++; // 挪动指针位置 ++
        dest ++; // 挪动指针位置 ++  目的是为了 挪动一个存储一个 挪动一个存储一个 ...
    }
    // printf '\0'
    *dest = '\0'; // 避免printf打印系统值

    printf("不能破坏 name:%s\n", name); // temp的好处就是,不会破坏name
}

// 全部变成小写 derry
int mainT6() {
    char * name = "DerrY"; // 隐士 DerrY+\0

    // 先定义结果
    char dest[20];
    lower(dest, name);
    printf("小写转换后的结构是:%s\n", dest);

    // 这样-不成功
    /*char * a = "ABCDEFG";
    char * b = "AB";
    int r = b - a;
    printf("r:%d\n", r);*/

    // 作业:
    /*char * str = "Derry is";
    char * result;
    函数(&result, str, 2, 5);
    printf("%s\n", result); 最终输出:rry*/

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

左绍骏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值