Laborarory: Structures

Gábor Horváth / Zsolt Kohári · 2020.10.14.

Creation and use of structures.

1. Competitors

The results of a running competition are shown in the table below.

IndexNameBirthdateRank
0Am, Erica1984. 05. 06.1
1Abnorm, Al1982. 09. 30.3
2Pri, Mary1988. 08. 25.2
3Duck, Ling1979. 06. 10.5
4Mac, Donald1992. 04. 05.4

Find an unfinished program below that contains the appropriate types and the above data in an array. Complete the program, step-by-step, according to the comments.

#include <stdio.h>

typedef struct Date {
    int year, month, day;
} Date;

typedef struct Competitor {
    char name[31];
    Date birth;
    int rank;
} Competitor;

void Date_print(Date d);

void Competitor_print(Competitor c);

int main() {
    Competitor competitors[5] = {
        { "Am, Erica", {1984, 5, 6}, 1 },
        { "Abnorm, Al", {1982, 9, 30}, 3 },
        { "Pri, Mary", {1988, 8, 25}, 2 },
        { "Duck, Ling", {1979, 6, 10}, 5 },
        { "Mac, Donald", {1992, 4, 5}, 4 },
    };

    /* name of competitor 0 - printf %s */
    /* rank of competitor 2 */
    /* birth date of competitor 4, use the given function */
    /* the first letter of the name of competitor 1 (a string is an array of characters) */
    /* is competitor 1 among the best three? yes/no, may use ?: operator */
    /* is competitor 4 faster than competitor 3? */
    /* was competitor 1 born in the same year as competitor 2? */
    /* complete the Competitor_print() function,
     * then print all data of competitor 1 */
    /* at last print all data of all competitors. */

    return 0;
}

void Date_print(Date d) {
    /* print year, month and day */
}

void Competitor_print(Competitor c) {
    /* print all data of the competitor */
}

Solution

#include <stdio.h>

typedef struct Date {
    int year, month, day;
} Date;

typedef struct Competitor {
    char name[31];
    Date birth;
    int rank;
} Competitor;

void Date_print(Date d);

void Competitor_print(Competitor c);

int main() {
    Competitor competitors[5] = {
        { "Am, Erica", {1984, 5, 6}, 1 },
        { "Abnorm, Al", {1982, 9, 30}, 3 },
        { "Pri, Mary", {1988, 8, 25}, 2 },
        { "Duck, Ling", {1979, 6, 10}, 5 },
        { "Mac, Donald", {1992, 4, 5}, 4 },
    };

    /* name of competitor 0 - printf %s */
    printf("%s\n", competitors[0].name);
    /* rank of competitor 2 */
    printf("%d\n", competitors[2].rank);
    /* birth date of competitor 4, use the given function */
    Date_print(competitors[4].birth);
    /* the first letter of the name of competitor 1 (a string is an array of characters) */
    printf("%c\n", competitors[1].name[0]);
    /* is competitor 1 among the best three? yes/no, may use ?: operator */
    printf("%s\n", competitors[1].rank <= 3 ? "yes" : "no");
    /* is competitor 4 faster than competitor 3? */
    printf("%s\n", competitors[4].rank < competitors[3].rank ? "yes" : "no");
    /* was competitor 1 born in the same year as competitor 2? */
    printf("%s\n", competitors[1].birth.year == competitors[2].birth.year ? "yes" : "no");
    /* complete the Competitor_print() function,
     * then print all data of competitor 1 */
     Competitor_print(competitors[1]);
    /* at last print all data of all competitors. */
    for (int i = 0; i < 5; ++i) {
        printf("%d. ", i);
        Competitor_print(competitors[i]);
    }

    return 0;
}

void Date_print(Date d) {
    printf("%d.%d.%d.\n", d.year, d.month, d.day);
}

void Competitor_print(Competitor c) {
    printf("%s, %d.%d.%d., %d\n", c.name, c.birth.year, c.birth.month, c.birth.day, c.rank);
}

2. Circles

Write a program to store the parameters of a circle on a 2D plane: the x and y coordinates of the center point and r, the radius. All three parameters are real (floating point) numbers.

  • Define a type to store the parameters of a circle.
  • Write a function that receives the parameters of two circles as function parameters, and returns whether the two circles overlap or not. (Two circles overlap if the distance between their center points - computed by the Pythagorean theorem - is less than the sum of their radius.)
  • Write a function that asks the user to enter the parameters of a circle, creates the circle, and returns it.
  • Expand the type definition and the functions to a program that reads the data of two circles, decides if they overlap, and displays a message accordingly.

Solution

#include <stdio.h>
#include <math.h>
#include <stdbool.h>

typedef struct Circle {
    double x, y, r;
} Circle;

Circle circle_read() {
    Circle c;
    scanf("%lf %lf %lf", &c.x, &c.y, &c.r);
    return c;
}

int circle_overlap(Circle c1, Circle c2) {
    return sqrt(pow(c1.x-c2.x, 2)+pow(c1.y-c2.y, 2)) < c1.r+c2.r;
}

int main() {
    Circle a, b;
    a = circle_read();
    b = circle_read();
    printf("%s\n", circle_overlap(a, b) ? "They overlap." : "They dont overlap.");
    return 0;
}

3. Fence

Let us define a Point type to store two-dimensional coordinates (x, y)! Write the following functions operating on this data type:

  • dist(): calculates the distance between the two points received (using the Pythagorean theorem)
  • equal(): checks if to points are equal or not
  • read(): reads a point from the keyboard and returns it

In the main, define two points, and test all these functions. When all tests are passed, solve the following task by utilizing the structure and functions defined above:

A farmer wants to surround his land with a wire fence. Write a program to compute how much fence is required! The program asks the farmer to enter the coordinates of the corner points of the fence, calculates the distances, and sums them up. Repeat these steps as long as the new coordinates are not equal to the first one (hence, till we return to the starting point).

It is recommended to store the starting point in a separate variable. After that, two more point variables are needed to calculate the length of a fence segment: one of them stores the current point, and the other the previous one.

Solution

No arrays are needed to solve the task: we always have to remember the previous coordinates only, which will be enough to calculate the length of the new section. Storing the first point in a variable enables us to detect when to stop reading the input and print the result of the program.

#include <stdio.h>
#include <math.h>
#include <stdbool.h>

typedef struct Point {
    double x, y;
} Point;

double dist(Point p1, Point p2) {
    return sqrt(pow(p1.x-p2.x, 2) + pow(p1.y-p2.y, 2));
}

int equal(Point p1, Point p2) {
    return p1.x == p2.x && p1.y == p2.y;
}

Point read(void) {
    Point p;
    scanf("%lf%lf", &p.x, &p.y);
    return p;
}

int main(void) {
    /* Reading the starting point, which is the ending point, too */
    printf("Starting point:\n");
    Point start;
    start = read();

    /* Summation */
    double length = 0;
    printf("Further points:\n");
    Point prev;     /* stores the previous point */
    Point current;  /* stores the new point */
    prev = start;
    do {
        current = read();
        length += dist(prev, current);
        prev = current;        /* for the next iteration */
    } while (!equal(current, start));

    /* Print the sum */
    printf("The length of the fence: %f\n", length);

    return 0;
}

4. Further problems for practicing

Vectors

It was a short test

2D vectors are needed to store in a program. Like velocity: vx horizontal, vy vertical components of the speed describe the v velocity vector.

  • Define a type to store a velocity vector.
  • Write a function that receives a velocity vector and returns the length of the vector (Pythagorean theorem).
  • Write a function that receives two velocity vector parameters and returns their sum as a velocity vector (add the components).
  • Write a program that defines two velocity vectors: (1 m/s, 2 m/s) and (-0.5 m/s, 3 m/s), calculates their sum and prints the result. Then calculate the length of the sum vector and print it.