结构体
一.对结构体进行打印
struct Student
{
char s_id[10];
char s_name[10];
char s_sex[8];
int s_age;
};
//void Printf_Student(struct Student stud [10], //int n)**等价,占用四个字节**
void Printf_Student(struct Student* stud, int n)
{
assert(stud != NULL);
printf("%10s %10s %8s %5d\n","id","name","sex","age");
for(int i=0;i<n;i++)
{
//方法一
printf("%10s %10s %8s %5d\n", stud[i].s_id, stud[i].s_name, stud[i].s_sex, stud[i].s_age);//(*(stud+1))
//方法二 //printf("%d %c %c %c\n",//方法三 (*(stud+i)).s_id, stud->.s_name, stud->s_sex, stud->s_age)
//stud=stud+1;排序,按年龄,按姓名
}
printf("\n");
}
int main()
{
struct Student studx[10] = {
{"0901","yhping","man",22},
{"0901","yhping","man",23},
{"0901","yhping","man",24},
{"0901","yhping","man",25},
{"0901","yhping","man",26},
{"0901","yhping","man",27},
{"0901","yhping","man",28},
{"0901","yhping","man",29},
};
Printf_Student(studx, 8);
return 0;
}
二.结构体的空间开辟
笔试结构体开辟字节考察
2.1 字节开辟
struct Student
{
const char* name;
int age;
};
struct Student s1;
struct Student s2 = { "zjhing",12 };
int main()
{
printf("s1:%d\n", sizeof(s1));//8
printf("s2:%d\n", sizeof(s2));//8
return 0;
}
2.2 联合体
联合体(共用体)
联合体(union)与结构体(struct)有一 些相似之处。 但两者有本质上的不同。在结构体中,各成员有各自的内存空间。而在联合体中,各成员共享同一段内存空间,一个联合变量的长度等于各成员中最长的长度。
应该说明的是这里所谓的共享不是指把多个成员同时装入一个联合变量内,而是指该联合变量可被赋予任一成员值但每次只能赋一种值, 赋入新值则冲去旧值。
一个联合体类型必须经过定义之后,才能使用它,才能把一个变 量声明定义为该联合体类型。
union Node
{
char a;
char b;//a和b在同一空间,地址一样
short sx;
};
int main()
{
union Node x;
x.sx = 0x0001;
if (x.b == 1)
{
printf("x");
}
else
{
printf("d");
}
}
2.3 哑元结构
不论是结构体还是联合体都没有名字
类型不开辟空间,此时Struct Node只有一字节空间。
三. 三个函数
3.1
int main()
{
int a = 10, b = 20;
char buff[20];
//把数字转换为字符串
sprintf_s(buff, 20, "a = %d b = %d\n", a, b);//格式化
float ft = 12.25f;
sprintf_s(buff, 20, "%.2f", ft);
fprintf(stdout, "a = %d b = %d \n", a, b);
//stdout 标准输出设备
return 0;
}
3.2 把整形转化为字符串
方法一:
void Unit_To_Str(char* buff, unsigned int ip)
{
assert(buff != NULL);
unsigned char x;
char str[10];
for (int i = 0; i < sizeof(unsigned int); i++)
{
x = ip & 0x000000FF;
ip = ip >> 8;
_itoa_s(x, str, 10);//
}
int a = 12;
printf("%d %o %x\n", a, a, a);//调动上边的函数
//此方法将倒序将转换后的结果拷入Buff中,不建议使用
}
int main()
{
char buff[20];
unsigned int ip = 234532464;
Unit_To_Str(buff, ip);
return 0;
}
方法二:简洁
union IPNode
{
unsigned int addr;
struct
{
unsigned char s1;
unsigned char s2;
unsigned char s3;
unsigned char s4;
};
};
void Unit_To_Str(char* buff,int len, unsigned int ip)
{
assert(buff != NULL);
IPNode x;
x.addr = ip;
sprintf_s(buff,len,"%d.%d.%d.%d", x.s4, x.s3, x.s2, x.s1);
}
int main()
{
char buff[20];
unsigned int ip = 2148205343;
Unit_To_Str(buff,20,ip);
return 0;
}
四.求偏移量
struct Node
{
short sx;
char str[3];
double dx;
char strb[7];
int age;
long int num;
};
int main()
{
Node x;
int dist = (int)((char*)&x.dx - (char*)&x);
printf("%d\n", dist);
return 0;
}
五.动态内存分配函数
C语言中动态内存管理的有四个函数:malloc,calloc,realloc,free,都需要引用stdio.h或malloc.h文件。
重点一
malloc向堆区申请一块指定大小的连续内存空间。
void *malloc(size_t,size);申请的是字节的个数,申请完成之后必须判空。
返回的是无类型指针,所以必须对返回值强转。
若分配成功,则返回为任何拥有基础对齐的对象类型指针。
*如何知道free多少字节空间
有上越界标记(四字节)和下越界标记(四字节)
上越界标记上还有28字节
重点二
示例一:动态内存分配·打家劫舍
int MAX_INT(int a, int b)
{
return a > b ? a : b;
}
int Rob(int* nums, int n)
{
if (nums == NULL || n == 0)return 0;
int* dp = (int*)malloc(sizeof(int) * n);
if (dp == NULL)return -1;
for (int i = 0; i < n; i++)dp[i] = 0;
dp[0] = nums[0];
dp[1] = nums[0] > nums[1] ? nums[0] : nums[1];
for (int i = 2; i < n; i++)
{
dp[i] = MAX_INT(dp[i - 1], dp[i - 2] + nums[i]);
}
int max = dp[n-1];
free(dp);
dp = NULL;
return max;
}
int main()
{
int nums[] = { 2,7,9,3,1 };
int n = sizeof(nums) / sizeof(nums[0]);
int maxv = Rob(nums, n);
printf("%d", maxv);
return 0;
}
不采用动态分配
int MAX_INT(int a, int b)
{
return a > b ? a : b;
}
int MaxFob(int *nums,int n)
{
int cur=nums[0];//i-1
int pre=0;//i-2
for(int i=1;i<n;i++)
{
int tmp = MAX_INT(cur, pre + nums[i]);
pre=cur;
cur=tmp;
}
return cur;
}
示例二:求斐波那契数列的第n个数
int fun(int n)
{
if (n < 0)
return -1;
int* dp = (int*)malloc(sizeof(int) * (n + 1));
if (n == 1 || n == 2)return 1;
dp[1] = 1, dp[2] = 1;
for (int i = 3; i <= n; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
}
int max=dp[n];
free(dp);
dp=NULL;
return max;
}
int main()
{
int a=10;
int max=fun(10);
printf("%d", max)
};
示例三:机器人的走法
int UniquePath(int** ar, int row, int col)
{
assert(ar != NULL);
for (int i = 0; i < col; i++)ar[0][i] = 1;//先置一
for (int i = 0; i < row; i++)ar[i][0] = 1;
for (int i = 1; i < row; i++)
{
for (int j = 1; j < col; j++)
{
ar[i][j] = ar[i][j - 1] + ar[i - 1][j];
}
}
int max= ar[row - 1][col - 1];
return max;
}
int main()
{
int row,col;
scanf_s("%d %d", &row, &col);
int** ar = (int**)malloc(sizeof(int*)*row);
for (int i = 0; i < row; i++)
{
ar[i] = (int*)malloc(sizeof(int) * col);
}
int num=UniquePath(ar,row,col);
printf("%d", num);
for (int i = 0; i < row; i++)
{
free(ar[i]);
ar[i] = NULL;
}
free(ar);
ar = NULL;
return 0;
}
六.动态开辟二维数组
一.采用二级指针开辟
int** GetTwo(int** s, int row, int col)
{
s = (int**)malloc(sizeof(int*) * row);
if (s == NULL)exit(1);
for (int i = 0; i < row; i++)
{
s[i] = (int*)malloc(sizeof(int) * col);
if (s[i] == NULL)exit(1);
}
return s;
}
void Printf(int** s, int row, int col)
{
assert(s != NULL);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
s[i][j] = rand() % 100 + 1;//*(*(s+i) + j);
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", *(*(s + i) + j));
}
printf("\n");
}
}
void Free(int** s, int row, int col)
{
assert(s != NULL);
for (int i = 0; i < row; i++)
{
free (s[i]);
}
free(s);
}
int main()
{
int** s = NULL;
int row, col;
scanf_s("%d %d", &row, &col);
s=GetTwo(s, row, col);
Printf(s, row, col);
Free(s, row, col);
二.采用结构体开辟
typedef int ElemType;
struct Array2
{
ElemType* data;
int row;
int col;
};
void Init_Ar(struct Array2 *br, int row, int col)
//void Init_Ar(struct Array2& br, int row, int col)//引用不用判空值
{
//br.row=row;
assert(br != NULL);
br->row = row;
br->col = col;
(*br).data=(ElemType*)malloc(sizeof(ElemType)*row * col);
if (((*br).data) == NULL)exit(1);
for (int i = 0; i < row * col; i++)
{
br->data[i] = i + 1;
}
}
void Destory_Ar(struct Array2 *br)
{
assert(br!=NULL);
free(par.data);
par.data=NULL;
par.row=par.col=0;
}
void SetItem(struct Array2& par, int r, int c, ElemType val)
{
assert(r < par.row&& c < par.col);
par.data[r * par.col + c] = val;
}
ElemType GetItem(struct Array2* br,int i, int j)
//void GetItem(struct Array2& br, int row, int col)
{
assert(br != NULL);
//Init_Ar(br, row, col);
//return br->data[i * col + j];
if (i >= br->row || j >= br->col);
return br->data[i * br->col + j];
//else return 0;
}
void Printf(struct Array2* br, int row, int col)
{
assert(br != NULL);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", (*br).data[i * col + j]);
}
printf("\n");
}
}
int main()
{
Array2 ar;
int row, col;
scanf_s("%d %d", &row, &col);
Init_Ar(&ar, row, col);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
SetItem(ar, i, j, i + j);
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d\n", GetItem(ar, i, j));
}
printf("\n");
}
printf("\n");
Printf(&ar, row, col);
Destory_Ar(ar);
return 0;
}
三.动态开辟多维数组
typedef int ElemType;
struct Arrayn
{
ElemType* data;
int* index;
int n;
};
七.数据类型概要
//1000 0000 符号位 数值位
//int mid=(right-lift)/2+left
//两个数字进行比较,类型必须转化一致
//计算机中数值是以补码存放的,所有运算都是以加法为基础的,进位去除
//类型强转本质是扩充符号位全0或全1,有符号数扩充1,无符号数扩充0(不改变符号位,不改变数值范围)范围小的-》范围大的
int main()
{
//sizeof(int)计算出来的是无符号数4U
for (int i = -1; i < sizeof(int); i++)
{
printf("%d", i)
;
}
}