Jednostavni invertar

Napraviti funkcionalnost jednostavnog invertara u RPG igri. Invertar sadrži predmete, gde svaki predmet ima svoj naziv, težinu i vrednost.

Rešiti zadatak u više fajlova: main.c, item.h, item.c, inventory.h inventory.c.

Predmet (Item) treba da podržava sledeće funkcionalnosti:

Invertar (Invertory) treba da podržava sledeće funkcionalnosti:

Dodatno: Proširiti funkcionalnosti invertara funkcijama po sopstvenom nahođenju.

Ulaz

Sa standardnog ulaza se unosi broj upita $q$ ($1 \leq q \leq 10$). Zatim se unose $q$ upita oblika:

Pretpostaviti da naziv predmeta nije veći od $20$, kao i da će se u invertar smeštati najviše $50$ predmeta, kao i da neće biti nevalidnih upita.

Izlaz

Na standardni izlaz ispisati, za svaki od upita w, i v odgovarajuću vrednost, za svaki od upita W i V ispisati odgovarajući predmet u formatu <name>{w=<w>,v=<v>}, i za svaki upit p ispisati invertar u formatu [ <it1>, <it2>, ..., <itn> ].

Primer

Ulaz

5
a sword 10 100
a shield 15 80
p
w
v

Izlaz

[ sword{w=10,v=100}, shield{w=15,v=80} ]
25
180

Primer

Ulaz

6
a apple 1 2
a rock 30 1
a gold 2 50
W
V
p

Izlaz

rock{w=30,v=1}
gold{w=2,v=50}
[ apple{w=1,v=2}, rock{w=30,v=1}, gold{w=2,v=50} ]

Rešenje

item.h

#ifndef ITEM_H
#define ITEM_H

#define MAX_NAME_LENGTH 20

typedef struct Item {
    char name[MAX_NAME_LENGTH + 1];
    int weight;
    int value;
} Item;

Item item_make(char name[MAX_NAME_LENGTH + 1], int w, int v);

void item_print(Item it);

int item_cmp_by_weight(Item a, Item b);
int item_cmp_by_value(Item a, Item b);

#endif // ITEM_H

inventory.h

#ifndef INVENTORY_H
#define INVENTORY_H

#include "item.h"

#define MAX_INVENTORY_SIZE 50

typedef struct Inventory {
    Item items[MAX_INVENTORY_SIZE];
    int size;
} Inventory;

// Better to use pointers for passing and returning large structs (see later lectures)

Inventory inv_empty(void);
Inventory inv_add(Inventory inv, Item it);

void inv_print(Inventory inv);

int inv_total_weight(Inventory inv);
int inv_total_value(Inventory inv);

Item inv_max_weight(Inventory inv);
Item inv_max_value(Inventory inv);

#endif // INVENTORY_H

item.c

#include "item.h"
#include <string.h>
#include <stdio.h>

Item item_make(char name[MAX_NAME_LENGTH + 1], int w, int v)
{
    Item it;

    strncpy(it.name, name, MAX_NAME_LENGTH);
    it.name[MAX_NAME_LENGTH] = '\0';

    it.weight = w;
    it.value = v;

    return it;  
}

void item_print(Item it)
{
    printf("%s{w=%d,v=%d}", it.name, it.weight, it.value);
}

int item_cmp_by_weight(Item a, Item b)
{
    return a.weight - b.weight;
}

int item_cmp_by_value(Item a, Item b)
{
    return a.value - b.value;
}

inventory.c

#include "inventory.h"
#include <stdio.h>

Inventory inv_empty(void)
{
    Inventory inv;

    inv.size = 0;

    return inv;
}

Inventory inv_add(Inventory inv, Item it)
{
    if (inv.size < MAX_INVENTORY_SIZE) {
        inv.items[inv.size] = it;
        inv.size++;
    }

    return inv;
}

void inv_print(Inventory inv)
{
    printf("[ ");
    for (int i = 0; i < inv.size; i++) {
        item_print(inv.items[i]);
        if (i < inv.size - 1) {
            printf(", ");
        }
    }
    printf(" ]\n");
}

int inv_total_weight(Inventory inv)
{
    int total_weight = 0;
    for (int i = 0; i < inv.size; i++) {
        total_weight += inv.items[i].weight;
    }
    return total_weight;
}

int inv_total_value(Inventory inv)
{
    int total_value = 0;
    for (int i = 0; i < inv.size; i++) {
        total_value += inv.items[i].value;
    }
    return total_value;
}

Item inv_max_weight(Inventory inv)
{
    Item max_item = { "", -1, 0 };

    for (int i = 0; i < inv.size; i++) {
        if (item_cmp_by_weight(inv.items[i], max_item)) {
            max_item = inv.items[i];
        }
    }

    return max_item;
}

Item inv_max_value(Inventory inv)
{
    Item max_item = { "", 0, -1 };

    for (int i = 0; i < inv.size; i++) {
        if (item_cmp_by_value(inv.items[i], max_item)) {
            max_item = inv.items[i];
        }
    }

    return max_item;
}

main.c

#include <stdio.h>

#include "item.h"
#include "inventory.h"

int main(void)
{
	int q;
	scanf("%d", &q);

	Inventory inv = inv_empty();

	while (q--) {
		char op;
		scanf(" %c", &op); // note the space before %c to skip previous newline
		if (op == 'a') {
			char name[MAX_NAME_LENGTH + 1];
			int w, v;
			scanf("%s %d %d", name, &w, &v);
			inv = inv_add(inv, item_make(name, w, v));
		} else if (op == 'p') {
			inv_print(inv);
		} else if (op == 'w') {
			printf("%d\n", inv_total_weight(inv));
		} else if (op == 'v') {
			printf("%d\n", inv_total_value(inv));
		} else if (op == 'W') {
			Item it = inv_max_weight(inv);
			item_print(it);
			printf("\n");
		} else if (op == 'V') {
			Item it = inv_max_value(inv);
			item_print(it);
			printf("\n");
		}
	}

	return 0;
}

Makefile

CC = gcc
CFLAGS = -Wall -Wextra -pedantic

.PHONY: all clean

all: main

main: main.o item.o inventory.o
	$(CC) $(CFLAGS) -o main main.o item.o inventory.o

main.o: main.c item.h inventory.h
	$(CC) $(CFLAGS) -c main.c -o main.o

item.o: item.c item.h
	$(CC) $(CFLAGS) -c item.c -o item.o

inventory.o: inventory.c inventory.h item.h
	$(CC) $(CFLAGS) -c inventory.c -o inventory.o

clean:
	rm -f main.o item.o inventory.o main