结构体
结构体定义与声明
一般形式:
struct Student
{
int id;
float score;
char name[20];
};
通过struct关键字来声明结构体变量
结构体变量的操作
访问结构体成员使用 .
运算符,如 student.id
。
结构体变量可以通过点运算符直接访问,也可以通过指针访问,使用箭头运算符(->
)。
结构体初始化
struct Student s1 = {.id = 1,.score = 95.5,.name = "zhangsan"};
struct Student s2 = {.id = 2,.score = 97,.name = "lisi"};
struct Student a[] = {{1, 95.5, "zhangsan"},
{2, 97,"lisi"},
{3, 96,"wanger"}};
结构体对齐
1、结构体按照其最长成员大小对齐,意味着最终的大小必须是最长成员大小的整数倍;
2、结构体成员按照结构体成员声明先后次序依次存放,并且每个成员的首字节放置的位置必须
能够整除成员的字节数;
3、如果结构体某个成员的字节数大于CPU的字节数,则最长按照CPU的字节数对齐;
4、用预处理命令#pragma pack(n) 可以强制编译器按照指定的n来对齐,合法的n的数值分别是1、2、4、8、16。
结构体传参
1、用结构体变量的成员作参数。例如,用stu[1].num或stu[2].name作函数实参,将实参值传给
行参。用法和用普通变量作实参是一样的,属于“值传递”方式。应当注意实参与形参的类型保持
一致。
2、用结构体变量作实参。用结构体变量作实参时,采取的也是“值传递”的方式,将结构体变量
所占的内存单元的内容全部顺序传递给形参,形参也必须是同类型的结构体变量。在函数调用期
间形参也要占用内存单元。这种传递方式在空间和时间上开销较大,如果结构体的规模很大时
,开销是很可观的。此外,由于采用值传递方式,如果在执行被调用函数期间改变了形参(也是
结构体变量)的值,该值不能返回主调函数,这往往造成使用上的不便。因此一般较少用这种方法
3、用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。
函数
struct Student
{
int id;
float score;
char name[20];
};
//遍历
void printStudent(struct Student *s)
{
printf("%d %f %s\n",s->id,s->score,s->name);
}
//数组遍历
void printStudents(struct Student *s,int len)
{
int i;
for(i = 0;i < len;++i)
{
printStudent(s + i);
}
}
//交换
void swap(struct Student *s1,struct Student *s2)
{
struct Student t;
t = *s1;
*s1 = *s2;
*s2 = t;
}
//逆序
void reveser(struct Student *a,int len)
{
int i;
for(i = 0;i < len / 2;++i)
{
struct Student t;
t = a[i];
a[i] = a[len - i - 1];
a[len - i - 1] = t;
swap(a + i,a + len - i - 1);
}
}
//快排
int scorecmp(void *p1,void *p2)
{
struct Student *q1 = (struct Student *)p1;
struct Student *q2 = (struct Student *)p2;
if(q1->score > q2->score)
{
return 1;
}
else if(q1->score < q2->score)
{
return -1;
}
else
{
return 0;
}
}
//按名字大小排序
int namecmp(const void *p1,const void *p2)
{
struct Student *q1 = (struct Student *)p1;
struct Student *q2 = (struct Student *)p2;
return strcmp(q1->name,q2->name);
}
//按分数大小排序
void sortByScore(struct Student *a,int len)
{
int i,j;
for(i = 0;i < len - 1;++i)
{
for(j = i + 1;j < len;++j)
{
if(a[i].score > a[j].score)
{
swap(a + i,a + j);
}
}
}
}
int main()
{
struct Student s1 = {.id = 1,.score = 95.5,.name = "zhangsan"};
struct Student s2 = {.id = 2,.score = 97,.name = "lisi"};
struct Student a[] = {{1, 95.5, "zhangsan"},
{2, 97,"lisi"},
{3, 96,"wanger"}};
int len = sizeof(a) / sizeof(a[0]);
qsort(a,len,sizeof(a[0]),namecmp);
printStudents(a,len);
return 0;
}
链表
头插算法
struct Node
{
int data;
struct Node *next;
};
void push_front(struct Node *pHead,int n)
{
struct Node *pNew = malloc(sizeof(struct Node));
pNew->next = pHead->next;
pHead->next = pNew;
pNew->data = n;
}
//遍历
void printfList(struct Node *pHead)
{
struct Node *p = pHead->next;
while(p != NULL)
{
printf("%d\n",p->data);
p = p->next;
}
}
//有效个数
void size(struct Node *pHead,int *sum)
{
struct Node *p = pHead->next;
while(p != NULL)
{
*sum += 1;
p = p->next;
}
}
//是否空链表
int isEmpty(struct Node *pHead)
{
//return size(pHead) == 0;
return pHead->next == NULL;
}
int main()
{
struct Node head = {0,NULL};
push_front(&head,1);
push_front(&head,2);
push_front(&head,3);
push_front(&head,4);
printfList(&head);
int sum;
size(&head,&sum);
printf("%d\n",sum);
return 0;
}