欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(四)C 语言之指针专题二

程序员文章站 2024-01-03 08:54:04
...

1.1 1 理解指针必须和内存四区概念相结合
1.1.1 理论

  1. 主调函数 被调函数
    a)主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
    b)被调用函数只能返回堆区、全局数据
  2. 内存分配方式
    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 理论部分
(四)C 语言之指针专题二
1.3 一级指针的典型用法

1.3.1字符串
1.3.1.1 字符串

  • C语言中的字符串是以零结尾的字符串
  • 在C语言中没有字符串类型,通过字符数组模拟字符串
  • 字符串的内存分配方式 : 堆,栈,全局区(重要

1.3.1.2实例

  1. 字符串和字符数组
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;
}

(四)C 语言之指针专题二

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);
}

(四)C 语言之指针专题二

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 二级指针三种内存模型内存图

(四)C 语言之指针专题二

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

相关标签: C语言

上一篇:

下一篇: