[C] Baza danych, lista łaczona

0

Witam wszystkich.
Mam do napisania program obsługi wypożyczalni płyt DVD. Program musi umożliwiać wykonanie: dodawania nowych płyt i klientów, wyszukiwanie, modyfikacja i usuwanie już istniejących oraz wypożyczanie. Bazy odczytywane i zapisywane do domyślnych plików.

Ponieważ program ma mieć nieskończenie wiele wpisów pomyślałem, żeby stworzyć listę łączoną, czyli, że każda struktura ma w sobie wskaźnik do następnej struktury. Strasznie gubię się w wskaźnikach, więc liczę na waszą pomoc.

Jest to mój trzeci program w życiu, więc proszę o wyrozumiałość :)

Napisałem część kodu odpowiadającą za dodawanie nowych płyt i klientów. I tu chyba wszystko działa. Lista istnieje i jest zapisywana do pliku.
Chciałem napisać funkcję do wyszukiwania określonej części listy. Mój pomysł: funkcja wczytuje z pliku dane i na nowo tworzy listę łączoną. I tu się robi problem.

struct DVD
{
char title[MAXT];
char category[MAXC]
float cost;
struct DVD *nast;
}
int szukaj()
{
struct DVD *glowny = NULL;
struct DVD *poprz, *biezacy;
struct DVD pierwszy;

daneplyt=fopen("plyty.c", "r");
while(fread(&pierwszy, sizeof(struct DVD), 1, daneplyt) == 1)
{
if(glowny == NULL)
{
glowny = &pierwszy;
biezacy = glowny;
}
else
{
biezacy=&pierwszy;
poprz->nast=biezacy;
}
biezacy -> nast= NULL;
poprz = biezacy;
printf("Film: %s \t Kategoria: %s \t cena: %0.2f\n", biezacy->title, biezacy->category, biezacy->cost);
}
fclose(daneplyt);
return(0);
} 

Za pierwszym razem pętla while działa dobrze. Wczytuje to, co było w pliku. Za każdym następnym razem program wariuje. Podejrzewam, że błąd jest w "else". Ponieważ całość jest strasznie zrobiona na czuja, nie wiem co to za błąd i jak go naprawić.
Druga sprawa to jak wyszukać w liście łączonej to, co chcę? Musi być jakieś porównanie tego, co wprowadzi użytkownik z tym, co jest w liście. Jakaś wskazówka?

Pozdrawiam i z góry dziękuję za pomoc.

0

Że tak spytam. Jaki jest sens tej listy w funkcji szukaj i dlaczego nie ma tam ani jednego wywołania funkcji malloc?

0
struct DVD
{
char title[MAXT];
char category[MAXC]
float cost;
struct DVD *nast;                  //<------ !
}
...
while(fread(&pierwszy, sizeof(struct DVD), 1, daneplyt) == 1)   // <----- auucc..
...
struct DVD *glowny = NULL;
struct DVD *poprz, *biezacy;
struct DVD pierwszy;                 //<---- !!!!!
...
glowny = &pierwszy;                 //<---- aaaauuuuuuucccccc...
biezacy = glowny;
...
0
0x666 napisał(a)

Że tak spytam. Jaki jest sens tej listy w funkcji szukaj i dlaczego nie ma tam ani jednego wywołania funkcji malloc?

Wydawało mi się, że lista musi zostać odtworzona by później wyszukać coś w niej. Malloc jeszcze dopiszę.

quetzalcoatl -> Mógłbyś to jakoś rozwinąć? Bo nie bardzo rozumiem gdzie błąd robię. Pierwszy blok informacji jest wczytywany do zmiennej pierwszy. Jej adres jest przypisywany do glowny, gdzie glowny to początek listy.

0

Wydawało mi się, że lista musi zostać odtworzona by później wyszukać coś w niej.

No tak, ale w twoim przykładzie widać, że ta lista odtwarzana jest tylko na potrzebę funkcji szukaj. Równie dobrze możesz wczytywać rekordy z pliku, porównywać i robić cokolwiek innego bez tej listy. Tę funkcję można skrócić do takiej formy:

int szukaj()
{
    struct DVD pierwszy;

    daneplyt=fopen("plyty.c", "r");
    while(fread(&pierwszy, sizeof(struct DVD), 1, daneplyt) == 1)
    {
        printf("Film: %s \t Kategoria: %s \t cena: %0.2f\n", pierwszy->title, pierwszy->category, pierwszy->cost);
    }

    fclose(daneplyt);
    return(0);
} 

efekt będzie ten sam ;)

0
creaton napisał(a)

quetzalcoatl -> Mógłbyś to jakoś rozwinąć? Bo nie bardzo rozumiem gdzie błąd robię. Pierwszy blok informacji jest wczytywany do zmiennej pierwszy. Jej adres jest przypisywany do glowny, gdzie glowny to początek listy.

pierwsze auc dotyczy fread, poniewaz najwyrazniej zapisales do pliku tekstowego strukture zawierajaca wskaznik. jak sie zachowa czytanie tego i nastepnego rekordu, jesli ten wskaznik bedzie mial wartosc 0x00333231 co po zapisie tekstowym da "123" albo jesli bedzie mial wartosc 0x00202020 czyli " "?

a co do tego drugiego auc, to zauwazyles ze za kazdym razem &pierwszy daje ten sam adres? co z tego wynika? gdzie laduja kolejne partie danych odczytane przez fread? jakie sa wartosci wskaznikow DVD::nast po "utworzeniu" listy?

0

pierwsze auc dotyczy fread, poniewaz najwyrazniej zapisales do pliku tekstowego strukture zawierajaca wskaznik. jak sie zachowa czytanie tego i nastepnego rekordu, jesli ten wskaznik bedzie mial wartosc 0x00333231 co po zapisie tekstowym da "123" albo jesli bedzie mial wartosc 0x00202020 czyli " "?

Masz rację, dopiero teraz zdałem sobie z tego sprawę o co chodziło. Zmieniłem więc kod i zamiast zapisywać całą strukturę, kolejno zapisuję jej elementy za pomocą fprintf(). (czy fputc() da taki sam efekt?)

Czyli dla struktury struct DVD dane w pliku wyglądają tak:

Szeregowiec Ryan
wojenny
10.00
Zielona mila
dramat
5.00

itd...

Aby móc wyszukiwać, modyfikować i usuwać rekordy z listy musi być teraz odtwarzana przy każdym uruchomieniu programu.

int szukajfilm()
{
    struct DVD *glowny = NULL;
    struct DVD *poprz, *biezacy;
    struct DVD pierwszy;
    char temp[TYMCZ];

    daneplyt=fopen("plyty.c", "r");
    while(fgets(temp, MAXT, daneplyt) != NULL)
    {
        biezacy = (struct DVD *) malloc(sizeof(struct DVD));
        if(glowny == NULL)
            glowny = biezacy;
        else
            poprz->nast=biezacy;
        biezacy->nast=NULL;
        strcpy(biezacy->title, temp);
        fgets(temp, MAXC, daneplyt);
        strcpy(biezacy->category, temp);
        fscanf(daneplyt, "%0.2f", &biezacy->cost);
        biezacy->nast=NULL;
        poprz=biezacy;
    }
    biezacy = glowny;
    while (biezacy != NULL)
    {
        printf("Film: %s kategoria: %s cena: %0.2f", biezacy->title, biezacy->category, biezacy->cost);
        biezacy = biezacy->nast;
    }
    fclose(daneplyt);
    return(0);
}

Napisałem coś takiego do odtwarzania listy. Część z printf służy tylko i wyłącznie do pokazania mi, że lista się prawidłowo odtwarza. No i jak się można domyślić jest błąd :)

Pierwsze dwie wartości się dobrze wczytują. Czyli dla przykładu wyżej:
Film: Szeregowiec Ryan, Kategoria: wojenny, Cena: error ;)
Domyślam się, że chodzi o fscanf.. Jak zrobić by cena była poprawnie wczytywana z pliku? Nie mogę korzystać tu ze fgets() bo on wczytuje tylko łańcuchy.

Proszę o pomoc.

0

dziwne.. fscanf wyglada prawidlowo, formatstring rowniez.. na pewno trzecia linijka pliku z danymi jest poprawna? moze jakies smieci sie wkradly.. dobrze tez jest sprawdzic co fscanf zwraca -- tak jak wszystkie z rodziny scanf, zwraca ilosc poprawnie odczytanych pól -- czyli tutaj powinien zwrocic jedynke. mozesz w miare prosto sprawdzic czy calosc wczytywania poza tym jednym jest poprawna -- tymczasowo zamien fscanf'a na fgets'a i odczytaj cala linie pomijajac w ten sposob cene. sprawdzisz czy cala reszta sie dobrze odczytuje, a nad cena - hm - dziwne :)

0

Sprawdziłem plik, wszystko wygląda tak jak napisałem wcześniej.

To co się dzieje po uruchomieniu tego:

Jak działa fscanf() to mam:
Film: Szeregowiec Ryan kategoria: wojenny cena: 0.00
Film: 10.00 Kategoria: Zielona mila cena: 0.00
Film: dramat kategoria: 5.00 cena: 0.00
itd..

Usunąłem fscanf() i zamiast tego dałem fgets()
Film: Szeregowiec Ryan kategoria: wojenny cena: 0.00
Film: Zielona mila kategoria: dramat cena: 0.00

0

sprawdzilem - prawidlowy fscanf w Twoim przypadku to:

fscanf(daneplyt, "%f ", &biezacy.cost)

tak, razem z ta spacja po %f !!

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