C:04.字符串常见操作和指针练习

知识点:

1.字符串定义

字符串以 \0 结尾,动态开辟内存的时候也需要多考虑一位

定义方式有两种:

  1. char str[] = {'E','a','s','t','r','i','s','e','\0'}; : 可以修改
  2. const char *str1 = "Eastrise";:不能修改,字符串常量存放再全局的const内存区
int main(){
    // 第一种 字符串数组
    char str[] = {'E','a','s','t','r','i','s','e','\0'};

    str[2] = 'y';

    printf("%s\n",str); // 字符串结尾必须是 '\0',开辟内存也需要多开辟一个

    // 第二种 不加 const 会警告:deprecated conversion from string constant to 'char*'
    // 原因:
    //      "Eastrise"是字符串常量, 内存分配在全局的const内存区
    //       char * 声明了一个指针,而这个指针指向的是全局的const内存区,const内存区当然不会让你想改就改的。所以,如果你一定要写这块内存的话,那就是一个非常严重的内存错误。
    const char *str1 = "Eastrise";

//    str1[2] = 'y';

    printf("%s\n",str1);

    // 两种定义的区别:一个能修改,一个不能修改

}

2.字符串长度获取

  1. strlen(name)

  2. 通过sizeof 进行计算(不好使),不对

        const char str[] = {'E','a','s','t','r','i','s','e','\0','i','s'};
    
        // 怎么获取长度?有一种方式计算(不好使)
        printf("length is %d",sizeof(str)/sizeof(char)); // 打印出来 11,实际结果应该是 8
    
  3. 写一个方法读取字符串的长度

    int strlen_(char *str){
        // 怎么获取字符串的长度? 不断读取字符,判断末尾 '\0'
    
        int len = 0;
        while (*str != '\0')
        {
            len++;
            str++;
        }
        return len;
    }
    

3.字符串与基本数据类型的转换

  • atoi(num_str); // str 转 int如果不能转换就是 0 ,后面如果有其他不是数字的就会被剔除 12xxx -> 12
  • atof(num_str); // str 转 float // 如果不能转换返回的是默认值 0.000000
  • strtod(num_str, NULL); // str 转 double // 如果不能转换返回的是默认值 0.000000
int main(){

     const char* num1 = "1"; // -> int float double
     const char* num_str1 = "12.0xxx";
     int number1 = atoi(num_str1); // 如果不能转换就是 0 ,后面如果有其他不适数字的就会被剔除 12xxx -> 12
    printf("number1 is %d\n",number1);

     const char* num_str2 = "12.5f";
     float number2 = atof(num_str2); // 如果不能转换返回的是默认值 0.0000
    printf("number2 is %f\n",number2);

    const char *num_str3 = "12.5xx";
    double number3 = strtod(num_str3,NULL);// 如果不能转换就是 0.000 ,后面如果有其他不适数字的就会被剔除 12.5xxx -> 12.5000

    printf("number3 is %lf\n",number3);
    getchar();
}

打印结果:

number1 is 12
number2 is 12.500000
number3 is 12.500000

4.字符串的比较

  • int rc = strcmp(str1, str2); // 区分大小写比较,rc == 0代表相等,rc > 0 str1 比 str2 大
  • int rc = strcmpi(str1, str2); // 不区分大小写比较,rc == 0代表相等,反之不相等
  • int rc = strncmp(str1, str2,7); // 区分大小写比较, count 代表的是比较字符串前几个是否相等
  • int rc = strnicmp(str1, str2,7); // 不区分大小写比较, count 代表的是比较字符串前几个是否相等
int main(){
    const char* str1 = "Eastrise";
    const char* str2 = "eastrise";

    // 大于小于等于
    // int rc = strcmp(str1,str2); // 区分大小写比较
    // int rc = _strcmpi(str1,str2); // 不区分大小写比较 c strcmpi c++ _strcmpi , android ndk strcasecmp;

    // 比较前几个
//     int rc = strncmp(str1,str2,7); // count 达标的是比较字符串前几个是否相等
    int rc = _strnicmp(str1,str2,6); // 不区分大小写的比较
    if(rc == 0) {
        printf("相等");
    }else{
        printf("不相等");
    }

    getchar();
}

5.字符串查找,包含

  • char* pos = strstr(str, substr); // 返回的是字符串第一次出现的位置(位置指针), 如果没有找到返回的是空

    获取位置: int position = pos - str;

  • char* pos = strchr(name,'n'); // 返回的是字符第一次出现的位置(位置指针), 如果没有找到返回的是空

int main() {

    const char *str = "name not Eastrise";
    const char *substr = "E";
    char *pos = strstr(str, substr); //  返回的是字符串第一次出现的位置(位置指针),如果没有找到返回的是空
    printf("%s\n", pos); // Eastrise;
    // 求一下位置 int 怎么办? strstr
    int position = pos - str;

    printf("第一次出现的位置是:%d\n", position);

    // 包含? pos 是不是空就可以了
    if (pos)
        printf("%s", "包含");
    else
        printf("%s", "不包含");

    getchar();
}

打印结果:

Eastrise
第一次出现的位置是:9
包含

6.字符串复制和拼接

  • strcpy(dst, src); // 复制
  • strcat(dst,src); // 拼接
int main(){

    //strcopy; copy进来
    const char* str = "eastrise";

    const char* str1 = " is";

    // char* str1 = "is";
    char cpy[strlen(str)+strlen(str1)];

    // str 会 copy 到 cpy 里面
    strcpy(cpy,str);

    printf("%s\n",cpy);

    //拼接
    strcat(cpy,str1);

    printf("%s",cpy);

    getchar();
}

打印结果:

eastrise
eastrise is

7.手写字符串截取

// 截取
char* substr(const char* str,int start ,int end){
    // 开辟一个字符串去存储我们的数据,开辟多大计算
    // char sub[end -start];
    int len = end - start;
    if (len == 0) {
        return nullptr;
    }
    char* sub = (char*)malloc(sizeof(char)*(len+1));// 记得+1,因为还有一个\0,在 NDK 一般会采用静态的数组存储 char sub[len]
    // malloc 一定要 free

    // 遍历赋值
    for(int i = 0; i< len; i++){
        sub[i] = str[start+i];
    }
    // 标记字符串结尾,否则 print 无法判断结尾
    sub[len] = '\0';

    printf("%p\n",sub);

    // free(sub);

    return sub;
}

// 字符串的截取
int main(){
    const char* str = "Eastrise is";

    // 截取第三个位置到第五个位置 3,5
    char* sub = substr(str,0,5);

    printf("%p\n",sub);

    printf("%s",sub);

    // 一定要free ,因为你的 substr 有动态开辟内存,但是真正开发中并不会这么做,自己的方法尽量要自己处理好内存
    free(sub);

    getchar();
}

打印结果:

0000000000B61440
0000000000B61440
Eastr

8.手写字符串小写转换

字符大小写转换

  • tolower(ch); // A->a
  • toupper(ch); // a->A
#include <ctype.h>
// dest 用来存放结果, 大小自己指定
// source 需要转换的字符串
void lower(char* dest,const char* source){
    while (*source != '\0'){
        // 拿当前字符
        char ch = *source;
        // 转换完成后赋值给 dest
        *dest = tolower(ch); // a->a A->a
        source++;
        dest++;
    }
    // 标记字符串结尾
    *dest = '\0';
}

void upper(char* dest,const char* source){
    while (*source != '\0'){
        char ch = *source;
        *dest = toupper(ch);
        source ++;
        dest ++;
    }

    *dest = '\0';
}

9. 手写字符串的替换

char *substr(const char *str, int start, int end) {
    // 开辟一个字符串去存储我们的数据,开辟多大计算
    // char sub[end -start];
    int len = end - start;
    if (len == 0) {
        return nullptr;
    }
    char *sub = (char *) malloc(sizeof(char) * (len + 1));// 记得+1,因为还有一个\0,在 NDK 一般会采用静态的数组存储 char sub[len]
    // malloc 一定要 free

    // 遍历赋值
    for (int i = 0; i < len; i++) {
        sub[i] = str[start + i];
    }
    // 标记字符串结尾,否则 print 无法判断结尾
    sub[len] = '\0';

    printf("%p\n", sub);

    // free(sub);

    return sub;
}


char *str_replace(const char *str, const char *src, const char *dst) {
    char *pos = strstr(str, src);
    if (!pos)
        return const_cast<char *>(str);

    // 1. 计算新的数组大小
    char result[strlen(str) - strlen(src) + strlen(dst)];

    // 截取替换
    int start_position = pos - str;
    char *start = substr(str, 0, start_position);
    char *end = substr(str, start_position + strlen(src), strlen(str));

    // 拼接
    if (start){
        strcpy(result, start);
        strcat(result, dst);
        free(start);
        if (end){
            strcat(result, end);
            free(end);
        }
    }else{
        strcpy(result, dst);
        if (end){
            strcat(result, end);
            free(end);
        }
    }

    return str_replace(result, src, dst);
}

// 字符串替换
int main() {
    char *str = str_replace("aabbaabbfffaa", "aa", "ccc");

    printf("%s", str);

    getchar();
}

打印结果:

00000000006D1840
00000000006D1860
00000000006D1880
00000000006D18A0
cccbbcccbbfffccc
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值