In this assignment you will practice the usage of text and binary files in C. In doing so you will use the struct and union constructs to store related information in records. Last you will use the built-in sorting function (qsort) to sort your records and store them in the binary file. Your task is to manipulate geometric objects which are stored in a text file. You have to read the geometric objects and store them in a binary file.
The format of the text file is as follows: Each geometric object is stored on a separate line. The number of geometric objects in a file is given as the first field in the file. There are 4 geometric objects – circle, square, rectangle, and triangle. Each line, which represents a geometric object, has several fields. The number of fields is not consists and is object dependent. The first two fields in each line contain general information bout the objects:
The remaining fields in each line depend on the geometrical representation of the object.
Geometrical objects representations
1. Print objects 2. Sort objects by type 3. Sort objects by id 4. Store object in binary file 5. Read an object from file 6. quit
4 3 12345 50.0 175.0 40 30 2 346224 115.0 175.0 30 1 12 170.0 170.0 20 4 8987654 217.0 155.0 254.0 165.0 233.0 190.0
12 2 346224 115.0 175.0 30 2 6224 1115.0 213.50 3 1 1232 470.22 2170.0 12 4 9754 21 15 25 16 23.0 190.5 3 1 0 1 40 30 3 345 90 175.2 234 30 2 362 115.0 175.0 30 1 12 170.0 170.0 20 4 87654 17.0 55 154.0 65.0 33 190 1 569345 -70.0 170.0 15 3 3892 50.0 175.0 40 30 2 3424 -115.0 -175.0 30
#include<stdlib.h> #include<stdio.h> typedef struct list_head{ } LIST_HEAD; typedef struct circle{ float id; float x; long y; long a; } CIRCLE; typedef struct rectangle{ float id; double x; double y; short a; short b; } RECTANGLE; typedef struct square{ float id; float x; float y; long a; } SQUARE; typedef struct triangle{ float id; float x1; float y1; float x2; float y2; float x3; float y3; } TRIANGLE; typedef struct geomObj{ union { struct circle circle; struct square square; struct rectangle rectangle; struct triangle triangle; }theUnion; int id; short type; } GEOMOBJ;
#include<stdlib.h> #include<stdio.h> #include"dataStructures.h" int charToInt(char c); GEOMOBJ addCircle(float id, float x, float y, float a); GEOMOBJ addSquare(float id, float x, float y, float a); GEOMOBJ addRectangle(float id, float x, float y, float a, float b); GEOMOBJ addTriangle(float id, float x1, float y1, float x2, float y2, float x3, float y3); void printGeomObj(struct geomObj p); void printCircle(CIRCLE c); void printSquare(SQUARE c); void printRectangle(RECTANGLE c); void printTriangle(TRIANGLE c); int compareTypes(GEOMOBJ a, GEOMOBJ b); int compareIDs(GEOMOBJ a, GEOMOBJ b); int readTextFile(char *filename, struct geomObj **p);
#include<stdlib.h> #include<stdio.h> #include "functions.h" LIST_HEAD *createList(); //yeeea, 5 free points!! :) int readTextFile(char *filename, struct geomObj **p){ } // convert character to int (I know there exists a better way ;) ) int charToInt(char c){ int result=0; if (c=='0') result=0; if (c=='1') result=1; if (c=='2') result=2; if (c=='3') result=3; if (c=='4') result=4; if (c=='5') result=5; if (c=='6') result=6; if (c=='7') result=7; if (c=='8') result=8; if (c=='9') result=9; return result; } // all printing functions void printGeomObj(struct geomObj p){ if (p.type==1) printCircle (p.theUnion.circle); if (p.type==2) printSquare (p.theUnion.square); if (p.type==3) printRectangle (p.theUnion.rectangle); if (p.type==4) printTriangle (p.theUnion.triangle); } void printCircle(CIRCLE c){ printf(" CIRCLE id= %f, centre(%f, %f), radius= %f\n", c.id, c.x, c.y, c.a); } void printSquare(SQUARE c){ printf(" SQUARE id= %f, centre(%f, %f), width= %f\n", c.id, c.x, c.y, c.a); } void printRectangle(RECTANGLE c){ printf("RECTANGLE id= %f, centre=(%f, %f), length= %f, width= %f\n", c.id, c.x, c.y, c.a, c.b); } void printTriangle(TRIANGLE c){ printf("TRIANGLE id= %f, vertices(%f, %f) (%f, %f) (%f, %f)\n", c.id, c.x1, c.y1, c.x2, c.y2, c.x3, c.y3); } // all adding functions GEOMOBJ addCircle(float id, float x, float y, float a){ CIRCLE newCircle; newCircle.id=id; newCircle.x=x; newCircle.y=y; newCircle.a=a; GEOMOBJ object; object.id=id; object.type=1; object.theUnion.circle=newCircle; return object; } GEOMOBJ addSquare(float id, float x, float y, float a){ SQUARE newSquare; newSquare.id=id; newSquare.x=x; newSquare.y=y; newSquare.a=a; GEOMOBJ object; object.id=id; object.type=2; object.theUnion.square=newSquare; return object; } GEOMOBJ addRectangle(float id, float x, float y, float a, float b){ RECTANGLE newRectangle; newRectangle.id=id; newRectangle.x=x; newRectangle.y=y; newRectangle.a=a; newRectangle.b=b; GEOMOBJ object; object.id=id; object.type=3; object.theUnion.rectangle=newRectangle; return object; } GEOMOBJ addTriangle(float id, float x1, float y1, float x2, float y2, float x3, float y3){ TRIANGLE newTriangle; newTriangle.id=id; newTriangle.x1=x1; newTriangle.y1=y1; newTriangle.x2=x2; newTriangle.y2=y2; newTriangle.x3=x3; newTriangle.y3=y3; GEOMOBJ object; object.id=id; object.type=4; object.theUnion.triangle=newTriangle; return object; } //print the menu and ask for an answer. Return the answer number int printMenu(void){ printf("\n 1. Print objects\n 2. Sort objects by type\n 3. Sort objects by id\n 4. Store objects in binary file\n 5. Read an object from file\n 6. quit\n"); char ans=' '; scanf("%c", &ans); if (ans=='1') return charToInt(ans); else if (ans=='2') return charToInt(ans); else if (ans=='3') return charToInt(ans); else if (ans=='4') return charToInt(ans); else if (ans=='5') return charToInt(ans); else if (ans=='6') return charToInt(ans); else return 0; } //compare types of objects int compareTypes(GEOMOBJ a, GEOMOBJ b){ if (a.type>b.type) return -1; if (a.type==b.type) return 0; if (a.type<b.type) return 1; } //compare IDs of objects int compareIDs(GEOMOBJ a, GEOMOBJ b){ if (a.id>b.id) return -1; if (a.id==b.id) return 0; if (a.id<b.id) return 1; }
#include<stdlib.h> #include<stdio.h> #include "functions.h" FILE *inputFile; // this is input file (binary in future) FILE *outputFile; // this is output file (binary) char enteredFilename[255]; // filename string int main(int argc, char *argv[]){ if (argc!=0) inputFile = fopen (argv[1], "r"); //if filename was passed as argument, open this file if (argc==1) { printf("You have to type filename now: "); // if no arguments were passed - ask to type in a filename scanf("%s", enteredFilename); // typing inputFile=fopen(enteredFilename, "r"); } // and open it if (inputFile==NULL) printf("Error opening file\n"); // if not opened - error message if (inputFile!=NULL){ // if no errors found - go on int numberOfObjects=0; // total number of geom objects found in file int counter=0; // just a counter for loops int firstObject=0; // first object char line[80]; // to store first line fscanf(inputFile, "%d", &numberOfObjects); // read first line and get total number of objects printf("\nThe number of objects read into memory is %d\n", numberOfObjects); int objects[numberOfObjects]; //create an array of integers - every integer will be one object's number(type) fgets(line, 80, inputFile); while (counter<numberOfObjects) { //read every line's first character and storing in into array 'objects' - fgets(line, 80, inputFile); objects[counter]=charToInt(line[0]); counter++; } fclose(inputFile); //now we have an array as a catalogue of objects //close the file GEOMOBJ currentObjects[numberOfObjects]; //array of geom objects size of number of objects int garbage=0; fscanf(inputFile, "%d", &garbage); //we actually don't need this variable - this is just to get one line and go to another counter=0; float a1, a2, a3, a4, a5, a6, a7, a8; //maximum parameters is 8 while (counter<numberOfObjects){ a1=a2=a3=a4=a5=a6=a7=a8=0; if (objects[counter] == 1) { // if it's a circle fscanf(inputFile, "%f %f %f %f %f", &a1, &a2,&a3,&a4,&a5); currentObjects[counter]=addCircle(a2,a3,a4,a5); } if (objects[counter] == 2) { // if it's a sqaure fscanf(inputFile, "%f %f %f %f %f", &a1, &a2,&a3,&a4,&a5); currentObjects[counter]=addSquare(a2,a3,a4,a5); } if (objects[counter] == 3) { // if it's a rectanlge fscanf(inputFile, "%f %f %f %f %f %f", &a1, &a2,&a3,&a4,&a5, &a6); currentObjects[counter]=addRectangle(a2,a3,a4,a5, a6); } if (objects[counter] == 4) { // if it's a triangle fscanf(inputFile, "%f %f %f %f %f %f %f %f", &a1, &a2,&a3,&a4,&a5, &a6, &a7, &a8); currentObjects[counter]=addTriangle(a2,a3,a4,a5, a6, a7, a8); } counter++; } counter=0; int menuOption; while (menuOption!=6){ menuOption=printMenu(); if (menuOption==0) printf("Invalid option entered, please enter the number in range 1-6\n"); else if (menuOption==1) { // if '1' is pressed - print all the objects while (counter<numberOfObjects){ printGeomObj(currentObjects[counter]); counter++;} } else if (menuOption==2){ qsort((void *)&objects, numberOfObjects, sizeof(struct geomObj), (void *)compareTypes); while (counter<numberOfObjects){ printGeomObj(currentObjects[counter]); counter++; } } else if (menuOption==3){ qsort((void *)&objects, numberOfObjects, sizeof(struct geomObj), (void *)compareIDs); while (counter<numberOfObjects){ printGeomObj(currentObjects[counter]); counter++; } } // WRITE TO BINARY FILE else if (menuOption==4){ printf("\nPlease, enter the filename to save data: "); scanf("%s", enteredFilename); outputFile = fopen (enteredFilename, "w+b"); fwrite(objects, sizeof(GEOMOBJ), numberOfObjects, outputFile); if (outputFile!=NULL) printf("Binary file succesfully saved\n"); } //READ FROM BINARY FILE else if (menuOption==5){ printf("\nPlease, enter the filename to read data: "); scanf("%s", enteredFilename); outputFile = fopen (enteredFilename, "rb"); if (outputFile!=NULL) fread(objects, sizeof(GEOMOBJ), numberOfObjects, outputFile); while (counter<numberOfObjects){ printGeomObj(currentObjects[counter]); counter++; } } }} } //the end