C语言学习10:结构体,结构体应用,联合用法,枚举,fopen函数使用,fseek,ftell的作用和文件结束符EOF,数组和文件交换数据,个人信息管理。

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: 
原文地址:https://www.cnblogs.com/will-boot/p/3355093.html