(四)C 语言之指针专题二
程序员文章站
2024-01-03 08:54:04
...
1.1 1 理解指针必须和内存四区概念相结合
1.1.1 理论
- 主调函数 被调函数
a)主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
b)被调用函数只能返回堆区、全局数据 - 内存分配方式
a)指针做函数参数,是有输入和输出特性的
。
b) 输入特性是指主调函数分配内存
c) 输出特性是指被调函数分配内存,供主调函数使用
int getMem(char ** str1 /*out*/,int * len1 /*out*/,char ** str2 /*out*/,int * len2 /*out*/)
{
char * tmp1 = NULL;
char * tmp2 = NULL;
tmp1 = (char*)malloc(sizeof(char) * 20);
tmp2 = (char*)malloc(sizeof(char) * 30);
strcpy(tmp1,"zhangsan");
strcpy(tmp2,"list");
*len1 = strlen(tmp1);
*len2 = strlen(tmp2);
*str1 = tmp1;
*str2 = tmp2;
}
int main()
{
char * str1 = NULL;
char * str2 = NULL;
int len1 = 0;
int len2 = 0;
getMem(&str1,&len1,&str2,&len2);
printf("strl =%s\n",str1);
printf("str2 = %s\n",str2);
printf("len1 =%d\n",len1);
printf("len2=%d\n",len2);
if(str1 != NULL)
{
free(str1);
str1 = NULL;
}
if(str2 != NULL){
free(str2);
str2 = NULL;
}
printf("zhangsan\n");
return 0;
}
1.2 :应用指针必须和函数调用相结合(指针做函数参数)
1.2.1 理论部分
1.3 一级指针的典型用法
1.3.1字符串
1.3.1.1 字符串
- C语言中的字符串是以零结尾的字符串
- 在C语言中没有字符串类型,通过字符数组模拟字符串
- 字符串的内存分配方式 : 堆,栈,全局区(
重要
)
1.3.1.2实例
- 字符串和字符数组
int main()
{
//不指定长度 C编译器会自动帮程序员 求元素的个数
char buf1[] ={'a','b','c','d'}; //buf1是一个数组 不是一个以0结尾的字符串
char buf2[64] = {'a','b','c','d'}; //后面的buf2[4]-buf2[63] 0
// buf3[2] = {'a', 'b', 'c', 'd'}; //如果初始化的个数大于内存的个数 编译错误
return 0;
}
2.求字符串的长度和字符数组的长度
- //用字符串 来 初始化字符数组
- //strlen() 长度 不包括0
- //sizeof() 内存块的大小
int main()
{
int size = 0;
char buf3[] = "abcd"; // buf3 作为字符数组 应该是5个字节 //作为字符串 应该4个字节
int len = strlen(buf3);
printf("buf3字符的长度:%d \n", len); //4
//buf3 作为数组 数组是一种数据类型 本质(固定小大内存块的别名)
size = sizeof(buf3); //
printf("buf3数组所占内存空间大小:%d \n", size); //5
printf("hello....\n");
{
char buf4[128] = "abcd"; // buf
printf("buf4[100]:%d \n", buf4[100]);
}
return 0;
}
// []的本质 :和*p 是一样 ,只不过是符合程序员的阅读习惯
// buf5 是一个指针, 只读的常量 buf5是一个常量指针 析构内存的时候,保证buf所指向的内存空间安全释放
1.3.2一级指针内存模型
int main()
{
char buf[20]= "aaaa"; //定义并且初始化
char buf2[] = "bbbb";
char *p1 = "111111";
char *p2 = malloc(100);
strcpy(p2, "3333");
return 0;
}
1.3.3一级指针做输入
//*操作 和++的操作
//++ 优先级高
void copy_str22(char *from, char *to)
{
for (; *from!='\0';)
{
*to++ = *from++; // 先 *to = *from; 再from++, to++
}
*to = '\0'; //
return ;
}
void copy_str23(char *from, char *to)
{
while( (*to = *from) != '\0' )
{
from ++;
to ++;
}
}
1.3.4 一级指针做输入输出
//char *p = "abcd11112wq2abcd33qw33322abcd3333w322qwqqq";
//求字符串p中 abcd出现的次数
int getCount(char *mystr /*in*/, char *sub /*in*/,int *ncount /*out*/)
{
int ret = 0;
int tmpCount = 0;
//初始化 让p指针达到查找的条件
char *p = mystr; //不要轻易改变形参的值
if (mystr==NULL || sub==NULL ||ncount==NULL)
{
ret = -1;
printf("func getCount() err:%d (mystr==NULL || sub==NULL ||ncount==NULL) \n", ret);
return ret;
}
do
{
p = strstr(p, sub);
if (p != NULL)
{
tmpCount++; //
p = p + strlen(sub); //指针达到下次查找的条件
}
else
{
break;
}
} while (*p != '\0');
*ncount = tmpCount; //间接赋值是指针存在的最大意义
return ret;
}
1.4 二级指针的典型用法
1.4.1二级指针输出模型
- 被调用函数分配内存
int getMem(char ** myp1,int *mylen1,char **myp2,int *mylen2)
{
char * tmp1= NULL;
char * tmp2= NULL;
tmp1= (char *)malloc(10);
tmp2= (char *)malloc(20);
strcpy(tmp1,"zhangsan");
strcpy(tmp2,"lisilisi");
*myp1= tmp1;
*myp2= tmp2;
*mylen1 =strlen(tmp1);
*mylen2 =strlen(tmp2);
return 0;
}
int getFree(char ** myp /*in*/)
{
char * tmp = NULL;
if(myp == NULL) return -1;
tmp =*myp;
free(tmp);
*myp= NULL; //这里用二级指针作为输入参数,可以避免野指针
return 0;
}
int getFree0(char * myp)
{
if(myp == NULL) return -1;
free(myp); //这里有野指针出现
}
int main()
{
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
getMem(&p1,&len1,&p2,&len2);
printf("p1: %s \n", p1);
printf("p2: %s \n", p2);
//getFree0(p1); //这里有野指针出现 ,如果释放两次p1,就会报错
//getFree0(p1);
getFree(&p1); //这里释放两个没有任何问题
getFree(&p1);
return 0;
}
1.4.2 二级指针做输入的三种内存模型
1.4.2.1 二级指针做输入的第一种内存模型
void printArray1(char ** array,int num)
{
int i =0;
for(i =0;i< num ;i++)
{
printf("array[%d] = %s\n",i,array[i]);
}
}
void sortArray1(char **array, int num )
{
char * tmp = NULL;
int i =0;
int j =0;
for( i =0 ;i<num ;i++)
{
for( j=i; j< num ;j++)
{
if(strcmp(array[i],array[j])> 0)
{
tmp =array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
}
int main()
{
//数组 数组中的每一个元素是指针 指针数组
char * array[] ={"cccc","bbbb","aaaa","1111"};
int num = sizeof(array)/sizeof(array[0]);
printf("before sort \n");
printArray1(array,num);
sortArray1(array,num);
printf("after sort \n");
printArray1(array,num);
}
1.4.2.1 二级指针做输入的第二种内存模型
//问题的本质是:dm03_二级指针做输入_第2种内存模型 的 myArray + 1
// dm03_二级指针做输入_第1种内存模型 myArray + 1 不一样 ;
//指针的步长不一样 指针所指向的内存空间的数据类不一样 。。。。
void printArray2_err(char ** array,int num)
{
int i =0;
for( i =0;i< num ;i++)
{
printf("array[%d] = %s\n",i,array[i]);
}
}
void printArray2(char array[10][30],int num)
{
int i =0;
for( i =0;i< num ;i++)
{
printf("array[%d] = %s\n",i,array[i]);
}
}
void sortArray2(char array[10][30], int num )
{
char tmp[30] ;
int i =0;
int j =0;
for( i =0 ;i<num ;i++)
{
for( j=i ;j< num ;j++)
{
if(strcmp(array[i],array[j])> 0) //交换的是内存块
{
strcpy(tmp,array[i]);
strcpy(array[i],array[j]);
strcpy(array[j],tmp);
}
}
}
}
int main()
{
char array[10][30] ={"aaaaaa", "ccccc", "bbbbbbb", "2222222222"};
printf("before sort \n");
printArray2(array,4);
sortArray2(array,4);
printf("after sort \n");
printArray2(array,4);
}
char myArray[10][30] = {"aaaaaa", "ccccc", "bbbbbbb", "1111111111111"};
//myArray: 编译器只会关心:有10行 ,每行30列。。。。。干什么?myArray+1 多维数组名的本质,
1.4.2.1 二级指针做输入的第三种内存模型
int getMem(char *** array,int num)
{
char ** tmpArray= NULL;
int i =0;
if(array == NULL) return -1;
tmpArray = (char **) malloc(sizeof(char*) * num);
if(tmpArray == NULL) return -1;
for( i = 0;i<num ;i++)
{
tmpArray[i]=(char*)malloc(sizeof(char) *100);
sprintf(tmpArray[i],"%d%d%d",i+1,i+1,i+1);
}
*array = tmpArray;
return 0;
}
void getFree(char *** array,int num)
{
char ** tmpArray = NULL;
int i =0;
if(array == NULL) return ;
tmpArray = *array;
for(i =0 ;i< num ;i++)
{
if(tmpArray[i]) free(tmpArray[i]);
}
free(tmpArray);
*array= NULL;
}
void printArray(char ** array,int num)
{
int i =0;
for(i =0;i< num ;i++)
{
printf("%s\n",array[i]);
}
}
void sortArray(char ** array,int num)
{
int i=0,j=0;
char * tmp =NULL;
if(array == NULL) return ;
for(i =0;i<num ;i++)
{
for(j =i+1;j<num ;j++)
{
if(strcmp(array[j],array[i])>0)
{
tmp =array[i];
array[j] =array[j];
array[j]=tmp;
}
}
}
}
int main()
{
char **p2 = NULL;
int num = 5;
char *tmp = NULL;
getMem(&p2,num);
printArray(p2,num);
getFree(&p2,num);
return 0;
}
1.4.2.1 二级指针三种内存模型内存图
1.5 案例
// 有一个字符串符合以下特征(”abcdef,acccd,eeee,aaaa,e3eeeee,sssss,";)
int splitStr(const char * mystr,char c,char ***mysubstr,int *len)
{
//计算c出现的次数
int count = 0;
int i =0;
char * p1 = NULL;
char * p2 = NULL;
char **tmp = NULL;
p1= mystr;
do{
p1 =strchr(p1,c);
if(p1) {
count++;
p1 = p1 +sizeof(char);
}
else{
break;
}
}while(*p1 != '\0');
*len = count;
tmp = (char**)malloc(sizeof(char*) * count);
if(tmp == NULL) return -1;
for( i =0 ;i< count;i++)
{
tmp[i] = (char*)malloc(sizeof(char)*30);
}
p1 = mystr;
p2 = mystr;
for(i =0 ;i<count;i++)
{
p2 = strchr(p1,c);
if(p2 == NULL) break;
strncpy(tmp[i],p1,p2-p1);
tmp[i][p2-p1] ='\0';
p1 = p2 +1;
}
*mysubstr = tmp;
return 0;
}
void printArray(char ** array,int num)
{
int i =0 ;
for(i = 0;i <num ;i++)
{
printf("array[%d] = %s\n",i,array[i]);
}
}
int main()
{
char ** spl = NULL;
int count = 0;
char *str ="abcdef,acccd,eeee,aaaa,e3eeeee,sssss,";
splitStr(str,',',&spl,&count);
printf("count =%d\n",count);
printArray(spl,count);
}
参考一 : 狄泰软件课程
参考二 : 传智扫地僧老师课程
如有侵权:请联系邮箱 aaa@qq.com
推荐阅读