美文网首页
C语言-4、字符串

C语言-4、字符串

作者: 喂_balabala | 来源:发表于2022-07-25 19:33 被阅读0次
    • printf 必须遇到 \0 才结束
    // 字符串
    int mainT2() {
        char str[] = {'D', 'e', 'r', 'r', 'y', '\0'};
        str[2] = 'z'; // 这里能修改?
        printf("第一种方式:%s\n", str); // printf 必须遇到 \0 才结束
    
        char * str2 = "Hello"; // 隐式  Hello+\0
        str2[2] = 'z'; // 会奔溃
        printf("第二种方式:%s\n", str);
    
        return 0;
    }
    

    Question

    • 上述例子为什么字符数组可以修改中间的字符,而字符串不能修改中间的某个字符?
    • 因为str数组是在栈空间开辟,但是实际数组是在全局区(静态区)然后拷贝到栈区来使用的,修改str实际修改的是拷贝后在栈区的数据,所以可以修改。但是str2是指针,指向全局区里面的字符串,假如要修改str2中某个值实际是要修改全局区的值,是没有权限修改全局区的值的,所以会崩溃。
    获取字符串长度
    • 方式一
    int getLen(char * string) {
        int count = 0;
        while (*string) { // *string != '\0' 我就一直循环
            string ++;
            count++;
        }
        return count;
    }
    
    int main() {
        char string[] = {'A', 'B', 'C', 'D', '0', '\0'}; // printf方法能够停下来,不要打印系统值
        int r =  getLen(string);
        printf("长度是:%d\n",r);
        return 0;
    }
    
    • 方式二
    // int类型使用这种方式【第一种方式】
    // sizeof(intarr)28 / sizeof(int)4 = 7
    int len = sizeof(intarr) / sizeof(int);
    printf("len长度是:%d\n", len);
    
    • 方式三

    C/C++编译器——数组作为参数传递,会把数组优化成指针(为了高效率)

    
    void getLen(int * resultLen, int intarr[]) { // 模仿了 strLen函数
    
        // C/C++编译器 数组作为参数传递,会把数组优化成指针(为了高效率)
        // 所以数组作为参数传递 就不能这样写了
    
        // sizeof(intarr)28 / sizeof(int)4 = 7
        /*int len = sizeof(intarr) / sizeof(int);
        printf("getLen len长度是:%d\n", len);*/
    
        // 手动计算长度
        int count = 0;
        while (*intarr != '\0') {
            intarr++;
            count++;
        }
        *resultLen = count;
    }
    
    字符串转换、比较
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    // 真正的C语言,在Linux上学,在VIM上才是专业的
    int main() {
        // 字符串转换 =======================
        char * num = "1"; // 字符串
        num = "12.68";
    
        // 【int】
        int result =  atoi(num);
        if (result) { // 非0即ture  不是0进入if,  0就是转换失败了
            printf("恭喜你转换成功:%d\n", result);
        } else {
            printf("转换失败!\n");
        }
    
        // 【double】
        double resultD =  atof(num);
        printf("恭喜你转换成功:%lf\n", resultD);
    
    
        // 字符串的比较 ======================
        char * str1 = "Derry";
        char * str2 = "derry";
    
        // int resultC = strcmp(str1, str2); // strcmp = 区分大小写
        int resultC = strcmpi(str1, str2); // strcmpi = 不区分大小写
    
        if (!resultC) { // 0代表是相等的, 非0代表是不相等的
            printf("相等");
        } else {
            printf("不相等");
        }
    
        return 0;
    }
    
    
    
    字符串查找,包含,拼接
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main() {
        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;
    }
    
    
    大小写转换(手写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";
    
        // 先定义结果
        char dest[20];
        lower(dest, name);
        printf("小写转换后的结构是:%s\n", dest);
    
        // 作业:
        /*char * str = "Derry is";
        char * result;
        函数(&result, str, 2, 5);
        printf("%s\n", result); // 最终输出:rry*/
    
        // 这样-不成功
        /*char * a = "ABCDEFG";
        char * b = "AB";
        int r = b - a;
        printf("r:%d\n", r);*/
    
        return 0;
    }
    
    字符串截取的四种方式
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    // TODO 第一版   通用
    void substrAction1(char * result, char * str, int start, int end) {
        char * temp = str; // 定义临时指针,不破坏str指针
        int count = 0; // 记录当前的位置
        while (*temp) {
            // 2 到 5 的位置  在截取的范围内
            if (count >= start && count < end) {
                *result = *temp; // *temp 取出 D e r r y ...
                result++; // (接收值也要挪动)挪动指针来接收   =   *temp给我的值
            }
            temp++; // 取值也要挪动
            count++; // 当前的位置要同步
        }
    }
    
    // TODO 第二版    有意让同学,深刻理解  栈区 堆区 开辟(1)
    void substrAction2(char ** result, char * str, int start, int end) {
        char * temp = str; // 定义临时指针,不破坏str指针
    
        // 合理分配,截取多少用多少,节约
        char resultArr[end - start]; // 我只需要你截取的大小空间:例如:rry
    
        // 尽量不要使用第二种方式,会被C工程师鄙视的,为什么? 你开辟的,就应该你回收
        // char * resultArr = malloc(end - start); // 堆区开辟,第二种解决方案
    
        int count = 0;
        for (int i = start; i < end; ++i) {
            resultArr[count] = *(temp + i); // *(temp + i);取出D e r r y 给  数组容器
            count++;
        }
    
        // * 取出二级指针的一级指针 ==  main函数的result一级指针
    
        // *result = resultArr; // 不能让我们的一级指针 指向容器,因为容器会被回收掉
    
        strcpy(*result, resultArr); // 第一种解决方案
    
        printf("%s\n", resultArr);
    
        // 1   2  不能回收堆空间,否则main函数 打印了空
        // free(resultArr);
    
    } // 函数弹栈后,会回收所有的栈成员,包括:resultArr
    
    // TODO 第三版    三行代码搞定
    void substrAction3(char * result, char * str, int start, int end) { // 没有涉及栈区 堆区的概念
        // 合理分配,截取多少用多少,节约 思路
        for (int i = start; i < end; ++i) { // 刚好结束 循环三次
            *(result++) = *(str+i); // i = 2
        }
    }
    
    // TODO 第四版   一行代码搞定
    void substrAction4(char * result, char * str, int start, int end) {
        // 参数1:我最终是copy到result容器里面
        // 参数2:直接从r开始,因为我一级做了,指针挪动了
        // 参数3:你从r开始,挪动多少
        strncpy(result, str+start, end - start);
    }
    
    // 【截取】字符串的截取操作
    int main() {
    
        char *str = "Derry is";
        // 正好她是一级指针
        char *result; // char * 不需要结尾符\0
    
        // 截取第二个位置到第五个位置 2,5
    
        // substrAction1(result, str, 2, 5);
        // substrAction2(&result,str, 2, 5);
        // substrAction3(result,str, 2, 5);
        substrAction4(result, str, 2, 5);
    
        printf("main 截取的内容是:%s", result); // 最终截取:rry
    
        if (result) {
            free(result);
            result = NULL;
        }
    
        return 0;
    }
    
    
    修改值的误区
    void substrAction3(char * result, char * str, int start, int end) {
        for (int i = start; i < end; ++i) {
            *(result++) = *(str + i);
        }
    }
    
    int main() {
        char * str = "Derry is";
        // char * result = "ABCDEFG"; (会报错,因为不准修改常量值,ABCDEFG是放在全局区(静态区)的)
        // char * result = NULL;  (会报错,因为不准修改NULL值)
        // VS不允许野指针(严格)
        // char * result; // 这就是不通过的 才对的  VS 不通过对的
        // 在你的栈区开辟空间[推荐方式]  数组里的ABC是从静态区拷贝过来的
        char result[100] = "ABC";
        substrAction3(result, str, 3, 5);
        printf("%s\n", result);
        // 这两个地方搞晕了,
       // char arry1[]={'1','2'}; // 不会自动增加\0
       // 一级指针,字符指针,数组
       char * arry = "21"; // 会自动增加\0
        // char arry[10] = "12";
        char arry3[10] = "12";
    
        return 0;
    }
    
    
    

    总结

    • 数组作为参数传递,会把数组优化成指针(为了高效率)

    相关文章

      网友评论

          本文标题:C语言-4、字符串

          本文链接:https://www.haomeiwen.com/subject/yyqnirtx.html