本人编程萌新,见解仅供参考。
结构和其他数据形式
结构变量的建立、声明及初始化(链接)
建立
定义结构体前的准备阶段,此时应明确结构体中应含有的变量种类及数量。
声明
申明结构体需要使用struct
语句(与int
、float
相似但不同),声明样例如下:
/* 声明样例1 */
struct tag {
member-list
member-list
member-list
...
} variable-list ;
/* 声明样例2 */
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
样例1中结构体tag
包含多个变量,定义tag
后其中含有多个成员。
样例2中结构体Books
中包含title
、author
、subject
、book_id
四个变量,而最后一个分号前的book
则定义了一个类型为Books
的结构体变量book
。
初始化
初始化样例如下:
/* 初始化样例 */
struct book library{
"The Pious Pirate and Devious Damsel",
"Renee Vivotte",
1.95
};
该样例将结构体library
中的变量初始化赋值。
结构体的数据对齐原则(链接)
1: 整体空间是占用空间最大的成员(的类型)所占字节数的整数倍,若最大成员类型所占字节数超过4,如double是8,则整体空间是4的倍数即可。
2: 数据对齐原则。内存按结构体成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整数倍,如果不够则补齐,依次向后类推。某成员类型所占字节数超过4,如double是8,则前面已摆放的空间大小是4的整数倍即可,不够则补齐。
结构成员的访问
结构成员的访问需要使用成员访问运算符.
例:library.value
便是结构体变量library
中的value
变量。
/* 样例 */
struct book gift = {
.value= 25.99,
.author = "James Broadfoot",
.title = "Rue for the Toad"};
结构数组(链接)
结构数组中的每一个元素都是struct book
类型的结构体变量。
/* 结构体声明略 */
struct STUDENT stu[10];
stu[i]
便是stu
数组中的第i + 1
个结构体变量。
嵌套结构(链接)
在一个结构中包含另一个结构,以方便使用。
/* 样例 */
struct Student_info{
char *name; //姓
char *Branch_name; //名
struct Evaluation{
char *division;
int hsc_score;
int ssc_score;
int roll_num;
}eval;
}student;
指向结构的指针(链接)
当一个指针变量指向结构体时,我们就称它为结构体指针。
//结构体
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
} stu1 = { "Tom", 12, 18, 'A', 136.5 };
struct stu *pstu = &stu1; //结构体指针
使用
#include <stdio.h>
int main(){
struct{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
} stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
//读取结构体成员的值
printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
return 0;
}
->
是一个新的运算符,习惯称它为“箭头”,有了它,可以通过结构体指针直接取得结构体成员;这也是->
在C语言中的唯一用途。
运行结果:
Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
#include <stdio.h>
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
}stus[] = {
{"Zhou ping", 5, 18, 'C', 145.0},
{"Zhang ping", 4, 19, 'A', 130.5},
{"Liu fang", 1, 18, 'A', 148.5},
{"Cheng ling", 2, 17, 'F', 139.0},
{"Wang ming", 3, 17, 'B', 144.5}
}, *ps;
int main(){
//求数组长度
int len = sizeof(stus) / sizeof(struct stu);
printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
for(ps=stus; ps<stus+len; ps++){
printf("%s\t%d\t%d\t%c\t%.1f\n", ps->name, ps->num, ps->age, ps->group, ps->score);
}
return 0;
}
运行结果:
Name | Num | Age | Group | Score |
---|---|---|---|---|
Zhou ping | 5 | 18 | C | 145.0 |
Zhang ping | 4 | 19 | A | 130.5 |
Liu fang | 1 | 18 | A | 148.5 |
Cheng ling | 2 | 17 | F | 139.0 |
Wang ming | 3 | 17 | B | 144.5 |
向函数传递结构的信息(链接)
传递结构成员
有时候我们并不需要对于结构体的全体成员进行访问,而只需要单个的或者个别几个的成员便足矣。这时候我们只需要将结构体的部分成员对函数及逆行传参即可。
#include<stdio.h>
struct person
{
char name[10]; //成员姓名
char sex; //成员性别
double salary; //平日工资
double extra_gains; //外快收入
};
double sum(double x,double y)
{
return(x + y);
}
int main()
{
struct person Zhangsan =
{
"张三",
'm',
10000, //张三日常划水的工资收入
10000000, //法外狂徒的外快收入
}
printf("张三一个月的收入有%.2f元\n",sum(Zhangsan.salary,Zhangsan.extra_gains));
return 0;
}
传递结构
希望能够更加方便地对整个结构体进行操作,在现行的C语言标准下,是可以的,通过该函数后变化的只是结构体的副本,而非结构体本身。
#include<stdio.h>
struct person
{
char name[10]; //成员姓名
char sex; //成员性别
double salary; //平日工资
double extra_gains; //外快收入
};
double sum(struct person who)
{
return(who.salary + who.extra_gains);
}
int main()
{
struct person Zhangsan =
{
"张三",
'm',
10000, //张三日常划水的工资收入
10000000, //法外狂徒的外快收入
};
printf("张三一个月的收入有%.2f元\n", sum(Zhangsan));
return 0;
}
传递结构的地址
将指向结构体的指针作为参数传入到函数当中,由于指针本身只占有4个字节,内存较小,同时也能对结构体本身进行修改。
#include<stdio.h>
struct person
{
char name[10]; //成员姓名
char sex; //成员性别
double salary; //平日工资
double extra_gains; //外快收入
};
double sum(struct person who)
{
who.extra_gains += who.salary;
return( who.extra_gains);
}
int main()
{
struct person Zhangsan =
{
"张三",
'm',
20000, //张三日常划水的工资收入
10000000, //法外狂徒的外快收入
};
printf("张三一个月的收入有%.2f元\n", sum(Zhangsan));
printf("此时Zhangsan的extra成员的值为%f\n", Zhangsan.extra_gains);
return 0;
}
复合字面量和结构(链接)
复合字面量:通过复合字面量,我们可以在一个语句中给结构变量的多个成员变量赋值。
struct time this_time={3,29,55};//相当于定义了时间结构变量,并将其设置为3:29:55
struct time={.hour=12,.minut=10};//通过给出成员的名字,可以以任意顺序初始化结构变量的成员,或者只初始化部分成员
struct date birthdays[10]; //定义了一个结构数组,该数组包含了10个元素,每个元素都是一个结构类型变量
birthdays[1].month=8;
birthdays[1].day=8;
birthdays[1].year=2004; //将结构数组中的第二个元素赋值为2004年8月8日
checkdate(birthdays[1]); //将数组中第二个元素传递给checkdate函数
//checkdate的函数定义可能如下:
void checkdate (struct date d0){}//因为该函数需要接收struct date类型参数
伸缩型数组成员(链接)
struct flex{
int count;
double average;
double scores[]; //伸缩型数组成员,利用molloc动态分配
}
#include <stdio.h>
#include <stdlib.h>
struct arr
{
int count;
double average;
double scores[]; //伸缩型数组成员
};
void show_arr(const struct arr *p); //不改变结构体中的内容,故使用关键字const
int main (int argc, char *argv[])
{
int total = 0;
int n = 5;
int i;
struct arr *p1;
//为结构体分配存储空间
p1 = malloc(sizeof(struct arr) + n * sizeof(double));
p1->count = n;
for (i = 0; i < n; i++)
{
p1->scores[i] = 20.0 - i;
total += p1->scores[i];
}
p1->average = total / n;
show_arr(pl);
//释放在堆中动态分配的存储空间
free(p1);
return 0;
}
void show_arr(const struct arr *p)
{
int i;
printf ("Scores : ");
for (i = 0; i < p->count; i++)
{
printf("%g ", p->scores[i]);
}
printf ("\n");
printf ("Average: %g\n", p->average) ;
}
匿名结构(链接)
C语言中,可以在结构体中声明某个联合体(或结构体)而不用指出它的名字,如此之后就可以像使用结构体成员一样直接使用其中联合体(或结构体)的成员。
把结构内容保存到文件中(链接)
利用fprintf
、fread
和fwrite
,对文件进行读写操作。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
ptr – 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
size – 这是要读取的每个元素的大小,以字节为单位。
nmemb – 这是元素的个数,每个元素的大小为 size 字节。
stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
ptr – 这是指向要被写入的元素数组的指针。
size – 这是要被写入的每个元素的大小,以字节为单位。
nmemb – 这是元素的个数,每个元素的大小为 size 字节。
stream – 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。
int fprintf(FILE *stream, const char *format, …)
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
format – 这是 C 字符串,包含了要被写入到流 stream 中的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。format 标签属性是 %[flags][width][.precision][length]specifier,具体讲解见链接
链式结构(链接)
二叉树及相关知识
联合体(共用体)简介(链接)
结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员。在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union)。
结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。
枚举类型(链接)
枚举enum
是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读。
第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。
把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
typedef简介(链接)
typedef是C语言的一个重要的关键字,是为数据类型的定义一个新的名字。也就是类型的别名。
#include<stdio.h>
typedef int A;
int main(void)
{
A a = 10;
printf("a = %d", a);
return 0;
}
其他复杂的声明
符号 | 含义 | 优先级 |
---|---|---|
* | 表示一个指针 | 低 |
() | 表示一个函数 | 高 |
[] | 表示一个数组 | 高 |
函数和指针(链接)
可以把适当类型的函数的地址赋给函数指针,然后通过函数指针访问函数。
void ToUpper (char *);
void ToLower (char *);
int round (double);
void (*Pf) (char *);
pf = ToUpper; // 合法,ToUpper是函数ToUpper( )的地址
pf = ToLower; // 合法,ToLower是函数ToLower( )的地址
// pf = round; // 非法,round是错误类型的函数
// pf = ToLower(); // 非法,ToLower()不是地址