likes
comments
collection
share

C语言字符串操作和指针小操练

作者站长头像
站长
· 阅读数 15

C语言字符串操作和指针小操练

1、静态开辟

静态开辟通常是指在栈区开辟的内存,在函数执行的过程中,函数会进栈,函数内所声明的数据类型,和数据大小,所占内存都是栈区内存。栈区内存通常大小是2M左右,如果申请的内存大小超过2M,会抛出StackOverFlow异常,栈溢出。此异常大部分是程序员使用了不正常的递归函数导致。栈区内存,在函数出栈时,内存会自动释放

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void allocateMemory() {
    //int arr[1024*1024*10];//会栈溢出
    //int arr[1024 * 1024 * 1];//会栈溢出
    int arr[(int)(1024 * 1024 * 0.2)];//不会栈溢出
    printf("arr的大小为:%d\n", sizeof(arr));//栈区占用内存大小最大值,大概两M,和平台有关系

}//执行完毕后,函数出栈,释放所有栈成员


int main() {
    //在C语言中,bool 非0 即true
    while(1) {
        allocateMemory();//一直再重复进栈 开辟 0.8M内存   ,出栈释放 0.8M内存,这个循环不会把栈撑爆
        sleep(500);
    }
    
    return 0;
}

2.动态开辟

动态开辟通常是指在堆区开辟内存

void allocateMemory() {
    //malloc 返回值是 void * , void * 可以任意转化成别的指针
    int * arr =malloc(1024*1024*1);//堆区开辟 4M 方法执行完毕,不会释放改内存,需要程序员自己释放
    // realloc(void *_Memory,size_t _NewSize);  可以理解为扩容函数,刚开始申请的大小不够用,可以调用这个函数进行扩容,
    //arr  需要扩容的数组指针,  第二个size  ,扩容后的新数组的大小, arr 数组的size + 需要扩大的容量
    int * new_arr =realloc(arr, 1024*1024*1+1024*1024);
   
    if(new_arr) {
        free(new_arr);//释放堆区内存  只是将该指针 指向的内存释放,但是指针,还会指向这个位置,此时指针变为悬空指针,需要将指针指向NULL
        new_arr =NULL;
        arr=   NULL;
    }else {//开辟失败
        free(arr);
        arr=NULL;

    }


}

malloc在堆区开辟内存, 栈区存放的是个指针,指针的地址是堆区的内存的首地址 realloc为什么要传入原先的指针,和总大小呢? arr的值和new_arr的值一样么

首先回答第二个问题,可能一样,可能不一样!

通过malloc 申请的内存都是连续的,在realloc之前,我们可能进行了其他操作,开辟了其他内存,导致arr内存后边的内存被占用,它会在一块足够大小的地方开辟一块新的内存,并将arr的内容全部复制到新内存中,并返回新内存的首地址,这时 new_arr 和 arr的值是不一样的,但是如果后边的内存没被占用,它会直接往后扩容,不会发生复制操作,这时返回的new_arr的值,和arr的值是一样的。所以为了开辟新的,所以得传入总大小,和原先数组的指针进行复制操作。

C语言字符串操作和指针小操练 还有一种情况,是开辟失败,地不多了,new_arr的地址是空,你的旧房子还在。

3、指针操练开胃小菜

#include <stdio.h>
int main() {
    int arrInt[] ={6,4,8,3,1,2,9,7,0,5};
    int reslut =arrInt[*(arrInt+*(arrInt+4))];
    printf("result的值是:%d\n",reslut);
    return 0;
}

先说结果 result =1 (arrInt+4) 数组首地址 后移四个,返回的是 1 对应的地址 (arrInt+4) 取出对应地址的值 1 arrInt+(arrInt+4) 数组首地址 后移 1, 四对应的地址 (arrInt+(arrInt+4)) 取出地址对应的值 = 4 =arrInt[*(arrInt+*(arrInt+4))] = arr[4] = 1

4、字符串两种形式

int main() {
    char str [] ="Hello";
    char * str2 = "Hello";
    printf("str%s\n",str);
    printf("str%s\n",str2);
    str[0] = 'h';
    printf("str%s\n",str);
    str2[0] ='h';//会崩溃,不允许访问
    printf("str%s\n",str2);
    return 0;
}

"Hello"是在全局区(静态区)存储 char str [] 是把全局区的Hello 复制一份到 栈区,放到str 数组里,所以可以修改,修改的只是栈区的数据。 char * str2 是在栈区定义了个指针,这个指针指向 全局区的Hello,所以无法修改

5、字符串常用API

str转int 相当于Java里的Integer.valueOf

void strToInt() {
    char * str = "x1000";
    int result = atoi(str);//atoi 转int ,atof 转float ,atod 转doble
    //1000转化结果1000  
    //1000.12转化结果1000  
    //1000abc 转化结果1000  
    //abc1000 转化结果 0 转化失败就是0
    printf("转换的结果是:%d",result);
}

有一个问题就是,如果我转换的字符串是“0”,我怎么判断它转成功了还是失败了。。。。

strcmp strcmpi

void compareStr() {
    char * str= "C语言";
    char * str2 ="Java语言C语言";
    int result = strcmp(str,str2);//此API区分大小写,,   strcmi 不区分大小写
    if(result) { //result == 0 两个字符串相同, result = -1 两个字符串相同
        printf("字符串不相同%d",result);
    }else {
        printf("字符串相同");
    }
}

这里的判断 为啥,和Bool是反的。。。 strstr

findStr() {
    char * str ="Android";
    char * str2 = "dr";
    char * result  =strstr(str,str2);//查找第一次出现的位置

    if(result) {//result != NULL 说明查找到了
        printf("查找的结果%s",result);//输出结果,droid
        //求取下标
        int index = result - str;
        printf("下标%d",index);
    }

}

字符串拼接操作

void strAppend() {
    char * android ="android";
    char * ndk ="ndk";
    char * cpp= "C嘎嘎";
    char container [13] ;
    strcpy(container,android);
    strcat(container,ndk);
    strcat(container,cpp);
    printf("拼接结果:%s",container);

}

字符串转小写(指针小操练)

void strToLower(char * dst ,char * str) {
    while(*str) {
        *dst = tolower(*str);//将一个字符转小写
        dst++;//移动指针
        str++;
    }
    *dst='\0';
}

字符串截取(指针小操练)

void subStr( char* dst ,char *src ,int start,int end) {
    int i =0;;
    src+=start;
    for ( i=start;i < end; ++i) {
        *dst = *src;
        dst++;
        src++;
    }
    *dst = '\0';
}
转载自:https://juejin.cn/post/7398231828219379727
评论
请登录