C提高4 多维数组,结构体与二级指针

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C提高4 多维数组,结构体与二级指针相关的知识,希望对你有一定的参考价值。


昨天的试题:原题见昨天作业题

[email protected]:~/high/day03$ cat main.c 
/* 二级指针,绝佳训练题1 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int spitspring(char *buf1,char *c,char **myp,int *total)
{
	char *p_head =  buf1;
	char *p_tail =  buf1;
	int   count = 0;
	while(*p_head != ‘\0‘)
	{
		p_head = strstr(p_head,c);
		if(p_head == NULL)
		{
			break;
		}

		if(p_head - p_tail > 0)
		{
			strncpy(myp[count],p_tail,p_head - p_tail);
			myp[count][p_head - p_tail] = ‘\0‘;
			count ++;
			p_head = p_head+1;
			p_tail = p_head;
		}
	}
	*total = count;
	return 0;
}

int main()
{
	int ret = 0;
	int i = 0;
	char *string = "abcd,efg,accd,2313,3,42,4";
	char *split_char = ",";
	int count = 0;

	//在主函数中手动分配malloc空间,用来存放10个子串
	char **str_arr = NULL;
	str_arr = (char **)malloc(10* sizeof(char *)); //str_arr指针的步长是 char *
	if(str_arr == NULL)
	{
		return -1;
	}
	//为10个子串分别分配30个char的长度空间
	for(i = 0;i<10;i++)
	{
		*(str_arr + i) = (char *)malloc(30 * sizeof(char));
	}

	//调用函数,将处理的结果返回到str_arr中
	ret = spitspring(string,split_char,str_arr,&count);
	if(ret != 0)
	{
		printf("ERROR IN spitspring %d",ret);
		return ret;
	}
	
	//打印输出
	for(i = 0;i<10;i++)
	{
		printf("%s \n",*(str_arr + i));
	}

	//释放空间
	for(i = 0;i<10;i++)
	{
		free(*(str_arr + i) );
	}
	free(str_arr);
	printf("Hello End!\n");
	return ret;

}
[email protected]:~/high/day03$ 
[email protected]:~/high/day03$ 
[email protected]:~/high/day03$ gcc -g -o main main.c  && ./main 
abcd 
efg 
accd 
2313 
3 
42 
 
 
 
Hello End!
[email protected]:~/high/day03$





还是上面这道题,主调函数不分配内存,被调函数返回malloc

[email protected]:~/high/day03$ cat main.c 
/* 二级指针,绝佳训练题1 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char ** spitspring(char *str,char *c,int *total)
{
	//1先求出有多少个子串,count
	char *p_head =  str;//向字符串右跑
	char *p_tail =  str;//
	int   count = 0;
	while(p_head)
	{
		p_head = strstr(p_head,c);
		if(p_head - p_tail > 0)
		{
			count ++;
			p_tail = p_head = p_head+1;
		}
	}
	*total = count;

	//根据子串数目,精确分配个数
	char **str_arr = (char **)malloc(sizeof(char *) * count);
	if(str_arr == NULL)
	{
		return NULL;
	}


	p_head =  str;
	p_tail =  str;
	count = 0;
	while(p_head)
	{
		p_head = strstr(p_head,c);
		if(p_head - p_tail > 0)
		{
			int len = p_head - p_tail +1; //存放字符串的‘\0‘
			*(str_arr + count) = malloc(len * sizeof(char));
			if(*(str_arr + count) == NULL)
			{
				return NULL;
			}

			strncpy(*(str_arr + count),p_tail,p_head - p_tail);
			*(*(str_arr + count) + (p_head - p_tail) ) = ‘\0‘;
			count ++;
			p_head = p_head+1;
			p_tail = p_head;
		}
	}
	return str_arr;
}

int main()
{
	int ret = 0;
	int i = 0;
	char *string = "abcd,efg,";
	char *split_char = ",";
	int count = 0;

	char **str_arr = spitspring(string,split_char,&count);
	if(str_arr == NULL)
	{
		printf("ERROR IN spitspring %d \n",ret);
		return ret;
	}
	
	//打印输出
	for(i = 0;i<count;i++)
	{
		printf("%s \n",*(str_arr + i));
	}

	//释放空间
	for(i = 0;i<count;i++)
	{
		free(*(str_arr + i) );
	}
	free(str_arr);
	return ret;

}
[email protected]:~/high/day03$ 
[email protected]:~/high/day03$ 
[email protected]:~/high/day03$ gcc -g -o main main.c  && ./main 
abcd 
efg 
[email protected]:~/high/day03$




我的练习

技术分享

[email protected]:~/high$ cat my.c  
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
	涉及的知识点:
	两个指针挖字符串
	多级指针内存分配
	多级指针内存分配出错的处理
	多级指针释放内存空间
*/

void free_two_level_pointer(char ***p,int count)
{
	if(p == NULL) return ;
	int i;
	for(i = 0;i<count;i++)//先释放几个子串的空间
	{
		if(*(p + i) != NULL)
		{
			free(*(*(p) + i));//此处相当于数组 第p[i]  行
			*(*(p) + i) = NULL;
		}
	}
	if(*p != NULL)//再释放存放子串数目的空间
	{
		free(*p);
		*p = NULL;
	}
	return ;
}
int splitstr(const char *str/*in*/,const char *split_str/*in*/,char ***str_arr/*out*/,int *count/*in*/)
{
	if(str == NULL)			return -1;
	if(split_str == NULL)		return -2;
	if(str_arr == NULL)		return -3;
	if(count == NULL)		return -4;
	const char *p_head = str;
	const char *p_tail = str;
	int my_count = 0;
	int i =0;
	int ret = 0;

	//1找出子串的个数
	while(p_head = strstr(p_head,split_str))
	{
		p_head += strlen(split_str);;
		my_count++;
	}
	*count = my_count;
	//printf("[]%d \n",*count);

	//创建二维数组的行数,有几个子串就创建几行
	char **my_str_arr = (char **)malloc(sizeof(char *) * my_count);
	if(my_str_arr == NULL)
	{
		ret = -1;
		goto END;
	}
	char **tmp_str_arr  =my_str_arr;//只有当分配成功时才执行
	//这一步非常重要,将申请到的空间置0,为判断下一级指针分配是否成功,埋下伏笔
	memset(tmp_str_arr,0,sizeof(char *) * my_count);

	//给把分割的子串存放起来
	p_head = str;
	p_tail = str;
	my_count = 0;
	while(p_head = strstr(p_head,split_str))
	{
		*(tmp_str_arr + my_count) = (char * )malloc(sizeof(char) * (p_head - p_tail + 1 )); //为‘\0‘分配存储空间
		if(*(tmp_str_arr + my_count) == NULL)
		{
			ret = -2;
			goto END;
		}
		strncpy(*(tmp_str_arr + my_count),p_tail,p_head - p_tail);
		*(*(tmp_str_arr + my_count) + (p_head - p_tail +1))  = ‘\0‘;
		my_count ++;
		p_head += strlen(split_str);;
		p_tail = p_head;
	}
END:
	if(ret != 0)
	{
		//释放堆内存
		free_two_level_pointer(&my_str_arr,*count);
		printf("ERROR in splitstr :%d \n",ret);
		return -1;
	}
	*str_arr = my_str_arr;

	return 0;
}


int main()
{
	int ret = 0;
	int i = 0;
	char *str = "ab123,ad456,qwedc,123,12wsx,";
	char *split_str = ",";
	int count  = 0;
	char **str_arr = NULL;

	//调用这个函数
	ret = splitstr(str,split_str,&str_arr,&count);
	if(ret != 0)
	{
		printf("ERROR in splitstr :%d\n",ret);
		return ret;
	}
	
	//遍历
	for(i = 0;i<count;i++)
	{
		printf("[%d] -> %s \n",i+1,*(str_arr + i));
	}

	//释放堆内存
	free_two_level_pointer(&str_arr,count);
	return ret ;
}
[email protected]:~/high$ gcc -g my.c  && ./a.out 
[1] -> ab123 
[2] -> ad456 
[3] -> qwedc 
[4] -> 123 
[5] -> 12wsx 
[email protected]:~/high$




【数组指针】【数组指针】【数组指针】【数组指针】【数组指针】

数组类型:

数组地址,自定义数组:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
        int a[] = {1,2};                //长度为2
        int b[100] = {1,3};             //长度为100,后面全是0
        int c[200] = {0};               //长度为200,编译器自动全部置0
        memset(c,0,sizeof(c));          //显式重置内存块
        // c是数组的首地址 步长为 4个字节
        // &c是数组的地址,步长为200 *4个字节
        printf("%p  ,%p \n",c,c+1);
        printf("%p  ,%p \n",&c,&c+1);


        typedef int (MyArrayType)[5];   //定义了一个数据类型,数组数据类型
        MyArrayType myArray;            //相当于  int myArray[5];
        int i = 0;
        for (i = 0;i < 5;i++ )
        {
                myArray[i] = i*i;
        }

        for (i = 0;i < 5;i++ )
        {
                printf("%d \n",myArray[i]);
        }
        
        return 0;
}
编译:
[email protected]:~/high$ gcc -g main.c  && ./a.out 
0x7ffd6f70b700  ,0x7ffd6f70b704 
0x7ffd6f70b700  ,0x7ffd6f70ba20 
0 
1 
4 
9 
16


【压死初学者的三座大山】

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义数组指针变量的方法1
//用自定义数组类型 *
int main()
{
        int i = 0;

        //指针数组
        char *arr1[] = {"hehe","haha","123456"};//指针数组,三个指针指向不同的字符串

        //数组的指针
        typedef int (MyArrayType)[5];   //定义了一个数据类型,int [5]数组数据类型
        MyArrayType  arr2;              //相当于  int myArray[5];
        MyArrayType *arr3;              

        int arr4[5];                    //普通数组
        arr3 = &arr4;
        for(i = 0;i<5;i++)
        {
                *((*arr3) + i) = i * i;
        }

        for(i = 0;i<5;i++)
        {
                printf("%d \n",*((*arr3) + i));
        }
        
        
        return 0;
}

编译:
[email protected]:~/high$ gcc -g main.c  && ./a.out 
0 
1 
4 
9 
16




//定义数组指针变量的方法2

//定义声明一个数组指针类型

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义数组指针变量的方法2
//定义声明一个数组指针类型
int main()
{
        int i = 0;
        typedef int (*P_arr)[5];        //申明一种数据类型,相当于二级指针
        P_arr arr1  = NULL;             //告诉编译器,给我分配一个指针变量

        int arr2[5] ;                   //定义了一个普通的数组
        arr1 = &arr2;
        for(i = 0;i<5;i++)
        {
                *((*arr1) + i)  = i * i;
        }

        for(i = 0;i<5;i++)
        {
                printf("%d \n",*((*arr1) + i));
        }
        
        return 0;
}

[email protected]:~/high$ gcc -g main.c  && ./a.out 
0 
1 
4 
9 
16





直接定义数组指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义数组指针变量的方法3
//前两种方法通过类型定义变量  比较麻烦
int main()
{
        int (*p)[5] = 0;        //定义了一个指向数组的 ,数组指针变量
        int arr[5];
        p = &arr;

        int i = 0;
        for(i = 0;i < 5;i++)
        {       
                *((*p) + i) = i * i + i;
        }       
        for(i = 0;i < 5;i++)
        {
                printf("%d \n",*((*p) + i));
        }
        
        return 0;
}
编译:
[email protected]:~/high$ gcc -g main.c && ./a.out 
0 
2 
6 
12 
20




//多维数组的本质推演

//看图

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//多维数组的本质推演
//看图
int main()
{
	int arr1[3][5];
	int i = 0;
	int j = 0;
	
	for(i = 0;i < 3;i++)
	{
		for(j = 0;j < 5;j++)
		{
			arr1[i][j] = i + j;
		}
	}


	for(i = 0;i < 3;i++)
	{
		for(j = 0;j < 5;j++)
		{
			printf("%d\t",arr1[i][j]);
		}
		printf("\n");
	}

	//探索
	printf("%p ,%p ,(跳过了20个字节)\n",arr1,arr1 + 1);
	printf("%p ,%p ,(跳过了60个字节)\n",&arr1,(&arr1) + 1);

	int (*p)[5];//这个指针的步长是5 * int
	p = arr1;
	for(i = 0;i < 3;i++)
	{
		for(j = 0;j < 5;j++)
		{
			printf("%d\t",p[i][j]);
		}
		printf("\n");
	}

	return 0;
}
[email protected]:~/high$ gcc -g main.c && ./a.out 
0	1	2	3	4	
1	2	3	4	5	
2	3	4	5	6	
0x7ffc3f09a490 ,0x7ffc3f09a4a4 ,(跳过了20个字节)
0x7ffc3f09a490 ,0x7ffc3f09a4cc ,(跳过了60个字节)
0	1	2	3	4	
1	2	3	4	5	
2	3	4	5	6	
[email protected]:~/high$




//证明:二维数组做函数形参  退化

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//证明:二维数组做函数形参  退化
void printf_arr(int (*p)[5]) //p的步长的int 5
{
        int i = 0;
        int j = 0;
        for(i = 0;i < 3;i++)
        {
                for(j = 0;j<5;j++)
                {
                        printf("%d ", *(*(p + i) + j) );
                }
        }
        
}

int main()
{
        int arr1[3][5];
        int i = 0;
        int j = 0;
        
        for(i = 0;i < 3;i++)
        {
                for(j = 0;j < 5;j++)
                {
                        arr1[i][j] = i + j;
                }
        }
        printf_arr(arr1);
        return 0;
}
编译:
[email protected]:~/high$ gcc -g main.c && ./a.out 
0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 [email protected]:~/high$ 
[email protected]:~/high$



//证明:二维数组在内存中是线性存储的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//证明:二维数组在内存中是线性存储的
int main()
{
        int arr1[3][5];
        int i = 0;
        int j = 0;
        
        for(i = 0;i < 3;i++)
        {
                for(j = 0;j < 5;j++)
                {
                        arr1[i][j] = i + j;
                }
        }

        int *p = (int *) arr1;
        for(i = 0;i < 3* 5;i++)
        {
                printf("%d ",*(p + i));
        }


        return 0;
}

编译:
[email protected]:~/high$ gcc -g main.c && ./a.out 
0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 [email protected]:~/high$ 
[email protected]:~/high$








多维数组当函数参数,退化为指针的证明:

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//返回关键字所在菜单列表的位置
int searchKeyTable(char* table[],const int size, const char *key,int *pos)
{
	printf("数组大小 %ld \n",sizeof(table)/sizeof(*table));
	printf("这个就可以证明,多维数组当函数参数,退化为一个指针\n");
	return 0;
}


#define DIM(a) (sizeof(a)/sizeof(*a))

int main()
{
	int inum = 0;
	int pos = 0;
	int a[10];
	int i = 0;
	char *c_keyword[] = {
	"while",
	"case",
	"static",
	"do"
	};	
	printf("数组大小 %ld \n",sizeof(c_keyword)/sizeof(*c_keyword));
	searchKeyTable(c_keyword,DIM(c_keyword),"do",&pos);

	return 0;
}
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ gcc -g main.c && ./a.out 
数组大小 4 
数组大小 1 
这个就可以证明,多维数组当函数参数,退化为一个指针
[email protected]:~/high$





【指针数组的应用 】

返回关键字所在菜单列表的位置

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//返回关键字所在菜单列表的位置
int searchKeyTable(char* table[],const int size, const char *key,int *pos)
{
	int rv = 0;
	int i = 0 ;
	int inum = 0;
	if(table == NULL) return -1;  
	if(key == NULL) return -1;  
	if(pos == NULL) return -1;  
	for(i = 0;i<size;i++)
	{
		if(strcmp(key,table[i]) == 0)
		{
			*pos = i;
			return rv;
		}
	}
	if(i == size)
	{
		*pos  = -1;
	}

	return 0;
}


#define DIM(a) (sizeof(a)/sizeof(*a))

int main()
{
	int inum = 0;
	int pos = 0;
	int a[10];
	int i = 0;
	char *c_keyword[] = {
	"while",
	"case",
	"static",
	"do"
	};	
	searchKeyTable(c_keyword,DIM(c_keyword),"do",&pos);
	printf("%d \n",pos);

	return 0;
}
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ gcc -g main.c && ./a.out 
3 
[email protected]:~/high


指针数组的命令行模式

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int num,char **str1,char **str2) //操作系统在调用之前,为参数的存储提供空间
{
	int i = 0;
	for(i = 0;i<num;i++)
	{
		printf("%s \n",str1[i]);
	}
	printf("--------------------------\n");

	for(i = 0;str2[i] != NULL;i++)
	{
		printf("%s \n",str2[i]);
	}
	return 0;
}
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ gcc -g main.c && ./a.out 123 345
./a.out 
123 
345 


--------------------------
XDG_SESSION_ID=2 
TERM=xterm 
SHELL=/bin/bash 
SSH_CLIENT=10.11.12.1 9479 22 
SSH_TTY=/dev/pts/1 
USER=chunli 
LD_LIBRARY_PATH=:. 
MAIL=/var/mail/chunli 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games 
PWD=/home/chunli/high 
LANG=en_US.UTF-8 
SHLVL=1 
HOME=/home/chunli 
LANGUAGE=en_US:en 
LOGNAME=chunli 
SSH_CONNECTION=10.11.12.1 9479 10.11.12.4 22 
XDG_RUNTIME_DIR=/run/user/1000 
OLDPWD=/home/chunli 
_=./a.out 
[email protected]:~/high$




具有自我结束能力的指针数组

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//具有自我结束能力的指针数组
int main()
{
        int i = 0;
        char *str_arr[] = {
        "1234",
        "5678",
        "1357",
        "2468",
        ‘\0‘
        };
        while( *(str_arr + i) )
        {
                printf("%s \n",*(str_arr + i));
                i++;
        }
}
编译:
[email protected]:~/high$ gcc -g main.c && ./a.out
1234 
5678 
1357 
2468



更深层次:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//具有自我结束能力的指针数组
int main()
{
        int i = 0;
        char *str_arr[] = {
        "1234",
        "5678",
        "1357",
        "2468",
        ‘\0‘,   // ‘\0‘ 0 NULL 都是一样的效果,都是字符结束标志
        0,      // ‘\0‘ 0 NULL 都是一样的效果,都是字符结束标志
        NULL    // ‘\0‘ 0 NULL 都是一样的效果,都是字符结束标志
        };
        while( *(str_arr + i) )
        {
                printf("%s \n",*(str_arr + i));
                i++;
        }
}


--------------结构体------

【结构体 提高】

【1】结构体类型的定义

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义了一个数据类型。固定大小内存块的别名,此时还没有分配内存
struct Teacher
{
        char name[64];
        int age;
        int id;
};

int main()
{
        struct Teacher t1;      //告诉编译器,给我分配内存
        return 0;
}
//定义了一个数据类型。固定大小内存块的别名,此时还没有分配内存
typedef struct Teacher          //别名  
{
        char name[64];
        int age;
        int id;
} struct_teacher;

int main()
{
        struct_teacher t1;      //使用typedef之后,可以省略struct 直接这样定义
        return 0;
}




结构体变量的定义3中方法:

1,直接定义

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//结构体定义变量,有3种


typedef struct Teacher          
{
        char name[64];
        int age;
        int id;
} struct_teacher;

int main()
{
        struct_teacher t1; //定义结构体方法1
        return 0;
}





2,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//结构体定义变量,有3种

//2 定义类型的同时,定义变量
struct Teacher
{
        char name[64];
        int age;
        int id;
} teacher1,teacher2;

int main()
{
        return 0;
}



3,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//结构体定义变量,有3种

//2 定义类型的同时,定义隐式变量
struct 
{
        char name[64];
        int age;
        int id;
} teacher1,teacher2;

int main()
{
        return 0;
}



【初始化变量的3中方法】

1,定义变量的时候初始化;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
        char name[64];
        int age;
        int id;
} s_teacher;

int main()
{
        s_teacher t1 = {"chunli",22,007};
        return 0;
}



2,定义结构体时就定义两个变量

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
        char name[64];
        int age;
        int id;
}
teacher1 = {"chunli",22,7},
teacher2 = {"chunli",22,7};

int main()
{
        return 0;
}



3,匿名结构体

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct 
{
        char name[64];
        int age;
        int id;
}
teacher1 = {"chunli",22,7},
teacher2 = {"chunli",22,7};

int main()
{
        return 0;
}


结构体变量的引用:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
        char name[64];
        int age;
        int id;
};

int main()
{
        struct Teacher t1;
        struct Teacher t2;
        t1.age = 12;            //.点是寻址操作,计算age相对于t1大变量的偏移量
        t1.id = 1;
        strcpy(t1.name,"chunli");

        printf("%s,%d,%d \n",t1.name,t1.age,t1.id);
        return 0;
}
编译:
[email protected]:~/high$ gcc -g main.c && ./a.out
chunli,12,1




结构体指针的引用:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
        char name[64];
        int age;
        int id;
};

int main()
{
        struct Teacher t1;
        struct Teacher t2;
        t1.age = 12;            //.点是寻址操作,计算age相对于t1大变量的偏移量,计算过程在CPU,不在内存
        t1.id = 1;
        strcpy(t1.name,"chunli");

        //通过指针的方式操作内存
        struct Teacher *p;
        p = &t1;
        p -> id = 2;            //.点是寻址操作,计算age相对于t1大变量的偏移量,计算过程在CPU,不在内存
        printf("%s,%d,%d \n",t1.name,t1.age,t1.id);
        printf("%s,%d,%d \n",p -> name,p -> age,p -> id);
        return 0;
}
编译:
[email protected]:~/high$ gcc -g main.c && ./a.out
chunli,12,2 
chunli,12,2



结构体浅拷贝:

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
	char name[64];
	int age;
	int id;
};

//浅拷贝
void my_copy(struct Teacher *to,struct Teacher *from)
{
	*to = *from;
}

int main()
{
	struct Teacher t1 = {"chunli",2,22};
	struct Teacher t2;
	my_copy(&t2,&t1);
	printf("%s,%d,%d \n",t2.name,t2.age,t2.id);
	return 0;
}
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ gcc -g main.c && ./a.out
chunli,2,22 
[email protected]:~/high$




结构体在栈空间:按照年龄排序:

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
	char name[64];
	int age;
	int id;
};

void printf_teacher(struct Teacher *p,int num)
{
	while(num--)
	{
		printf("%d \n",p[num-1].age);
	}

}

void sort_teacher(struct Teacher *p,int num)
{
	int i = 0;
	int j = 0;
	struct Teacher tmp;
	for(i = 0;i<num; i++)
	{
		for(j = i+1;j<num;j++)
		if(p[i].age > p[j].age )
		{
			tmp  = p[i];
			p[i] = p[j];
			p[j] = tmp;			
		}
	}
}

int main()
{
	int 	i = 0;
	struct Teacher teacher_arr[3];
	for(i = 0;i < 3;i++)
	{
		printf("[%d]Enter age: ",i+1);
		scanf("%d",&teacher_arr[i].age);
	}
	sort_teacher(teacher_arr,3);
	for(i = 0;i < 3;i++)
	{
		printf("age = %d \n",teacher_arr[i].age);
	}

	return 0;
}
[email protected]:~/high$ gcc -g main.c && ./a.out
[1]Enter age: 12
[2]Enter age: 11
[3]Enter age: 23
age = 11 
age = 12 
age = 23 
[email protected]:~/high$




结构体指针做函数参数基本应用,内存分配,释放内存

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
	char name[64];
	int age;
	int id;
};

struct Teacher *create_teacher(int num)
{
	struct Teacher *p = (struct Teacher *)malloc(sizeof(struct Teacher ) * num);
	if(p == NULL)
	{
		return NULL;
	}
}

void printf_teacher(struct Teacher *p,int num)
{
	while(num--)
	{
		printf("%d \n",p[num].age);
	}

}

void free_teacher(struct Teacher *p,int num)
{
	while(num--)
	{
		if(p+num != NULL)
		{
			free(p + num);
		}
	}
	

}

void sort_teacher(struct Teacher *p,int num)
{
	if(p == NULL)
	{
		return ;
	}
	int i = 0;
	int j = 0;
	struct Teacher tmp;
	for(i = 0;i<num; i++)
	{
		for(j = i+1;j<num;j++)
		if(p[i].age <  p[j].age )
		{
			tmp  = p[i];
			p[i] = p[j];
			p[j] = tmp;			
		}
	}
}

int main()
{
	int 	i = 0;
	struct Teacher *teacher_arr = create_teacher(3);;
	for(i = 0;i < 3;i++)
	{
		printf("[%d]Enter age: ",i+1);
		scanf("%d",&(teacher_arr[i]).age);
		//printf("%d \n",teacher_arr[i].age);
	}
	sort_teacher(teacher_arr,3);
	printf_teacher(teacher_arr,3);

	return 0;
}
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ gcc -g main.c && ./a.out
[1]Enter age: 99   
[2]Enter age: 11
[3]Enter age: 66
11 
66 
99


结构体指针做函数参数,进阶

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
	char name[64];
	int age;
	int id;
};

int create_teacher( struct Teacher **pt,int num)
{
	int ret = 0;
	struct Teacher *p = NULL;
	p =  (struct Teacher *)malloc(sizeof(struct Teacher ) * num);
	if(p == NULL)
	{
		return -1;
	}
	*pt = p;
	return ret;
}

void printf_teacher(struct Teacher *p,int num)
{
	while(num--)
	{
		printf("%d \n",p[num].age);
	}

}

void free_teacher(struct Teacher **p,int num)
{
	if(*p != NULL)
	{
		free(*p);
		*p = NULL;
	}
	

}

void sort_teacher(struct Teacher *p,int num)
{
	if(p == NULL)
	{
		return ;
	}
	int i = 0;
	int j = 0;
	struct Teacher tmp;
	for(i = 0;i<num; i++)
	{
		for(j = i+1;j<num;j++)
		if(p[i].age <  p[j].age )
		{
			tmp  = p[i];
			p[i] = p[j];
			p[j] = tmp;			
		}
	}
}

int main()
{
	int 	i = 0;
	int 	ret = 0;
	int 	num = 3;
	struct Teacher *teacher_arr = NULL;
	ret  = create_teacher(&teacher_arr,num);;
	if(ret != 0)
	{
		printf("ERROR IN create_teacher %d \n",ret);
		return ret;	
	}

	for(i = 0;i < num;i++)
	{
		printf("[%d]Enter age: ",i+1);
		scanf("%d",&(teacher_arr[i]).age);
	}

	sort_teacher(teacher_arr,num);
	printf_teacher(teacher_arr,num);
	free_teacher(&teacher_arr,num);

	return 0;
}
[email protected]:~/high$ gcc -g main.c && ./a.out
[1]Enter age: 33
[2]Enter age: 22
[3]Enter age: 88
22 
33 
88 
[email protected]:~/high$



结构体套一级指针:

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher
{
	char name[64];
	char *alias;
	int age;
	int id;
};

int create_teacher( struct Teacher **pt,int num)
{
	int ret = 0;
	int i = 0;
	struct Teacher *p = NULL;
	p =  (struct Teacher *)malloc(sizeof(struct Teacher ) * num);
	if(p == NULL)
	{
		return -1;
	}
	memset(p,0,sizeof(struct Teacher) * num);

	for(i = 0;i<num;i++)		//为每一个节点分配内存空间
	{
		p[i].alias = (char *)malloc( 100);
		if(p[i].alias == NULL)
		{
			return -2;
		}
		memset(p[i].alias,0,100);
	}

	*pt = p;
	return ret;
}

void printf_teacher(struct Teacher *p,int num)
{
	while(num--)
	{
		printf("%d \n",p[num].age);
	}

}

void free_teacher(struct Teacher *p,int num)
{
	if(p == NULL) return ;
	int i = 0;
	for(i = 0;i<num;i++)
	{
		if(p[i].alias != NULL)
		{
			free(p[i].alias);
			p[i].alias = NULL;
		}
	}
	if(p != NULL)
	{
		free(p);
		p = NULL;
	}
}

void sort_teacher(struct Teacher *p,int num)
{
	if(p == NULL)
	{
		return ;
	}
	int i = 0;
	int j = 0;
	struct Teacher tmp;
	for(i = 0;i<num; i++)
	{
		for(j = i+1;j<num;j++)
		if(p[i].age <  p[j].age )
		{
			tmp  = p[i];
			p[i] = p[j];
			p[j] = tmp;			
		}
	}
}

int main()
{
	int 	i = 0;
	int 	ret = 0;
	int 	num = 3;
	struct Teacher *teacher_arr = NULL;
	ret  = create_teacher(&teacher_arr,num);;
	if(ret != 0)
	{
		printf("ERROR IN create_teacher %d \n",ret);
		return ret;	
	}

	for(i = 0;i < num;i++)
	{
		printf("\n[%d]Enter age: ",i+1);
		scanf("%d",&(teacher_arr[i]).age);

		printf("\n[%d]Enter name: ",i+1);
		scanf("%s",teacher_arr[i].name);

		printf("\n[%d]Enter alias: ",i+1);
		scanf("%s",teacher_arr[i].alias);
	}

	sort_teacher(teacher_arr,num);
	printf_teacher(teacher_arr,num);
	free_teacher(teacher_arr,num);

	return 0;
}
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$ gcc -g -Wall main.c && ./a.out

[1]Enter age: 11

[1]Enter name: 11

[1]Enter alias: 11

[2]Enter age: 22

[2]Enter name: 22

[2]Enter alias: 
22

[3]Enter age: 33

[3]Enter name: 33

[3]Enter alias: 33
11 
22 
33 
[email protected]:~/high$



教师结构体 二级指针训练

1,在堆中分配结构体空间

2,每个老师有一个别名,存在堆中

3,每个老师带领3名学生,学生的名字分别存在堆中

4,初始化每个老师与学生的信息

5,按照老师的名字,把结构体排序

6,打印出全部结构体信息

7,堆中结构体释放

[email protected]:~/high$ cat my_struct.c 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

/*
	堆内存分配好习惯:
	1,执行分配
	2,判断分配是否成功
	3,内存清零
	4,分配异常处理
*/

typedef struct Teacher
{
	int age;
	char name[60];
	char *alias_name;
	char **students_name;
	
} master;

void free_master(master *p_head,int teacher_num,int student_num)
{

	int i = 0;
	int j = 0;
	if(p_head == NULL)
	{
		return ;
	}
	for(i = 0;i<teacher_num;i++)
	{
		if( p_head[i].alias_name != NULL)
		{
			free(p_head[i].alias_name);			//释放别名一级指针
			p_head[i].alias_name = NULL;
		}

		for(j=0;j<student_num;j++)
		{
			if(p_head[i].students_name[j] == NULL)
			{
				free(p_head[i].students_name[j]);	//释放学生姓名二级指针的第二维
				p_head[i].students_name[j] = NULL;
			}
			
		}
		if(p_head[i].students_name != NULL)
		{
			free(p_head[i].students_name);		//释放学生个数二级指针的第一维
			p_head[i].students_name = NULL;
		}
	}
	if(p_head != NULL)
	{
		p_head = NULL;
	}
}

int create_master(master **p_head,int teacher_num,int student_num)
{
	int ret = 0;
	int i = 0;
	int j = 0;
	if(p_head == NULL)
	{
		return -1;
	}

	master *master_head = (master *)malloc(teacher_num * sizeof(master));//创建teacher_num个老师的空间
	if(master_head == NULL)
	{
		return -2;
	}
	memset(master_head,0,teacher_num * sizeof(master));

	for(i = 0;i<teacher_num;i++)		//有几个老师,
	{
		master_head[i].alias_name = (char *)malloc(100 * sizeof(char));
		if(master_head[i].alias_name == NULL)
		{
			return -3;
		}
		//memset((master_head +i ,0,100 * sizeof(char));  这儿不能这么写,害我查bug好久

		char **my_students = (char **)malloc(student_num * sizeof(char *));//每个导师带领student_num 名学生
		if(my_students == NULL)
		{
			return -4;
		}
		memset(my_students,0,student_num * sizeof(char *));
		for(j = 0;j<student_num;j++)
		{
			my_students[j] = (char *)malloc(100);
			if(my_students[j] == NULL)
			{
				return -5;
			}
		}
		master_head[i].students_name = my_students;

	}
	*p_head = master_head;
	return ret;
}

void sort_teacher(master *p,int num)
{
	int i = 0;
	int j = 0;
	for(i = 0;i<num;i++)
	{
		for(j=i+1;j<num;j++)
		{
			if(strcmp(p[i].name,p[j].name) >0)
			{
				master tmp = p[i];
				p[i] = p[j];
				p[j] = tmp;
			}
		}
	}
}

void printf_teacher(master *p,int teacher_num,int student_num)
{
	int i =0;
	int j =0;
	printf("------------------------\n");
	for(i = 0;i<teacher_num;i++)
	{
		printf("[%d] %d,%s,%s -->",i+1,p[i].age,p[i].name,p[i].alias_name);
		for(j = 0;j<student_num;j++)
		{
			printf("%s ",p[i].students_name[j]);
		}
		printf("\n");
	}
}



int main()
{
	int ret = 0;
	int i = 0;
	int j = 0;
	int teacher_num = 3;
	int student_num = 3;
	master *p_head = NULL;
	ret = create_master(&p_head,teacher_num,student_num);
	if(ret != 0)
	{
		return -1;
	}



	for(i=0;i<teacher_num;i++)
	{
		printf("[%d]Enter age ",i+1);	scanf("%d",&(p_head[i].age));
		printf("[%d]Enter name ",i+1);	scanf("%s",p_head[i].name);
		printf("[%d]Enter alias ",i+1);	scanf("%s",p_head[i].alias_name);
		for(j = 0;j<student_num;j++)
			{
				printf("[%d][%d]Enter student_name  ",i+1,j+1);
				scanf("%s",p_head[i].students_name[j]);
			}
	} 
	sort_teacher(p_head,teacher_num);
	printf_teacher(p_head,teacher_num,student_num);
	free_master(p_head,teacher_num,student_num);
	
	return 0;
}
[email protected]:~/high$


[email protected]:~/high$ gcc -g -Wall my_struct.c  && ./a.out 
[1]Enter age 32
[1]Enter name chunli
[1]Enter alias chunli-1 
[1][1]Enter student_name  chunli-2
[1][2]Enter student_name  chunli-3
[1][3]Enter student_name  chunli-4
[2]Enter age 11
[2]Enter name kangkang
[2]Enter alias kangkang-1
[2][1]Enter student_name  kangkang-1^H2
[2][2]Enter student_name  kangkang-2
[2][3]Enter student_name  kangkang-3
[3]Enter age 99
[3]Enter name zhangsanfeng
[3]Enter alias zhangsanfeng-1
[3][1]Enter student_name  zhangsanfeng-2
[3][2]Enter student_name  zhangsanfeng-3
[3][3]Enter student_name  zhangsanfeng-4
------------------------
[1] 32,chunli,chunli-1 -->chunli-2 chunli-3 chunli-4 
[2] 11,kangkang,kangkang-1 -->kangkang-2 kangkang-2 kangkang-3 
[3] 99,zhangsanfeng,zhangsanfeng-1 -->zhangsanfeng-2 zhangsanfeng-3 zhangsanfeng-4 
[email protected]:~/high$


本文出自 “魂斗罗” 博客,请务必保留此出处http://990487026.blog.51cto.com/10133282/1790842

以上是关于C提高4 多维数组,结构体与二级指针的主要内容,如果未能解决你的问题,请参考以下文章

C 语言数组 ( 多维数组本质 | 步长角度 理解 多维数组本质 )

单片机C语言 -- 结构体与指针在编程中的应用

C语言如何给指针分配内存?

结构体与共用体

C 语言结构体 ( 结构体中嵌套二级指针 | 为 结构体内的二级指针成员 分配内存 | 释放 结构体内的二级指针成员 内存 )

结构体与共用体