Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdbool.h>
- #include <math.h>
- #include <string.h>
- #include <stdlib.h>
- // Read coordinates X, Y for point @point_name, place them in @output
- #define INPUT_COORDS_POINT(point_name, output) \
- printf("Enter coordinate X for %s:\n", point_name); \
- scanf("%lf",output.x); \
- printf("Enter coordinate Y for %s:\n", point_name); \
- scanf("%lf",output.y);
- //#define OUTPUT_COORDS_POINT(polygon, point) \
- // printf("(%f,%f)", polygon. point.x, polygon.point.y);
- #define OUTPUT_COORDS_POINT(point) \
- printf("(%f,%f)", point.x, point.y);
- // For debugging and researching purposes
- void printBits(unsigned char n) {
- unsigned bitLength = sizeof(unsigned char) * 8;
- int count = 0;
- for (int bitPos = bitLength - 1; bitPos >= 0; bitPos--) {
- if (count == 4) putchar(' ');
- if ((n & (1 << bitPos)) == 0) {
- putchar('0');
- } else {
- putchar('1');
- }
- count++;
- }
- putchar('\n');
- }
- enum geometric_type {
- t_circle = 1,
- t_triangle = 2,
- t_rectangle = 3
- };
- typedef struct _point {
- double x, y;
- } point;
- typedef struct _circle {
- point center;
- unsigned int radius;
- } circle;
- typedef struct _triangle {
- point A;
- point B;
- point C;
- } triangle;
- typedef struct _rectangle {
- point A;
- point B;
- point C;
- point D;
- } rectangle;
- // WARNING: this will always access the first three points in the rectangle (rec.A, rec.B and rec.C)
- // It is the caller's responsibility to make sure these are declared beforehand.
- bool isValidRectangleDefinition(rectangle rec) {
- // we "move" B and C such that they can be considered vectors starting from the origin (0,0)
- // graphical explanation below
- point b, c;
- b.x = rec.B.x - rec.A.x; // (?):
- b.y = rec.B.y - rec.A.y; // is there an easier
- c.x = rec.C.x - rec.B.x; // or shorter way
- c.y = rec.C.y - rec.B.y; // of doing this?
- if (1.0 * b.x * c.x + 1.0 * b.y * c.y == 0) { // the dot product is 0 meaning that the vectors are perpendicular
- return true;
- }
- return false;
- }
- /*
- y ^ y ^
- | |
- | A (1, 1) turns to |
- | |
- | + |
- | | |
- | | |
- +----------------------------> +---------------->----------->
- | | |
- | | x | C (2, 0) x
- | v---------> |
- | |
- | B (1, -1) C (3, -1) |
- | v B (0, -2)
- | |
- | |
- + +
- */
- typedef struct _geometric_object {
- unsigned char shape : 2; // actually useless but I need to use bit fields somewhere
- // makes the switch statement in the reading function unsafe too...
- union {
- circle c;
- triangle t;
- rectangle r;
- };
- } geometric_object;
- void readGeometricObject(geometric_object *obj) {
- geometric_object input;
- unsigned char c;
- printf("What is the shape of the geometric object being defined?\n"
- "1. Circle\n"
- "2. Triangle\n"
- "3. Rectangle\n"
- "0. Abort\n");
- scanf("%hhu", &c);
- switch (c) {
- case t_circle:
- obj->shape = t_circle;
- printf("Enter coordinate X for the center:\n");
- scanf("%lf", &obj->c.center.x);
- printf("Enter coordinate Y for the center:\n");
- scanf("%lf", &obj->c.center.y);
- printf("Enter the radius:\n");
- scanf("%u", &obj->c.radius);
- break;
- case t_triangle:
- obj->shape = t_triangle;
- INPUT_COORDS_POINT("A", &obj->t.A)
- INPUT_COORDS_POINT("B", &obj->t.B)
- INPUT_COORDS_POINT("C", &obj->t.C) // these may or may not define a line (the points A,B,C)
- break;
- case t_rectangle:
- obj->shape = t_rectangle;
- INPUT_COORDS_POINT("A", &obj->r.A)
- INPUT_COORDS_POINT("B", &obj->r.B)
- bool valid;
- do {
- INPUT_COORDS_POINT("C", &obj->r.C)
- valid = isValidRectangleDefinition(obj->r);
- if (!valid) {
- printf("A, B and C cannot form a rectangle as they are not making a right angle. Enter point C again:\n");
- }
- } while (!valid);
- obj->r.D.x = (obj->r.C.x - obj->r.B.x) + obj->r.A.x;
- obj->r.D.y = (obj->r.C.y - obj->r.B.y) + obj->r.A.y;
- break;
- case 0:
- printf("Aborting...\n");
- break;
- default:
- printf("Invalid shape\n");
- }
- }
- void printGeometricObject(const geometric_object *obj) {
- switch (obj->shape) {
- case t_circle:
- printf("Circle defined by center (%f,%f) with radius %u\n", obj->c.center.x, obj->c.center.y,
- obj->c.radius);
- break;
- case t_triangle:
- printf("Triangle defined by points ");
- /*for (char ch = 'A'; ch <= 'C' ; ++ch){ // how would I go around doing this?
- OUTPUT_COORDS_POINT(&obj.t, ch)
- }*/
- printf("A ");
- OUTPUT_COORDS_POINT(obj->t.A)
- printf(", B ");
- OUTPUT_COORDS_POINT(obj->t.B)
- printf(", C ");
- OUTPUT_COORDS_POINT(obj->t.C)
- printf(".\n");
- break;
- case t_rectangle:
- printf("Rectangle defined by points ");
- printf("A ");
- OUTPUT_COORDS_POINT(obj->r.A)
- printf(", B ");
- OUTPUT_COORDS_POINT(obj->r.B)
- printf(", C ");
- OUTPUT_COORDS_POINT(obj->r.C)
- printf(", D ");
- OUTPUT_COORDS_POINT(obj->r.D)
- printf(".\n");
- break;
- default:
- printf("Object shape undefined.\n");
- }
- }
- // ----- HOME EXERCISES ----- //
- /*1. A simple classification of stars is as follows:
- *
- * (a) Main Sequence Stars characterized by: age category (an integer
- * value between 1 and 4) and color (a character array of at most
- * 12 characters)
- * (b) Binary Stars rotating around a mass center characterized by:
- * rotation radius for the first and the second star
- * (c) Variable Light Stars characterized by: lowest luminosity, highest
- * luminosity and light periodicity measured in Earth days
- *
- * All stars have a name of arbitrary length. Use composite variables
- * and bit fields and write a program that reads data about a star and
- * then prints it back on the screen.*/
- typedef struct _main_sequence_star {
- unsigned age; // integer between 1 and 4
- char color[13];
- } msStar;
- typedef struct _binary_star {
- unsigned firstStarRotationRadius : 16;
- unsigned secondStarRotationRadius : 16;
- } bStar;
- typedef struct _variable_light_star {
- // Stellar luminosity is characterized by the size of the star measured in
- // solar radii and its effective temperature measured in Kelvin, but for the
- // sake of simplicity I will only measure it in positive integer values
- // representing Bolometric luminosity (in solar units). The most luminous
- // star listed on Wikipedia is R136a1 measuring in at 8,710,000 su.
- // Here's the wiki page for reference:
- // https://en.wikipedia.org/wiki/List_of_most_luminous_stars
- unsigned lowLuminosity : 24;
- unsigned highLuminosity : 24; // values up to 16,777,215
- unsigned periodicity : 16;
- } vlStar;
- typedef struct _star {
- char *name;
- enum _class {
- t_ms,
- t_b,
- t_vl
- } class;
- union {
- msStar ms;
- bStar b;
- vlStar vl;
- };
- } Star;
- char *readString() {
- #define CHUNK 32
- char *input = NULL;
- char buf[CHUNK];
- size_t inputLength = 0, bufLength = 0;
- do {
- if (fgets(buf, CHUNK, stdin)) {
- bufLength = strlen(buf);
- input = realloc(input, inputLength + bufLength);
- strcpy(&input[inputLength], buf); // buf is guaranteed to have a null terminating character
- inputLength += bufLength;
- }
- } while ((bufLength == CHUNK - 1) && buf[CHUNK - 2] != '\n');
- return input;
- }
- Star readStar() {
- Star star;
- printf("Name of the star:\n");
- // reading the arbitrarily long string
- star.name = readString();
- printf("Type of star:\n"
- "(a) Main Sequence Star\n"
- "(b) Binary Star\n"
- "(c) Variable Light Star\n");
- char type;
- scanf("%c", &type);
- switch (type) {
- case 'a':
- star.class = t_ms;
- printf("Age (integer between 1 and 4):\n");
- scanf("%u", &star.ms.age);
- while (star.ms.age < 1 || star.ms.age > 4) {
- printf("Age out of range. Enter an integer between 1 and 4:\n");
- scanf("%u", &star.ms.age);
- }
- printf("Color (maximum of 12 characters):\n");
- fgets(star.name, 12, stdin);
- break;
- default:
- printf("Undefined classification\n");
- }
- return star;
- }
- int main() {
- // Exercise 0 //
- /*int listLength = 3;
- geometric_object list[listLength];
- *//*for (int i = 0; i < 3; ++i) {
- readGeometricObject(&list[i]);
- }
- for (int i = 0; i < 3; ++i) {
- printGeometricObject(&list[i]);
- }*//*
- readGeometricObject(&list[0]);
- printGeometricObject(&list[0]);*/
- // Exercise 1 //
- Star st = readStar();
- return 0;
- }
- /* QUESTIONS:
- * ----- Exercise 0: Geometric shapes -----
- * 1. ---DISMISSED--- The problem was solved by itself (somehow): I declared the function as a geometric_object type
- * function as a workaround (with no parameters, planning on just simply returning the variable @input) but returned
- * to my initial idea. Initial question:
- * ### I cannot use "geometric_object" instead of "struct _geometric_object" as a function parameter (compiler will not
- * recognize geometric_object as a type in this case). Why is that? ###
- * 2. Why is memmove a better approach than memset in the case of overlapping memory blocks? Is there undefined
- * behaviour involved?
- * 3. See function isValidRectangleDefinition().
- * 4. See function printGeometricObject().
- * 5. How would I go about making a delete function which sets all the values in a geometric_object type variable
- * to 0? I know the size of the union will be sizeof(rectangle) but what about the @shape?
- *
- * ----- Exercise 1: Stars -----
- * 1. Should I free() the stars' names at the end of main even if they get freed after terminating the program?
- * 2. True or not?
- * "Size of char is always 1 byte, regardless of whether 1 byte means 8 bits or not"
- * Should I ever call sizeof(char)?
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement