Tablica struktur i zwiekszanie wskaźnika

0

Napisałem dla treningu mały program, który służy do rezerwacji miejsc w 12-sto miejscowym samolocie. Menu programu wygląda następująco:
Aby wybrac opcje wpisz jej oznaczenie literowe
a) Pokaz liczbe pustych miejsc
b) Pokaz liste pustych miejsc
c) Zarezerwuj miejsce dla klienta
d) Usun rezerwacje miejsca
e) Wyjdz

Oto kod programu:

#include <stdio.h>
#define MIEJSCA 12
#define ROZ 50

struct samolot {
	int numer_id;
	int flaga;
	char imie[ROZ];
	char nazw[ROZ];
};

void usun_wiersz(void)
{
	while(getchar() != '\n')
		continue;
}

int pokaz_menu(void)
{
	int odp;
	
	puts("Aby wybrac opcje wpisz jej oznaczenie literowe");
	puts("a) Pokaz liczbe pustych miejsc");
	puts("b) Pokaz liste pustych miejsc");
	puts("c) Zarezerwuj miejsce dla klienta");
	puts("d) Usun rezerwacje miejsca");
	puts("e) Wyjdz");
	odp = tolower(getchar());
	usun_wiersz();
	while(strchr("abcdef", odp) == NULL)
	{
		puts("Wpisano nieprawidlowa opcje. Sprobuj jeszcze raz");
		odp = tolower(getchar());
		usun_wiersz();
	}
	return odp;
}

int liczba_wolnych(struct samolot * wsk)
{
	int liczba = 0, i = 0;
	
	while(i<MIEJSCA)
	{
		if(wsk->flaga == 0)
			liczba++;
		wsk++;
		i++;
	}
	printf("Pozostalo %d wolnych miejsc.\n\n", liczba);
}

void lista_wolnych(struct samolot * wsk)
{
	int i = 0;
	
	puts("Lista wolnych miejsc:");
	while(i<MIEJSCA)
	{
		if(wsk->flaga == 0)
			printf("%d ", wsk->numer_id);
		wsk++;
		i++;
	}
	printf("\n\n");
}

void zarezerwuj(struct samolot * wsk)
{
	int wybor, i;
	
	puts("Podaj numer miejsca, ktory chcesz zarezerwowac. Wpisz EOF, aby zakonczyc.");
	if(scanf("%d", &wybor) == 1)
	{
		usun_wiersz();
		for(i=1; i<wybor; i++)
			wsk++;
		if(wybor > 0 && wybor < 13 && wsk->flaga == 0)
		{
			puts("Podaj imie osoby rezerwujacej:");
			gets(wsk->imie);
			puts("Podaj nazwisko osoby rezerwujacej:");
			gets(wsk->nazw);
			wsk->flaga = 1;
			puts("Miejsce zostalo zarezerwowane!\n");
			
		}
		else if(wsk->flaga == 1)
		{
			puts("To miejsce jest juz zarezerwowane!\n");
			
		}
		else
		{
			puts("Nie ma miejsca o takim numerze.\n");
			
		}
	}
}

void usun_rezerwacje(struct samolot * wsk)
{
	int wybor, i;
	
	puts("Podaj numer miejsca, ktorego rezerwacje chcesz usunac.");
	while(scanf("%d", &wybor) == 1)
	{
		usun_wiersz();
		for(i=1; i<wybor; i++)
			wsk++;
		if(wybor > 0 && wybor < 13 && wsk->flaga == 1)
		{
			wsk->flaga = 0;
			puts("Rezerwacja anulowana\n");
			break;
		}
		else if(wsk->flaga == 0)
		{
			puts("To miejsce nie jest zarezerwowane!\n");
			break;
		}
		else
		{
			puts("Nie ma miejsca o takim numerze.\n");
			break;
		}
	}
}

int main(void)
{
	struct samolot dane[MIEJSCA] = {
		{1, 0},
		{2, 0},
		{3, 0},
		{4, 0},
		{5, 0},
		{6, 0},
		{7, 0},
		{8, 0},
		{9, 0},
		{10, 0},
		{11, 0},
		{12, 0}
	};
	int wybor;
	
	while((wybor = pokaz_menu()) != 'e')
	{
		switch(wybor)
		{
			case 'a' : liczba_wolnych(dane); break;
			case 'b' : lista_wolnych(dane); break;
			case 'c' : zarezerwuj(dane); break;
			case 'd' : usun_rezerwacje(dane); break;
		}
	}
	
	putchar('\n');
	system("pause");
	return 0;
}

Ogólnie wszystko działa, ale mam pytania co do tego programu.

  1. Funkcja rezerwująca miejsce i anulująca rezerwację mają podobną budowę, ale w jednej zastosowałem na początku instrukcje if, a druga rozpoczyna się od pętli while, ale przy okazji zawiera też instrukcję break. Stąd moje pytanie: która wersja jest lepsza i jak patrzycie na instrukcję break w pętli? Kolega mówił mi, że na jego uczelni profesor od programowania stawia dwóję za użycie instrukcji break w pętli. Czy rzeczywiście jest to aż tak nieodpowiednie?
  2. Program korzysta ze struktur. I tak w funkcji main po wyborze opcji "d" program wywołuje funkcję "zarezerwuj" i przekazuje jej adres pierwszego elementu tablicy struktur. Później jeżeli użytkownik wpisze, że chce zarezerwować - dla przykładu - miejsce 5, to stosuje funkcje for do zwiększenia wskaźnika, mianowicie:
    for(i=1; i<wybor; i++)
    wsk++;
    Czy jest jakiś inny, prostszy/lepszy sposób na zwiększenie tego wskaźnika? Ten sposób działa, ale myślę, że musi istnieć jakieś lepsze rozwiązanie.
0
  1. Obie wyglądają tak sobie. Chociaż samo break nie razi mnie jako takie praktycznie wcale, to tutaj użyte jest całkowicie bez sensu i trzeba by to rozplanować moim zdaniem inaczej.
    Moim zdaniem jeżeli funkcja nazywa się usun_rezerwacje, to ma po prostu usunąć rezerwację, ustawiasz flagę na 0, koniec, jako parametr przekazujesz numer miejsca. A numer rezerwacji pobierasz w oddzielnej funkcji. Jeżeli będziesz tak mieszał, to gdy projekt się rozrośnie, a Ty będziesz chciał zamiast prostej flagi w tablicy użyć np. bazy danych, będziesz musiał zamienić to w każdym miejscu ręcznie :/ mało przyjemne.
    A flagę opakowałbym w enum.
  2. Tablica, nie jestem pewien do końca ale chyba jak dasz [wybor] (sprawdź najpierw czy się zgadza zakres) to powinno działać ew. daj wsk+(wybor*sizeof(...)), najlepiej w oddzielnej funkcji
0

No właśnie najtrudniejsze jest to przejście z pisania programów na ich projektowanie. Szczerze mówiąc to podszedłem do tego zadanie z marszu, a wiem, że to niepoprawne podejście. Dlatego właśnie rozwiązania, które zastosowałem nie są optymalne.

Co do funkcji usun_rezerwacje to ona powinna po pierwsze, ustawiać flagę na zero, a po drugie usuwać imię i nazwisko z pól imie i nazw struktury. Wiesz może jak można to zrobić? Próbowałem przypisać tym polom pusty łańcuch czyli coś w stylu

wsk->imie = "";

Ale taka instrukcja jest niepoprawna, w sumie się nie dziwię. Jak w takim razie można usunąć łańcuch z tego pola?

dodanie znacznika <code class="c"> i `` - fp

1

wsk->imie oraz (*wsk).imie oraz wsk[0].imie to trzy wersji oznaczające jedno i to samo dostanie się do składowej imie która jest tablicą.
Aby ta tablica zawierała pusty napis trzeba w jej pierwszy element wpisać 0.
można to zrobić na 2 sposoby: *tab=0; lub tab[0]=0;
Więc na twój problem było 6 rozwiązań z których wybrałem najkrótsze.
Można np napisać to samo tak: wsk[0].imie[0]=0;

1 użytkowników online, w tym zalogowanych: 0, gości: 1