C博客作业06--结构体&文件

1.本章学习总结

1.1 学习内容总结

  • 结构体:结构是C语言中医中新的构造数据类型,,它能把有内在联系的不同类型的数据汇聚成一个整体,使它们相互关联;同时,结构又是一个变量的集合,可以按照对基本数据类型的操作方法单独使用其成员变量。结构就是这样一种特殊的构造数据类型。

  • 结构数组:结构数组是结构和数组的结合体,与普通数组的不同之处在于每个数组元素都是一个结构类型的数组,包括多个成员项;由于每个结构数组元素的类型都是结构类型,其使用方法就和相同类型的结构变量一样;
    结构数组元素之间可以直接赋值;

  • 结构指针:结构指针就是指向结构类型变量的指针;
    当我们需要结构体作为参数传递时,由于结构体的内存太大,每一次传参的代价太大,所以我们可以通过传递一个结构体指针,通过访问地址来访问结构体元素;

struct student s1={101,78}
p=&s1;

s1.num=101;
(*p).num=101;
p->num=101;

三个语句效果一样

  • 结构体如何定义、成员如何赋值:
    结构体的定义:例:定义一个学生学习结构体
   struct student {
   int num;
   char name[10];
    };

结构体类型变量定义:
1、先声明结构体类型,再定义结构体类型变量

struct Student{
......
};
struct Student stu;

2、在声明类型的同时定义变量

struct Student{
   ....
} stu;

3、不指定类型名而直接定义结构体类型变量

struct{  
....
} stu;

结构体成员赋值:结构体的赋值常用的有两种方法
1、在声明结构体变量时赋值:

struct stu{

    int x;

    char name[10];

};
    struct stu s={8,"123"};

2、单个赋值,其中字符串可以通过字符串复制函数进行赋值

struct stu{

    int x;

    char name[10];

};
    struct stu s;

    strcpy(s.name,"abcd")

    s.x=128;
  • 结构体数组排序做法:
    结构体的排序与之前数组排序大同小异,区别只在于我们是对结构体里面的成员进行排序,而不是整个结构体一起排序,所以应该将成员拿出来再进行排序

方法有:冒泡法,选择法

选择排序:

#include<stdio.h>
struct stu {

	int x;

	char name[10];

};
int main()
{
	int j = 0;
	struct stu s[3] = { {5,'a'},{4,'b'},{7,'c'} };
	struct stu temp;
	int flag = 0;
	for (int i = 0; i < 2; i++)
	{
		flag = 1;
		for (int j = 0; j < 2 - i; j++)
		{

			if (s[j].x > s[j + 1].x)
			{
				temp = s[j];
				s[j] = s[j + 1];
				s[j + 1] = temp;
			}
		}
		if (flag == 0)
		{
			break;
		}
	}
	for (int i = 0; i < 3; i++)
	{
		printf("name:%s,x:%d\n", s[i].name, s[i].x);
	}
	return 0;
}


冒泡排序:

#include<stdio.h>
struct stu {

	int x;

	char name[10];

};
int main()
{
	int j = 0;
	struct stu s[5] = { {5,'a'},{7,'b'},{4,'c'} ,{3,'d'}, {8,'e'} };
	struct stu temp;
	int flag = 0;
	for (int i = 0; i < 5; i++)
	{
		printf("name:%s,x:%d\n", s[i].name, s[i].x);
	}
	printf("\n");
	for (int i = 0; i < 2; i++)
	{
		flag = 1;
		for (int j = 1; j < 5; j++)
		{

			if (s[j-1].x > s[j].x)
			{
				temp = s[j-1];
				s[j-1] = s[j];
				s[j] = temp;
			}
		}
		if (flag == 0)
		{
			break;
		}
	}
	for (int i = 0; i < 5; i++)
	{
		printf("name:%s,x:%d\n", s[i].name, s[i].x);
	}
	return 0;
}

  • 共用体:使用同一段内存单元存放不同类型的变量,或者说使几个不同的变量共享同一段内存的结构;
    共用体的使用和结构体相似,但是初始赋值只能赋一个变量的值;
    结构体和共用体的区别在于:
    结构体的各个成员会占用不同的内存,互相之间没有影响;
    共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

  • 枚举:枚举把可能的值一一列举出来,变量的值只限于列举出来的值的范围内。
    定义形式为:

enum typeName{ valueName1, valueName2, valueName3, ...... }; 
  • 共用体、枚举类型做法
    union 共用体名

  { 
  成员表列  
}变量表列;
在引用时需注意,共用体变量中起作用的成员是最后一次存放的成员值,在存入一个新的成员后原有的成员就失去作用。
需要注意的是,枚举元素是常量而不是变量,不能再程序中对其进行赋值。每个枚举变量只能取该类型中的一个元素的值,这里也只能把元素名赋给枚举变量。

  • 文件:在操作系统中,文件是指主流在外部介质中的一个有序数据集,可以是源文件,目标程序文件,可执行文件,也可以是待输入的原始数据或是一组输出结果。
    文件有两种类型:
    1.文本文件(txt)
    文本文件是以字符ASCII码进行存储与编码的文件,其文件内容就是字符
    2.二进制文件(dat)
    二进制文件是存储二进制数据的文件

  • 文件指针:
    定义说明文件指针的一般形式为:
    FILE *指针变量标识符;
    一般情况下定义文件指针用fp
    fp是指向FILE结构的指针变量,通过fp即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件,实施对文件的操作。习惯上也笼统地把fp称为指向一个文件的指针

  • 文件相关函数
    1.重定位文件首函数rewind
    使指针指向文件首
    rwind(FILE *fp)
    2.指针移动控制函数fseek
    fseek(fp,offset,from)
    offse:距离from多字节数,正往后计算,负往前计算
    from:0(SEEK_SET)文件首,1(SEEK_CUR)当前,2(SEEK_END)文件尾
    3.获取指针当前位置函数ftell
    获取相对于文件首的距离(字节数)
    ftell(文件指针);
    4.文件末尾检测函数feof
    判断指针是否达到文件尾
    feof(fp)
    返回1代表达到尾部,0则表示文件未结束
    5.读写错误检查函数ferror
    用来检查文件在用各种输入输出进行读写时是否常
    返回0,未出错,否则就有错
    ferror(文件指针)
    6.出错标记清除函数clearerr
    用来清除出错标志和文件结束标志,使它们为0值
    clearerr(文件指针)

  • 文件读写,文件中数据如何读进结构体数组
    文件读写:

  • 一个个字符读写
    fgetc,fputc

  • 一行行字符读写
    fgets,fputs

  • 指定格式读写,写入结构体成语
    fprintf,fscanf(适用文本文件)

  • 整块结构体读写
    fread,fwrite(适用二进制文件)

文件数据读进结构体
1.通过建立一个中间值,将文件内容放入这个中间值,再通过字符串复制函数将中间值的内容放到结构体
2.直接使用fprintf,fscanf

1.2 本章学习体会

文件和结构体的学习感觉很头疼,很多地方都不是很理解,同时涉及到文件就有了多文件,之前不在意的一些问题全部体现了,其中之一就是传参;目前为止依然不是很能理解使用了typedef的结构体和不使用到底有什么区别,为什么使用后传参都不一样
文件的使用在我看来特别有用,对文件的处理包括写入,修改都很实用
同时随着结构体与文件的学习,C语言的学习也到了尾声,希望各位期末加油

代码量计算

周数 代码量
十五周 300~320
十六周 330~350
总代码量 630~670

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

2.1.文件介绍

1.头文件介绍

lead.h
结构体 entry:主要用来放用户信息,以方便后面用户登录函数的实现
结构体 IDIOM:用来放成语及其解释
void Input(char* id, char* str):用户登录函数
void MainPage():展示主页面
int Choice():进行功能选择
void GetIdioms(FILE* fp, IDIOM* idioms):将文件中的成语存放到结构体数组
void ExecutionGame(int num, IDIOM* idioms, FILE* fp):用来进行游戏
void right():在回答正确时随机输出语句
void wrong():在回答错误时随机输出语句
void division():分割线存放函数,目的就是为了方便
void Grade(int rcount, int wcount):成绩统计
void Exhibition():展示功能如何选择
void time():获取当前时间

2.函数实现文件介绍。

1:main.cpp
主要进行函数的调用以及最初的成语文件的打开,同时为了方便,我将choice每一次选择后功能的实现放入了main

2:interface.c
这个文件主要就是存放程序展示的两个函数,以及每次开始于结束时需要进行的choice函数
为了展示的方便性以及之后每次清屏的美观我将展示写成了两个函数

3:user.cpp
这个文件是单独拿出来进行用户登录的,同时在这里将文件写入用户的结构体


4:game.cpp
这个文件是功能最多的文件,文件包括了将成语放入结构体,进行“我爱成语”游戏,同时游戏函数内还嵌套了正确错误提示语函数的调用,以及成绩统计


5:statistics.cpp
这个文件是用来放正确和错误提示语以及成绩统计和时间获取四个函数的

2.2.运行结果

1.登录界面

2.游戏界面


2.3大作业总结

1.碰到问题及解决办法

1.登录页面的出错:无法同时输入账号密码,只能输入其中一个;
解决:这个问题在我试验用getchar吸收空格后有所解决,但是因为胡乱加了getchar程序又有了其他问题,在多次尝试后发现一个getchar就可以实现问题的解决;
2.
这个问题一开始我真的没思绪,主要在于函数定义都没有成功(有问过学长学姐),后来程序ok后发现是因为我定义了一个函数但是因为头文件中函数后已经有了“;",系统要对他进行解析,但是这是我的程序中并没有这个函数的具体代码,所以程序无法找到,只需要将函数的代码打出这个问题就不会出现;

3.这次文件的难点之一就是出题,出题的前提是将成语分出来同时能够随机输出其中两个,但是我的程序一直无法运行,在随机出题那出了问题;
解决:为了能够实现只显示两个字我选择使用二维数组,通过移动地址来实现数据的输出,同时将每一个结构体中的成语放到这个数组

2.小结

本次大作业困难之处就是对结构体以及文件的不熟悉,结构体传参出错了很多次,还有就是因为是多文件实现,所以函数传参特别麻烦,不像上次函数大作业那样传参特别方便,这次大作业中函数的每一个参数都要仔细斟酌,如果有一点没想好参就传不过去;同时因为是对文件进行处理,所以就涉及文件的打开,我的程序文件打开失败的情况就有很多次;
一开始没想到自己能将这次大作业最基本的框架写出来,虽然过程困难,但是通过这次大作业自己对结构体与文件的了解有了明显的加深

posted on 2019-12-15 21:53  linggu  阅读(621)  评论(2编辑  收藏  举报