Wypożyczalnia samochodów. Problem z funkcją wypożyczającą samochód.

0

Cześć. Tworzę amatorski program dla wypożyczalni samochodów jako projekt na studia. Mam problem z funkcją wypożyczającą samochód. Mam trzy pliki tekstowe "cars.txt" z bazą samochodów, "clients.txt" z bazą klientów oraz "rents.txt" w której mają się znajdować dane samochodu wypożyczonego oraz dane klienta. W pliku "cars.txt" liczba samochodów dostępnych powinna się zmienić, natomiast nie zmienia się a jest dopisywana nowa linijka z danymi samochodu ze zmienioną liczbą dostępnych egzemplarzy. Do pliku rents.txt nic nie jest zapisywane. Proszę o pomoc, ponieważ nie mogę sobie z tym poradzić. Dziękuje. Program operuje na dwóch strukturach.

void rent_car()
{
    char nr_rej[100];
    printf("Podaj numer rejestracyjny samochodu: ");
    scanf("%s", nr_rej);

    FILE *a = fopen("cars.txt", "r+");
    FILE *k = fopen("rents.txt", "a");

    if (a == NULL)
    {
        printf("Nie udalo sie otworzyc pliku cars.txt\n");
        return;
    }

    struct car samochod;
    int znaleziony = 0;
    while (fscanf(a, "%s %s %s %d %s %d %d %d", samochod.marka, samochod.model, samochod.nr_rej, samochod.rok_prod, samochod.kolor, samochod.przebieg, samochod.liczba_egzemplarzy, samochod.liczba_wypozyczonych) != EOF)
    {
        if (strcmp(nr_rej, samochod.nr_rej) == 0)
        {
            znaleziony = 1;
            if (samochod.liczba_wypozyczonych >= samochod.liczba_egzemplarzy)
            {
                printf("Brak dostepnych egzemplarzy samochodu o podanym numerze rejestracyjnym\n");
                break;
            }
            else
            {
                samochod.liczba_wypozyczonych += 1;
                samochod.liczba_egzemplarzy -= 1;
                fseek(a, -(long)sizeof(struct car), SEEK_CUR);
                fprintf(a, "%s %s %s %d %s %d %d %d\n", samochod.marka, samochod.model, samochod.nr_rej, samochod.rok_prod, samochod.kolor, samochod.przebieg, samochod.liczba_egzemplarzy, samochod.liczba_wypozyczonych);
                break;
            }
        }
    }
        if(!znaleziony)
        {
            printf("Nie znaleziono samochodu o podanym numerze rejestracyjnym.\n");
        }

    FILE *b = fopen("clients.txt", "r");
    if (b == NULL)
    {
        printf("Nie udalo sie otworzyc pliku clients.txt\n");
        return;
    }

    char numer_karty[20];
    struct person klient;
    int znaleziona_osoba = 0;
    printf("Podaj numer karty osoby wypozyczajacej samochod: ");
    scanf("%s", numer_karty);
    while (fscanf(b, "%s %s %s %s %s", klient.imie, klient.nazwisko, klient.numer_karty, klient.adres, klient.nr_tel) != EOF)
    {
        if (strcmp(numer_karty, klient.numer_karty) == 0)
        {
            znaleziona_osoba = 1;
            fprintf(k, "%s %s %s %d %s %d %d %d ", samochod.marka, samochod.model, samochod.nr_rej, samochod.rok_prod, samochod.kolor, samochod.przebieg, samochod.liczba_egzemplarzy, samochod.liczba_wypozyczonych);
            fprintf(k, "%s %s %s %s %s\n", klient.imie, klient.nazwisko, klient.numer_karty, klient.adres, klient.nr_tel);
            break;
        }
    }

    if (!znaleziona_osoba)
    {
        printf("Nie znaleziono osoby o podanym numerze karty\n");
        return;
    }
    fclose(a);
    fclose(b);
    fclose(k);
}
3

Otwarcie "w" likwiduje zawartość pliku. To JEDEN z wielu problemów tego kodu.

Straszna sieczka w jednym wielkim wszystko(), jest niemal pewnie, że poplątasz w pewnym momencie - a wystarczy poplątać uchwyty do plików

Zrób rodzinę wspołpracujacych funkcji sprawdz(), wypożycz() (prawdziwe, a nie wszystko), zwrot() itd, każda jednym zadaniem, i z takim kształtem, żeby w oczach było widać, że wykona się poprawnie.

Funkcja krótka, z tylko jedną ścieżką do przejścia, od jednego otwarcia plików we właściwym trybie, po ich pewne zamkniecie itd. Było posprzątane / zostawiam posprzątane

0

OK, a jest ktoś w stanie wytłumaczyć mi dlaczego ten fragment kodu nie działa poprawnie? Zamiast edytować tą linijkę w pliku to dopisuje nową na dole z poprawnie zmienionymi danymi.

{ samochod.liczba_wypozyczonych += 1; samochod.liczba_egzemplarzy -= 1; fseek(a, -(long)sizeof(struct car), SEEK_CUR); fprintf(a, "%s %s %s %d %s %d %d %d\n", samochod.marka, samochod.model, samochod.nr_rej, samochod.rok_prod, samochod.kolor, samochod.przebieg, samochod.liczba_egzemplarzy, samochod.liczba_wypozyczonych); break; }

2

@Jakub Wrona:

Używasz zapisów na styl tekstowy,wypisując dane w ich aktualnej długości, (a nie długości pól struktury)

fseek napisałeś *) na styl binarny. To se ne da pane Havranek

Nie ma za co

*) to wersja optymistyczna. Pesymistyczna: przekleiłeś

0

Szczerze to średnio rozumiem. Powinienem to zrobić bez (long) czy jak?

1

Szczerze to średnio rozumiem. Powinienem to zrobić bez (long) czy jak? — Jakub Wrona dziś, 14:17

Powinieneś głębiej oswoić tryby otwarcia plików, i właściwe dla tych trybów operacje, bo są odmienne (maja odmienny sens *) )
EDIT: sądzę, ze to jest jednym z celów zadania.

Rzutowanie nie ma NIC do rzeczy
.
Generalnie plik testowy, która zawiera jakąś kolekcję, trudno podczas aktualizacji obsłużyć inaczej, niż wczytując całą do RAM itd ...
(analogiczna sama idea w trybie binarnym jest znana, ale tez niełatwa, i to są .. bazy danych)

0

Teraz jedynie to edytowanie liczby egzemplarzy dostępnych i wypożyczonych mi nie działa.

Gdybyś miał selektywne funkcje, wykonujące jedną dobrze określoną czynność, o czystym kontekście, byś mógł je testować każdą w oderwaniu od innych ręczno-kodem (plik budowany ręcznie, odczytywany kodem, lub na odwrót, budowany kodem, oceniany wzrokowo)

Powtórzę:

ZrobieDobrze napisał(a):

Generalnie plik testowy, która zawiera jakąś kolekcję, trudno podczas aktualizacji obsłużyć inaczej, niż wczytując całą do RAM itd ...

Jakieś zyganie fseek na błędnych założeniach tego nie zastąpi

1
Jakub Wrona napisał(a):

Szczerze to średnio rozumiem. Powinienem to zrobić bez (long) czy jak?

Pisanie do pliku to mniej więcej jak pisanie w notatniku z tym że nie masz trybu insert, zawsze nadpisywanie.
W zasadzie możesz zapamiętać pozycję początku przed wczytaniem za pomocą ftell()
Wtedy fseek() na tą samą pozycję zadziała poprawnie.
A żeby wałczyć z trybem bez insert'a to możesz liczby zapisywać jako "%6d" zaś napisy jako "%32s" z tym że równieź należy pilnować aby użyszkodnik nie podał dłuższych napisów.

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