[C 结构体 文件] 读取直线、矩形、圆混合文件,并查询指定类型

【需要读取的文件】

LINE
0 0 10 10
RECT
10 10 20 20
CIRCLE
20 20 40
RECT
20 20 40 40
LINE
12 34 56 78
LINE
56 78 100 200
CIRCLE
11 22 33
END

【结果】
[C 结构体 文件] 读取直线、矩形、圆混合文件,并查询指定类型

【完整答案】

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct{
	char type[10];
	union{
		struct Line{
			double x0;
			double y0;
			double x1;
			double y1;
		}line;
		struct Rect{
			double x;
			double y;
			double width;
			double height;
		}rect;
		struct Circle{
			double x;
			double y;
			double r;
		}circle;
	}attr;
}Geometry;
typedef struct node{
	Geometry data;
	struct node *next;
}LNode, * LinkList;

LinkList ReadFile(char str[]); //读入文件
	LNode* ReadNext(FILE **fpp); //读入下一个Geometry
void PrintAllType(LinkList L, char type[]); //输出type的所有Geomtry
	void PrintGeometry(Geometry data); //输出Geometry
LNode* FreeAll(LNode *p); //释放所有空间


int main() {
	LinkList p;
	char type[10];

	p = ReadFile("2014-10.txt");

	printf(">>> 请输入要查询要素的类型:"); //
	scanf("%s", type);
	PrintAllType(p, type);
	
	printf("\n正在删除.....\n");
	p = FreeAll(p);
	if (p==NULL) printf("\n删除成功\n");

	return 0;
}

LinkList ReadFile(char str[]) {
	LNode *p;
	FILE *fp;
	
	fp = fopen(str, "r"); 
	if (!fp) exit(0);
	p = ReadNext(&fp);
	fclose(fp);

	printf("读入完毕\n");

	return p;
}
LNode* ReadNext(FILE **fpp) {
	LNode *p;

	p = (LNode *)malloc(sizeof(LNode)); if (!p) exit(0);
	// 读类型
	fscanf(*fpp, "%s", p->data.type);
	if ( strcmp(p->data.type, "END")==0 ) { //退出
		printf("END\n");
		free(p);
		return NULL;
	}
	//读数值
	if (strcmp(p->data.type, "LINE")==0 ) {
		printf("LINE\n");
		fscanf(*fpp, "%lf%lf%lf%lf", &p->data.attr.line.x0, &p->data.attr.line.x1, &p->data.attr.line.y0, &p->data.attr.line.y1);
	} else if ( strcmp(p->data.type, "RECT")==0 ) {
		printf("RECT\n");
		fscanf(*fpp, "%lf%lf%lf%lf", &p->data.attr.rect.x, &p->data.attr.rect.y, &p->data.attr.rect.width, &p->data.attr.rect.height);
	} else if ( strcmp(p->data.type, "CIRCLE")==0 ) {
		printf("CIRCLE\n");
		fscanf(*fpp, "%lf%lf%lf", &p->data.attr.circle.x, &p->data.attr.circle.y, &p->data.attr.circle.r);
	}
	p->next = ReadNext(fpp);
	return p;
}
LNode* FreeAll(LNode *p) {
	LNode *next;
	if (!p) return NULL;

	next = p->next;
	printf("删除%s\n", p->data.type);
	free(p);
	return FreeAll(next);
}
void PrintAllType(LinkList L, char str[]) {
	if (!L) return ; //结束

	if ( strcmp(L->data.type, str)==0 ) {
		PrintGeometry(L->data);
	}

	PrintAllType(L->next, str);
}
void PrintGeometry(Geometry data) {
	printf("%s:", data.type);
	if ( strcmp(data.type, "LINE")==0 ) {
		printf("%lf %lf %lf %lf\n", data.attr.line.x0, data.attr.line.x1, data.attr.line.y0, data.attr.line.y1);
	} else if ( strcmp(data.type, "RECT")==0 ) {
		printf("%lf %lf %lf %lf\n", data.attr.rect.x, data.attr.rect.y, data.attr.rect.width, data.attr.rect.height);
	} else if ( strcmp(data.type, "CIRCLE")==0 ) {
		printf("%lf %lf %lf\n", data.attr.circle.x, data.attr.circle.y, data.attr.circle.r);
	}
}