1,结构体以及两种用法
#include <stdio.h> struct s { int a; int b; char s[6]; }; //结构体声明 int main(void) { struct s obj={ .a=5, .b=8, .s="hello", }; //结构体初始化 printf("sizeof obj=%u ",sizeof obj); //结果为16是两个int型占8个字节,最后一个数组要凑齐被4整除的边界只能是8,所以有16个字节。 printf("&obj = %p,&obj.a=%p,&obj.b=%p " "&obj.s=%p,obj.s=%p ",&obj,&obj.a,&obj.b,&obj.s,obj.s); printf("------------------------- "); //obj.s类型等同于 char * //&obj.s类型等同于 char (*)[6] printf("obj.s=%p,obj.s+1=%p ",obj.s,obj.s+1); printf("&obj.s=%p,&obj.s+1=%p ",&obj.s,&obj.s+1); printf("------------------------ "); //.是域(field)运算符/取成员运算符 printf("obj.a=%d,obj.b=%d,obj.s=%s ",obj.a,obj.b,obj.s); printf("==========================="); //结构体取法 struct s *pobj = NULL; pobj=&obj; printf("sizeof pobj=%u ",sizeof pobj); printf("&pobj = %p,pobj = %p,&obj=%p ",&pobj,pobj,&pobj); printf("&pobj = %p,&pobj->a=%p,&pobj->b=%p " "&pobj->s=%p,pobj->s=%p ",&pobj,&pobj->a,&pobj->b,&pobj->s,pobj->s); printf("--------------------------------- "); printf("pobj->s=%p,pobj->s+1=%p ",pobj->s,pobj->s+1); printf("&pobj->s=%p,&pobj->s+1=%p ",&pobj->s,&pobj->s+1); printf("------------------------ "); //->是域运算符/取成员运算符 printf("pobj->a=%d,pobj->b=%d,pobj->s=%s ",pobj->a,pobj->b,pobj->s); return 0; }
结果:
will@will-laptop:~/ex/9$ ./a.out sizeof obj=16 &obj = 0xbeb79174,&obj.a=0xbeb79174,&obj.b=0xbeb79178 &obj.s=0xbeb7917c,obj.s=0xbeb7917c ------------------------- obj.s=0xbeb7917c,obj.s+1=0xbeb7917d &obj.s=0xbeb7917c,&obj.s+1=0xbeb79182 ------------------------ obj.a=5,obj.b=8,obj.s=hello ===========================sizeof pobj=4 &pobj = 0xbeb79170,pobj = 0xbeb79174,&obj=0xbeb79170 &pobj = 0xbeb79170,&pobj->a=0xbeb79174,&pobj->b=0xbeb79178 &pobj->s=0xbeb7917c,pobj->s=0xbeb7917c --------------------------------- pobj->s=0xbeb7917c,pobj->s+1=0xbeb7917d &pobj->s=0xbeb7917c,&pobj->s+1=0xbeb79182 ------------------------ pobj->a=5,pobj->b=8,pobj->s=hello
2,结构体应用
#include <stdio.h> #include <stdlib.h> struct s { int a; int b; char s[6]; }; int main(void) { struct s obj={ .a=6, .b=8, .s="hello", }; printf("obj.a=%d,obj.b=%d,obj.s=%s ",obj.a,obj.b,obj.s); printf("obj.a=%p,obj.b=%p,obj.s=%p ",&obj.a,&obj.b,&obj.s); printf("------------------------ "); struct s obj_copy; //同类型结构体对象之间可以直接复制 obj_copy = obj; printf("obj_copy.a=%d,obj_copy.b=%d,obj_copy.s=%s ",obj.a,obj.b,obj.s); printf("obj_copy.a=%p,obj_copy.b=%p,obj_copy.s=%p ",&obj.a,&obj.b,&obj.s); printf("------------------------ "); struct s *pobj=NULL; pobj = malloc(sizeof(struct s)); if(NULL==pobj) return 1; //结果体对象之间复制是浅拷贝 // pobj=&obj;这个是取地址,没有使用开辟的空间 *pobj = obj; printf("pobj->a=%d,pobj->b=%d,pobj->s=%s ",pobj->a,pobj->b,pobj->s); printf("pobj->a=%p,pobj->b=%p,pobj->s=%p ",&pobj->a,&pobj->b,&pobj->s); free(pobj); return 0; }
结果:
will@will-laptop:~/ex/9$ ./a.out obj.a=6,obj.b=8,obj.s=hello obj.a=0xbe869164,obj.b=0xbe869168,obj.s=0xbe86916c ------------------------ obj_copy.a=6,obj_copy.b=8,obj_copy.s=hello obj_copy.a=0xbe869164,obj_copy.b=0xbe869168,obj_copy.s=0xbe86916c ------------------------ pobj->a=6,pobj->b=8,pobj->s=hello pobj->a=0x7ee008,pobj->b=0x7ee00c,pobj->s=0x7ee010
3,联合用法
#include <stdio.h> union u{ int a; char ch; double d; }; int main(void) { union u uobj; union u *pu=NULL; pu=&uobj; printf("sizeof uobj=%u ",sizeof uobj); //选取最大的大小,也就是双精度的八位 uobj.a = 3; printf("uobj.a=%d ",uobj.a); printf("uobj.d=%lf ",uobj.d); //未初始化直接变成0 printf("--------------- "); printf("&uobj.a=%p,&uobj.ch=%p ""&uobj.d=%p,&uobj=%p ",&uobj.a,&uobj.ch,&uobj.d,&uobj);
//这个说明位置没有根本变化,只能拿一个出来用, uobj.d=3.14; printf("uobj.d=%lf ",uobj.d); printf("uobj.a=%d ",uobj.a); //越界了a的值不对了。如果要使用a的值就需要在打印完后再自行赋值 printf("--------------- "); uobj.ch='A'; printf("uobj.ch=%c ",uobj.ch); printf("&uobj.a=%p,&uobj.ch=%p ""&uobj.d=%p,&uobj=%p ",&uobj.a,&uobj.ch,&uobj.d,&uobj); //结果表明每一调出的元素都是相同的地址,联合是提供了不同的元素 printf("--------------- "); printf("&pu->a=%p,&pu->ch=%p ""&pu->d=%p,pu=%p ",&pu->a,&pu->ch,&pu->d,pu); //pu本身是存储地址的指针而已,所以不用取地址符 return 0; }
结果:
will@will-laptop:~/ex/9$ ./a.out sizeof uobj=8 uobj.a=3 uobj.d=0.000000 --------------- &uobj.a=0xbe8d1188,&uobj.ch=0xbe8d1188 &uobj.d=0xbe8d1188,&uobj=0xbe8d1188 uobj.d=3.140000 uobj.a=1374389535 --------------- uobj.ch=A &uobj.a=0xbe8d1188,&uobj.ch=0xbe8d1188 &uobj.d=0xbe8d1188,&uobj=0xbe8d1188 --------------- &pu->a=0xbe8d1188,&pu->ch=0xbe8d1188 &pu->d=0xbe8d1188,pu=0xbe8d1188
4,枚举
#include <stdio.h> //枚举就是将变量的值一一列举出来, //变量的值只限于列举出来的值的范围内 enum txt_attr { color_start,//0 black,//1 white, red, yellow, blue, green, orange, color_end =32, attr_start, italic, bold, attr_end }; int main(void) { enum txt_attr txt; txt = color_start; printf("color_start = %d ",txt); txt=black; printf("black = %d ",txt); txt=orange; printf("orange = %d ",txt); txt=color_end; printf("color_end = %d ",txt); printf("--------------------------- "); txt=attr_start; printf("attr_start = %d ",txt);//枚举就是排序有代号 printf("attr_start = %d ",attr_start); txt=italic; printf("italic =%d ",txt);//会自动加1,如果没有定义的话 return 0; }
结果:
will@will-laptop:~/ex/9$ ./a.out color_start = 0 black = 1 orange = 7 color_end = 32 --------------------------- attr_start = 33 attr_start = 33 italic =34
5,fopen函数使用
#include <stdio.h> #include <errno.h> int main(void) { FILE *fp=NULL; size_t ret=0; fp=fopen("1.txt","w+");//打开文件,因为有w+没有就创建 if(NULL==fp) { //perror:根据errno解释错误原因并输出到stderr //perror("fopen failed"); //strerror:根据errno返回错误原因的字符串描述 fprintf(stderr,"fopen failed,%s ",strerror(errno));
//错误标识语句 goto err0; } ret=fwrite("china unix",1,10,fp); if(ret!=10) { fprintf(stderr,"fwrite failed,%s ",strerror(errno)); goto err1; } printf("------file writed,now read file------- "); rewind(fp); //文件内部位置指针指向开头 char s[32]={0}; ret=fread(s,1,10,fp); if(ret!=10) { perror("fread failed");//这个是固定用的 goto err1; } printf("now readed.s = %s ",s); fclose(fp); return 0; err1: fclose(fp); err0: return 1; }
结果:
will@will-laptop:~/ex/9$ sudo ./a.out [sudo] password for will: ------file writed,now read file------- now readed.s = china unix
6,fseek,ftell的作用和文件结束符EOF
#include <stdio.h> int main(void) { FILE *fp = NULL; size_t ret; int pos; fp = fopen("files/2.txt", "w+"); if (NULL == fp) { perror("fopen failed"); goto err0; } pos = ftell(fp);//获得相对于文件首的偏移字数 printf("file opened, pos = %d ", pos); ret = fwrite("china", 1, 5, fp); if (5 != ret) { perror("fwrite failed"); goto err1; } printf("------'china' writed, pos = %d ", ftell(fp)); fseek(fp, 6, SEEK_CUR);//定位到文件头六个字节后 pos = ftell(fp); printf("------fseek 6 bytes. pos = %d ", pos); ret = fwrite(" unix", 1, 5, fp); if (5 != ret) { perror("fwrite failed"); goto err1; } printf("------' unix' writed, pos = %d ", ftell(fp)); rewind(fp); printf("read file and print now: "); int ch; printf("EOF == %d ", EOF);//文件结束符的值是-1 while ((ch = fgetc(fp)) != EOF)//循环输出文件内容 putchar(ch); putchar(' '); fclose(fp); return 0; err1: fclose(fp); err0: return 1; }
结果:
file opened, pos = 0 ------'china' writed, pos = 5 ------fseek 6 bytes. pos = 11 ------' unix' writed, pos = 16 read file and print now: EOF == -1 china unix
7,数组和文件交换数据
#include <stdio.h> void rand_a(int *p,int len) { int i; for(i=0;i<len;i++) p[i]=rand()%100; } void print_a(int *p,int len) { int i; for(i=0;i<len;i++) { printf("%d ",p[i]); } putchar(' '); } int main(void) { FILE *fp=NULL; int a[10]={0}; int b[10]={0}; fp=fopen("3.int","w+"); if(NULL==fp) { perror("fopen failed"); goto err0; } rand_a(a,10); printf("a: "); print_a(a,10); fwrite(a,sizeof(int),10,fp); fclose(fp); printf("-------------------- "); fp=fopen("3.int","r"); if(NULL==fp) { perror("fopen failed"); goto err0; } fread (b,sizeof(int),10,fp); printf("b: "); print_a(b,10); fclose(fp); return 0; err0: return 1; }
结果:
will@will-laptop:~/ex/9$ ./a.out a: 83 86 77 15 93 35 86 92 49 21 -------------------- b: 83 86 77 15 93 35 86 92 49 21
8,个人信息管理
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _basic{ int id; char sex; char name[32]; }basic_t; typedef struct _contact { char qq[16]; char email[]; }contact_t; typedef struct _person{ struct _basic binfo; contact_t *pcont; }person_t; int add_person(person_t **p,int *cnt) { p[*cnt]=malloc(sizeof(person_t)); if(NULL==p[*cnt]) goto err0; p[*cnt]->pcont =malloc(sizeof(contact_t)); if(NULL==p[*cnt]->pcont) goto err1; p[*cnt]->binfo.id=rand()%100; p[*cnt]->binfo.sex ="MF"[rand()%2]; printf(" input name:"); gets(p[*cnt]->binfo.name); printf(" input qq:"); gets(p[*cnt]->pcont->qq); printf(" input email:"); gets(p[*cnt]->pcont->email); *cnt +=1; return 0; err1: free(p[*cnt]); p[*cnt]=NULL; err0: return -1; } void print_person(person_t **p,int cnt) { int i; for(i=0;i<cnt;i++) { printf(" ---第%d人信息:--- ",i+1); printf(" id:%d sex:%c name:%s ",p[i]->binfo.id,p[i]->binfo.sex,p[i]->binfo.name); printf(" qq:%s email:%s ",p[i]->pcont->qq,p[i]->pcont->email); } } int save_person(person_t **p ,int cnt) { FILE *fp = NULL; size_t ret; int i; if(NULL==(fp=fopen("person.db","w"))) { perror("fopen"); goto err0; } if(1!=(ret=fwrite(&cnt,sizeof(int),1,fp))) goto err1; for(i=0;i<cnt;i++) { if(1!=fwrite(p[i],sizeof(person_t),1,fp)) goto err1; if(1!=fwrite(p[i]->pcont,sizeof(contact_t),1,fp)) goto err1; } fclose(fp); return 0; err1: fclose(fp); err0: return -1; } int load_person(person_t **p,int *cnt) { FILE *fp=NULL; int i,j,count; for(i=0;i<*cnt;i++) { free(p[i]->pcont); free(p[i]); } if(NULL==(fp=fopen("person.db","r"))) perror("fopen"); goto err0; if(1!=fread(&count,sizeof(int),1,fp)) goto err1; for(i=0;i<count;i++) { p[i]=malloc(sizeof(person_t)); if(NULL==p[i]) goto err2; if(1!=fread(p[i],sizeof(person_t),1,fp)) goto err2; p[i]->pcont=malloc(sizeof(contact_t)); if(NULL==p[i]) goto err3; if(1!=fread(p[i]->pcont,sizeof(contact_t),1,fp)) goto err3; } *cnt=count; fclose(fp); return 0; err3: free(p[i]); err2: for(j=0;j<i;j++) { free(p[i]->pcont); free(p[j]); p[j]=NULL; } err1: fclose(fp); err0: return -1; } int main(void) { person_t *pers[10]={NULL}; printf(" ====>欢迎光临个人信息管理系统<==== "); int quit =0,ret,op; int i,count=0; while(!quit) { retry: printf(" ===>1.输入个人信息 "); printf(" ===>2.遍历个人信息 "); printf(" ===>3.存储个人信息 "); printf(" ===>4.读取个人信息 "); printf(" ===>5.退出 "); printf(" ===>请选择【1-5】"); ret=scanf("%d",&op); while(getchar()!=' ') ; if(ret==0) { printf(" 输入错误 "); } switch (op) { case 1: if(count >= 10) { printf(" 只能存放10个个人信息! "); break; } if(0==add_person(pers,&count)) printf(" 添加成功! "); else printf("添加失败 "); case 2: print_person(pers,count); break; case 3: if(0==save_person(pers,count)) printf(" 保存成功 "); else printf("保存失败 "); break; case 4: if(0==load_person(pers,&count)) printf("读取成功 "); else printf("读取失败 "); break; case 5: quit = 1; break; default: break; } } for(i=0;i<count;i++)//循环结束,就必须释放空间内存 { free(pers[i]->pcont); free(pers[i]); } return 0; }
结果:
===> 欢迎光临个人信息管理系统 <=== ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 1 input name: a input qq: 123 input email: asd 添加成功! ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 1 input name: 2 input qq: 2 input email: 添加成功! ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 2 --- 第 1 人信息: --- id: 83 sex: M name: a qq: 123 email: asd --- 第 2 人信息: --- id: 77 sex: F name: 2 qq: 2 email: ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 3 保存成功! ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 4 读取成功! ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: ^C will@will-Inspiron-N4010:~/uplooking/c/9th$ ./a.out ===> 欢迎光临个人信息管理系统 <=== ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 4 读取成功! ====> 1. 输入个人信息 <==== ====> 2. 遍历个人信息 <==== ====> 3. 存储个人信息 <==== ====> 4. 读取个人信息 <==== ====> 5. 退出 <==== ==> 请选择[1 - 5]: 2 --- 第 1 人信息: --- id: 83 sex: M name: a qq: 123 email: asd --- 第 2 人信息: --- id: 77 sex: F name: 2 qq: 2 email: