Assignment 4

Preface

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:

  1. objectId - this is the first field. This is a numeric filed which contains an integer number between 1-12,000,000
  2. objectType - this is the second field. It is a numeric field in the range of 1-4.
    1. Value == 1 – this means that the object is a circle
    2. Value == 2 – this means that the object is a square
    3. Value == 3 – this means that the object is a rectangle
    4. Value == 4 – this means that the object is a triangle

The remaining fields in each line depend on the geometrical representation of the object.

Geometrical objects representations

  • A circle is represented by its centre and its radius. Thus it contains three fields
    • A real value (float) – this field is the x-coordinate of centre of the circle
    • A real value (float) – this field is the y-coordinate of centre of the circle
    • An integer value (long) – this field is the radius of the circle
  • A square is represented by its centre and its width. Therefore it contains three fields
    • A real value (float) – this field is the x-coordinate of centre of the square
    • A real value (float) – this field is the y-coordinate of centre of the square
    • A real value (long) – this field is the width of the square
  • A rectangle is represented by its centre and its width and height. Therefore it contains four fields
    • A real value (double) – this field is the x-coordinate of the centre of the rectangle
    • A real value (double) – this field is the y-coordinate of the centre of the rectangle
    • An integer value (short) – this field is the width of the rectangle
    • An integer value (short) – this field is the length of the rectangle
  • A triangle is represented by its three vertices. Therefore it contains six fields
    • A real value (float) – this field is the x-coordinate of the bottom first vertex
    • A real value (float) – this field is the y-coordinate of the bottom second vertex
    • A real value (float) – this field is the x-coordinate of the bottom second vertex
    • A real value (float) – this field is the y-coordinate of the bottom second vertex
    • A real value (float) – this field is the x-coordinate of the bottom third vertex
    • A real value (float) – this field is the y-coordinate of the bottom third vertex

Requirements

  • Reading text file – the text file name will be given as part of the command line. If the file name is not given then the program must ask the user to enter the text file name.
  • Once the input file name is given the program should read the geometrical objects into memory.
    • Note that the program must allocate the correct number of records according to the information in the first line of the file.
    • The array, used to contain the geometrical object, must be declared using struct geomObj.
  • Present the user with the following menu

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

  • Print objects – this function must print all the objects that are stored in memory. The printing should be done as follows:
  • Sort objects by type – this function will sort the objects in the array according to their type. Namely, all circles followed by all squares, followed by all rectangles and last all triangles.
  • Sort objects by id – this function will sort the objects in the array according to their id.
  • Store objects in binary file – this function will ask the user for a file name and then save all the objects in the file.
  • Read an object from file – this function will read a geometrical record from a file. The program will ask the user for a file name. If the file name does not exist it should request another file name. If the file exists then the program will ask the user which object number to read from a given range. Namely, the program should present the user with a valid range of object numbers. The prompt should be “Enter record number to be range (valid range is 1-xx) :” where xx represent the number of records in the file.
  • Quit – close all files and quit.

Solution

A4_sample1.txt

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

A4_sample2.txt

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

data_structures.h

#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;

functions.h

#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);

functions.c

#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;
}

mainfile.c

#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

 
sources/2007/linux_and_c/assignment_4.txt · Последние изменения: 2010/03/05 07:27 От freetonik
 
За исключением случаев, когда указано иное, содержимое этой вики предоставляется на условиях следующей лицензии:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki