zoukankan      html  css  js  c++  java
  • c博客06-2019-结构体&文件

    1.本章学习总结

    1.1 学习内容总结

    • 结构体如何定义、成员如何赋值
    1.结构体形式
    
    
    
    结构类型定义的一般形式:
    
    struct 结构名 {
    	类型名 结构成员1;
    	类型名 结构成员2;
    
    	...
    };
    
    常用形式:
    
    typedef struct {
    	类型名 结构成员1;
    	类型名 结构成员2;
    
    	...
    }新的变量类型名;
    
    
    

    2.结构的嵌套定义

    注意:必须先定义成员的结构类型,再定义主结构类型

    3.结构体的赋值:

    结构变量可以初始化,即在定义时对其赋初值,不能分行赋值
    (整个结构变量虽然是变量,不能分行赋值)

    
    例如
    
    struct student {
    	int num;
    	char name[20];
    	int score;
    };
    
    struct student s1={101,"zhang",78,}
    
    

    4结构变量的使用

    对结构变量成员的使用方法与同类型的变量完全相同。(因此应当注意:字符串赋值应当调用库函数实现,而不是用赋值符)

    5.结构变量的整体赋值

    如果两个结构变量具有相同的类型,则允许将一个结构变量的值直接赋给另一个结构变量。这是结构中唯一整体操作的方式。

    • 结构体数组排序做法
    1.结构数组
    结构数组的定义方法与结构变量相似。在定义结构数组时,也可以对其进行初始化,其格式与二维数组的初始化类似。
    
    
    其一般格式为:
    
    结构数组名[下标].结构成员名
    
    

    2.思路
    结构数组的排序,通常是根据结构体中的某一成员进行比较。由于同一结构数组的成员其结构类型必定相同,因此是可以相互赋值的。然后再根据选择排序法或者冒泡排序法,利用temp中间值等,进行结构体数组的排序。(例子参考p225-学生成绩排序)

    • 结构体指针怎么用

    1.结构体指针的概念

    结构指针的值实际上就是结构变量的首地址,即第一个成员的地址。

    2结构数组访问成员的不同方法
    
    
    1).用*p访问结构成员
    
    如 (*p).num = 101 ;
    
    其中*p表示的是p指向的结构变量。
    注意,(*p)中的括号是不可少的,因为成员运算符"."的优先级高于"*"的优先级。
    
    
    
    2).用指向运算符->访问指针指向的结构成员
    
    如 p->num = 101 ;
    
    

    但在使用结构指针访问时,通常使用指向运算符->。

    • 共用体、枚举类型做法
    共用体的一般声明形式:
    
    union 联合名
    {
    	成员声明;
    	成员声明;
    	...
    
    }变量列表;
    
    

    联合中的所有成员共享一块内存空间,显然使用共用体能够节省内存。c语言编译程序保证分配给联合的内存能容纳其最大的成员变量

    编程时应该保证联合变量时采用的成员变量和最后一次向其中存入值时采用的成员变量相同

    
    定义枚举数据类型的一般格式如下:
    
    snum 枚举名{ 枚举值1,枚举值2,... }变量列表;
    
    
    当一个变量值可能有几种值时,我们可以采用枚举变量,有如星期日。
    
    
    • 文件读写,文件中数据如何读进结构体数组
      1.2 本章学习体会

    2.综合作业--“我爱成语”

    2.1.文件介绍

    2.头文件介绍

    idiom.h

    typedef struct {
    	char name[N];
    	char meaning[N];
    
    }IDIOM;
    

    结构体IDIOM 用于存储成语及其意思。

    typedef struct {
    	char username[N];
    	char password[N];
    }USER;
    

    结构体USER 用于储存用户的账号和密码,主要用于登入匹配系统。

    
    - void InitialMenu();//显示初始界面
    
    
    - void ListMenu();//显示程序功能的主菜单
    
    
    - void ExitMenu();//显示退出的界面
    
    
    - int ExitTips();//提醒用户是否退出的函数
    
    
    - void MakeChoice(IDIOM* idioms, int num);//让用户做选择的函数,根据选择实现其他功能函数
    
    
    
    - int CheckUserValid();//登入匹配系统
    
    
    - int  GetData(FILE* fp, IDIOM* idioms);//获取成语数据文件中内容的函数,存放进结构数组中方便处理。
    
    
    - void SetQuestions(char *randomidiom,int i);//显示题目的出题函数
    
    
    - void Game(IDIOM*idioms,int num);//总的成语游戏
    
    
    - void LearnIdioms(IDIOM* idioms,int num);//成语词典函数,功能是查找到成语,输出其意思
    

    代码展示

    2.函数实现文件介绍

    文件1 main.c

    文件功能主要就是:先判断用户是否能够登入系统,然后在根据用户要求,实现相应的功能要求。

    设计思路

    - 1.由于成语数据的文件,将频繁应用于各个功能函数间,因此该文件的打开和关闭,我放在主函数实现。并且打开后即处理文件数据内容,存入到结构数组中。
             
    - 2.先显示初始菜单,接着就是一个while循环,直到用户输入正确的账号密码时,才可以跳出循环进入下一步的界面和操作,进入主菜单。
             
    - 3.接着就只有一个while循环了,其功能是结合分装函数中的退出提示的函数使用。根据用户需求来设计的,当用户想退出游戏时,可直接根据退出提示操作,而当用户想要回到主菜单则主     要依靠,这一while循环来实现。
    
    

    主函数主要思路部分代码:

    总的代码:

    文件2 idiom.c

    1.3菜单展示函数

    设计思路:

    
    1) 始展示的是初始菜单InitialMenu()。
    
    2) 提示用户登入账号密码,成功登入后,才显示成语游戏的主菜单ListMenu(),展示功能。
    
    3) 无论何种情况下,用户选择退出后,都给用户显示退出界面ExitMenu()。
    

    具体代码

    2.登入系统

    主函数中相关部分代码

    设计思路

    1)主函数思路:
    
    从上图可知,我是通过while恒真循环,控制用户登入成功后,才显示下一步的操作。
    
    上图橙色框控制的是输出页面,若输入错误,都用清屏再输出初始菜单的方法,来让用户重新输入。是界面看起来更清楚,更合理(清屏后,用户看不到先前已输入的错误的信息)
    
    
    2)主函数可拓展功能:
    
    可以在while循环下,控制次数,来达到如果输入一直错误,控制用户输入的次数。
    
    匹配过程中是可以知道,是账户不存在,还是账号密码错误,可以据此开拓,给予用户提示的功能。
    
    
    3)由于用户账号密码文件仅在该函数中打开使用,因此打开文件操作只写在该函数中,不写在主函数中
    
    
    4)该函数类型是int 型,返回值用来代表匹配结果,成功为1,否则为2
    
    
    

    3.其他功能函数

    选择函数在主函数中相关部分:

    设计思路

    1)第一个是退出提醒函数 int ExitTips(),该函数较为方便,可应用在各功能函数中。根据询问用户需求,再做出是否继续使用功能函数或者是返回主菜单,亦或者直接退出游戏。
    
    
    2)第二个则是做选择函数 void MakeChoice(IDIOM* idioms, int num),由于回到回到主菜单之后,都需要再次询问用户选择,并根据选择执行,放在主函数中写太过繁杂,因此分装来写。
    
    
    3)如上图主函数中相关部分所示,利用while循环,清屏显示主菜单页面,调用选择函数,这几步操作,达到用户使用完功能函数后能够回到主菜单,再次选择使用。
    
    

    具体代码

    退出提示函数

    做选择函数

    4.成语查找功能函数

    设计思路

    1)
    主要函数就是 void LearnIdioms(IDIOM* idioms,int num),其中嵌套成语数据获取文件函数 int  GetData(FILE* fp, IDIOM* idioms)。
    
    由于成语数据获取文件函数,可以在多个函数间调用,因此独立分装,并且,*该文件的打开放在主函数中执行。*
    
    
    2)获取数据函数的函数类型是int ,返回获取数据的总值num。因为后面的成语游戏需要随机抽取函数,因此需要知道获取数据的总量。
    
    
    3)成语查找功能函数中:
    
    能够多次查找成语功能,利用while恒真循环来达成。
    
    每查询五次就调用退出提示函数,对用户需求进行确认。此时while循环能达成继续使用该功能。
    
    
    

    具体代码

    获取数据函数

    成语查找功能函数;


    5.成语游戏

    设计思路

    1)成语游戏功能的主要函数是 void Game(IDIOM*idioms,int num),其中调用获取数据函数 int  GetData(FILE* fp, IDIOM* idioms) 和
    出题函数void SetQuestions(char *randomidiom,int i)。
    
    
    2)出题函数的主要思路:
    我是先在成语游戏中已经抽取出一个随机的成语,将这个成语传参给出题函数。
    
    在出题函数中再定义一个出题成语,先将随机成语复制给出题成语,再根据四字两空的六种不同情况,修改出题成语,并直接输出题目,因此无返回值,出题函数函数类型为void。
    
    
    3)
    成语游戏函数中定义一个用户输入的成语,再调用了出题函数之后,则直接将已定义的随机成语与用户输入成语进行比较即可。
    
    因此出题函数仅在出题函数周期内生存,只要能输出题目即可。
    
    
    4)与成语查找功能相同的是,整个函数主要也是在while循环内,为了达到十次游戏结束后,根据提示还能继续完游戏的效果。
    
    

    具体代码

    出题函数

    成语游戏函数

    2.2.运行结果

    1.登录界面

    进入初始界面,输入错误的账户密码

    显示输入错误的账户密码后,重新输入正确的账号密码

    显示登入成功并且展示主菜单

    2.游戏界面

    每次游戏共十道题,答完十道题后,就会跳出退出提示。

    选择0则展示退出界面并结束程序

    选择1,继续该功能,则会清屏重来游戏。选择2,则返回主菜单,展示登入成功后的样子。

    3.成语查找界面

    查找不到即提示,查找到了就显示意思

    同样的每查询五次,就弹出退出提示窗口。

    2.3大作业总结

    1.碰到问题及解决办法

    • 一开始写完读取文件数据的函数后,就调试。但发现输出的结构体数组,是一大堆乱码,想不明白。
      检查自己的读写代码好久,最后请舍友帮忙看看,才想到保存的文件没有以ASCII码的形式保存,因此输出的是乱码。

    • 写出题函数,是一开始不知道该怎么输出空格。因此后来想到了将成语的两个字替换成下划线,因为这个操作比较麻烦,所以才另外写了出题函数,在成语游戏中调用。
      一开始是想直接在出题函数中抽取随机成语,替换成功,显示替换后的成语,然后再与用户的答案进行比较。然而此时的题目成语已经不完整,无法比较了。
      于是我又重新调整,在成语游戏中就抽取出随机成语,传参给出题函数,令出题函数名副其实,只做出题的功能(输出题目)。
      方法是在出题函数中另外定义出题成语,对其进行处理后输出,其主要功能就是输出显示,无其他作用,所以生存期也就仅存在于出题函数中。

    • 考虑到如何更能符合用户需求,能够根据用户需求,选择继续该功能抑或是返回主菜单还是直接退出。
      首先需要一个操作提醒,该函数功能就是获取用户需求,返回用户的选择,根据用户的选择再进行判断。
      为了能够继续使用该功能,因此每个功能总的操作都是while恒真循环,得到返回主菜单命令条件时break,结束该函数的调用。要直接退出时则利用exit(0)。
      同样的为了能使用户回到主菜单,在主函数中使用while恒真循环,使得一直都会回到主菜单。若需要继续功能或者直接退出,都根据提示操作。
      在循环嵌套下,为了达成返回主菜单等的视觉效果,还要注意,清屏函数再次输出菜单的操作。

    • 在写做选择函数时,由于这部分内容原属主函数一部分,只是分装起来显得更加简洁,所以一开始设计的时候也就没有返回值以及传参。
      选择函数中的主要语句就是switch语句,根据不同选择来调用不同函数实现功能。
      单个函数写完后就有调试功能,放在选择函数中调用后,却无法正常运行,逐语句调试时,发现到要调用函数时就显示异常了。
      一开始不理解这么简单的代码,会错在哪,看调用的函数中有的带有形参表时,才反应过来,由于是在函数中调用函数,所以次要函数中所需要的形参,在主要函数中也要记得传参过来否则 就无法实现次要函数。
      这提醒了我以后写代码时,在函数调用中嵌套调用时,要注意是否需要传参。当然这也说明了,如果我的功能函数越多,需要的信息越多,在我的做选择函数就需要传更多的参数,尽管并非它自己直接使用。

    2.小结

    • 要写一个完整体验、体验舒适的程序很花时间,用户需求啊,界面样式,语言风格等的都要设计。
    • 通过大作业,确实是会帮助巩固学过的知识的,毕竟是综合应用,穿插起来应用,就需要对知识掌握娴熟一些,写起来才不会到处卡壳。而且综合起来使用,多处调试,提高了一些找错能力。我感觉确实的培养了,写每完个功能函数都能及时调试改正的习惯,能写多少功能算多少,保证已经写的功能能用。
    • 还有很多很多很多很多可以拓展改进的地方。
  • 相关阅读:
    django第10天(聚合查询,常用字段)
    django第9天(多表操作)
    django第8天(在测试文件中运行django项目|单表操作)
    django第七天(模板的复用性,include标签和母版)
    django第六天(模板相关,过滤器和标记)
    SparkCore2
    SparkCore
    SQL
    Spark基础
    使用Observer实现HBase到Elasticsearch的数据同步
  • 原文地址:https://www.cnblogs.com/zml7/p/12045676.html
Copyright © 2011-2022 走看看