logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C] Problem z listą, wywołanie funkcji z kilkoma wkaźnikami.

vcd_a 29 Gru 2007 17:53 1221 3
REKLAMA
  • #1 4636969
    vcd_a
    Poziom 18  
    Posty: 388
    Pomógł: 9
    Ocena: 6
    Witam, mam następujący problem, piszę właśnie programik który odczytuję listę z pliku i daje możliwość dodania nowych pozycji do listy, pozycje są potem dopisywane do pliku. Na samym początku zrobiłem 2 oddzielne programiki, jeden zapisywał dane do pliku, drugi odczytywał i nie było problemu. Teraz przyszła pora na to by wrzucić wszystko do jednego programu i pojawił się problem. Problem polega na tym, że wywołując funkcję, trzeba ją wywołać z trzema wskaźnikami do listy.

    Oto co mi pokazuje kompilator.
    
    dedal<XXXXX>$ cc -o zapis_odczyt zapis_odczyt.c
    "zapis_odczyt.c", line 8: syntax error before or at: *
    "zapis_odczyt.c", line 8: parameter redeclared: przedmiot
    "zapis_odczyt.c", line 8: parameter redeclared: przedmiot
    "zapis_odczyt.c", line 9: syntax error before or at: *
    "zapis_odczyt.c", line 9: parameter redeclared: przedmiot
    "zapis_odczyt.c", line 9: parameter redeclared: przedmiot
    "zapis_odczyt.c", line 10: syntax error before or at: *
    "zapis_odczyt.c", line 10: parameter redeclared: przedmiot
    "zapis_odczyt.c", line 10: parameter redeclared: przedmiot
    cc: acomp failed for zapis_odczyt.c
    


    A to kod całego programu:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define ROZMIAR 45
    
    //++++++++++++++++++++++++++++++++ NAGLOWKI FUNKCJI +++++++++++++++++++++++++++++++++++++++++
    void menu(void);
    void wczytaj_liste(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy);
    void przegladaj(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy);
    void dodaj(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy);
    
    //++++++++++++++++++++++++++++++++++++++ MAIN +++++++++++++++++++++++++++++++++++++++++++++++
    typedef struct przedmiot_ {
    	char nazwa[ROZMIAR];
    	char producent[ROZMIAR];
    	int ilosc;
    	struct przedmiot_ * nast;
    } przedmiot;
    
    int main(void)
    {	
    	przedmiot* glowny = NULL;
    	przedmiot* poprz, * biezacy;
    	char nazwa_przedmiotu[ROZMIAR];
    	char producent[ROZMIAR];
    	char ch;
    	int koniec = 1;
    	
    	wczytaj_liste(glowny, poprz, biezacy);
    	menu();
    	while(koniec == 1)
    	{
    		switch (ch)
    		{
    			case 'p' :
    				fflush(stdin);
    				przegladaj(glowny, poprz, biezacy);
    				break;
    			case 'd' :
    				fflush(stdin);
    				dodaj(glowny, poprz, biezacy);
    				break;
    			case 'q' :
    				koniec == 1;
    				break;
    			default :
    				printf("Nie ma takiego dzialania!\n");
    		}
    	}
    	return 0;
    }
    
    //++++++++++++++++++++++++++++++++++++++ FUNKCJE ++++++++++++++++++++++++++++++++++++++++++++
    //-------------------------------------------------------------------------------------------
    void menu()
    {
    	printf("+++++++ MENU +++++++\n");
    	printf("p - przegladaj liste\n");
    	printf("d - dodaj do listy\n");
    	printf("q - wyjdz z programu\n");
    }
    
    //-------------------------------------------------------------------------------------------
    void wczytaj_liste(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy)
    {
    	char plik[] = "test.dat";
    	FILE* fp;
    
    	if ((fp = fopen(plik, "a+b")) == NULL)
    	{
    		fputs("Nie moge otworzyc pliku test.dat\n", stderr);
    		exit(1);
    	}
    	rewind(fp);
    	while (feof(fp) == 0)
    	{
    		biezacy = (przedmiot *) malloc(sizeof(przedmiot));
    		if (glowny == NULL)
    			glowny = biezacy;
    		else
    			poprz->nast = biezacy;
    		biezacy->nast = NULL;
    		if (fread(biezacy, sizeof(przedmiot), 1, fp) != 1)
    		{
    			memset(biezacy, 0, sizeof(przedmiot));
    			poprz->nast = NULL;
    			break;
    		}
    		poprz = biezacy;
    	}
    	fclose(fp);
    }
    
    //------------------------------------------------------------------------------------------
    void przegladaj(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy)
    {
    	if (glowny == NULL)
    		printf("Nie wpisano zadnych danych!\n");
    	else
    		printf("Oto Twoja lista przedmiotow:\n");
    	biezacy = glowny;
    	while (biezacy != NULL)
    	{
    		printf("Przedmiot: %s\n", biezacy->nazwa);
    		printf("Producent: %s\n", biezacy->producent);
    		printf("    Ilosc: %d\n\n", biezacy->ilosc);
    		biezacy = biezacy->nast;
    	}
    }
    
    //-------------------------------------------------------------------------------------------
    void dodaj(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy)
    {
    	char nazwa_przedmiotu[ROZMIAR];
    	char producent[ROZMIAR];	
    	char plik[] = "test.dat";
    	FILE *fp;
    
    	if ((fp = fopen(plik, "a+b")) == NULL)
    	{
    		fputs("Nie moge otworzyc pliku test.dat\n", stderr);
    		exit(1);
    	}
    	rewind(fp);
    
    	printf("Rozmiar = %d\n", sizeof(przedmiot));
    	puts("Podaj nazwe przedmiotu:");
    	while (gets(nazwa_przedmiotu) != NULL && nazwa_przedmiotu[0] != '\0')
    	{
    		biezacy = (przedmiot *) malloc(sizeof(przedmiot));
    		if (glowny == NULL)
    			glowny = biezacy;
    		else
    			poprz->nast = biezacy;
    		biezacy->nast = NULL;
    		strcpy (biezacy->nazwa, nazwa_przedmiotu);
    		puts ("Podaj nazwe producenta:");
    		gets(producent);
    		strcpy(biezacy->producent, producent);
    		puts ("Podaj ilosc przedmiotow");
    		scanf ("%d", &biezacy->ilosc);
    		while (getchar() != '\n')
    			continue;
    		if (fwrite(biezacy, sizeof(przedmiot), 1, fp) != 1)
    		{
    			printf("Blad przy zapisie danych do pliku!\n");
    			fclose(fp);
    			exit(1);
    		}
    		puts("Podaj nazwe nastepnego przedmiotu(pusty wiersz konczy dodawanie):");
    		poprz = biezacy;
    	}
    	fclose(fp);
    }
    
    //-------------------------------------------------------------------------------------------
    


    Proszę o pomoc i pozdrawiam, Krzysiek
  • REKLAMA
  • Pomocny post
    #2 4637174
    Seba85
    Poziom 17  
    Posty: 110
    Pomógł: 24
    Przenieś deklarację struktury na sam początek i po problemie.
  • REKLAMA
  • #3 4638580
    vcd_a
    Poziom 18  
    Posty: 388
    Pomógł: 9
    Ocena: 6
    Dzięki wielkie za bardzo szybkie odpowiedzi i pomoc ;)

    Zastanawiam się teraz jak zrobić edycję oraz usuwanie poszególnej struktury w liście. Móglibyście mi pomóc raz jeszcze?, cały problem polega na tym, że usuwając strukturę ze środka listy, trzeba przepisać wszystkie wskaźniki do struktur znajdujących się od usuwanej do końca. I tu właśnie jest problem, bo przyznam się szczerze, że za bardzo nie wiem jak to ugryźć.

    To kod zmodyfikowanego programu jakby ktoś potrzebował :)
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define ROZMIAR 45
    
    typedef struct przedmiot_ {
    	char nazwa[ROZMIAR];
    	char producent[ROZMIAR];
    	int ilosc;
    	struct przedmiot_ * nast;
    } przedmiot;
    
    //++++++++++++++++++++++++++++++++ NAGLOWKI FUNKCJI +++++++++++++++++++++++++++++++++++++++++
    void menu(void);
    void wczytaj_liste(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy);
    void dodaj(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy);
    
    //++++++++++++++++++++++++++++++++++++++ MAIN +++++++++++++++++++++++++++++++++++++++++++++++
    int main(void)
    {	
    	przedmiot* glowny = NULL;
    	przedmiot* poprz, * biezacy;
    	char nazwa_przedmiotu[ROZMIAR];
    	char producent[ROZMIAR];
    	char ch;
    	int koniec = 1;
    	
    	fflush(stdin);
    	while(koniec == 1)
    	{
    		menu();
    		scanf ("%c", &ch);
    		fflush(stdin);
    		switch (ch)
    		{
    			case 'p' :
    				fflush(stdin);
    				wczytaj_liste(glowny, poprz, biezacy);
    				//przegladaj(glowny, poprz, biezacy);
    				break;
    			case 'd' :
    				fflush(stdin);
    				dodaj(glowny, poprz, biezacy);
    				break;
    			case 'q' :
    				koniec = 0;
    				break;
    			default :
    				printf("Nie ma takiego dzialania!\n");
    				break;
    		}
    	}
    	return 0;
    }
    
    //++++++++++++++++++++++++++++++++++++++ FUNKCJE ++++++++++++++++++++++++++++++++++++++++++++
    //-------------------------------------------------------------------------------------------
    void menu()
    {
    	printf("+++++++ MENU +++++++\n");
    	printf("p - przegladaj liste\n");
    	printf("d - dodaj do listy\n");
    	printf("q - wyjdz z programu\n");
    }
    
    //-------------------------------------------------------------------------------------------
    void wczytaj_liste(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy)
    {
    	char plik[] = "test.dat";
    	FILE* fp;
    
    	if ((fp = fopen(plik, "a+b")) == NULL)
    	{
    		fputs("Nie moge otworzyc pliku test.dat\n", stderr);
    		exit(1);
    	}
    	rewind(fp);
    	while (feof(fp) == 0)
    	{
    		biezacy = (przedmiot *) malloc(sizeof(przedmiot));
    		if (glowny == NULL)
    			glowny = biezacy;
    		else
    			poprz->nast = biezacy;
    		biezacy->nast = NULL;
    		if (fread(biezacy, sizeof(przedmiot), 1, fp) != 1)
    		{
    			memset(biezacy, 0, sizeof(przedmiot));
    			poprz->nast = NULL;
    			break;
    		}
    		poprz = biezacy;
    	}
    	fclose(fp);
    	printf("Struktura wpisana\n");
    	if (glowny == NULL)
    		printf("Nie wpisano zadnych danych!\n");
    	else
    		printf("Oto Twoja lista przedmiotow:\n");
    	biezacy = glowny;
    	while (biezacy != NULL)
    	{
    		printf("Przedmiot: %s\n", biezacy->nazwa);
    		printf("Producent: %s\n", biezacy->producent);
    		printf("    Ilosc: %d\n\n", biezacy->ilosc);
    		biezacy = biezacy->nast;
    	}
    }
    
    //-------------------------------------------------------------------------------------------
    void dodaj(przedmiot* glowny, przedmiot* poprz, przedmiot* biezacy)
    {
    	char nazwa_przedmiotu[ROZMIAR];
    	char producent[ROZMIAR];	
    	char plik[] = "test.dat";
    	FILE *fp;
    
    	if ((fp = fopen(plik, "a+b")) == NULL)
    	{
    		fputs("Nie moge otworzyc pliku test.dat\n", stderr);
    		exit(1);
    	}
    	rewind(fp);
    
    	printf("Rozmiar = %d\n", sizeof(przedmiot));
    	puts("Podaj nazwe przedmiotu:");
    	while (gets(nazwa_przedmiotu) != NULL && nazwa_przedmiotu[0] != '\0')
    	{
    		biezacy = (przedmiot *) malloc(sizeof(przedmiot));
    		if (glowny == NULL)
    			glowny = biezacy;
    		else
    			poprz->nast = biezacy;
    		biezacy->nast = NULL;
    		strcpy (biezacy->nazwa, nazwa_przedmiotu);
    		puts ("Podaj nazwe producenta:");
    		gets(producent);
    		strcpy(biezacy->producent, producent);
    		puts ("Podaj ilosc przedmiotow");
    		scanf ("%d", &biezacy->ilosc);
    		while (getchar() != '\n')
    			continue;
    		if (fwrite(biezacy, sizeof(przedmiot), 1, fp) != 1)
    		{
    			printf("Blad przy zapisie danych do pliku!\n");
    			fclose(fp);
    			exit(1);
    		}
    		puts("Podaj nazwe nastepnego przedmiotu(pusty wiersz konczy dodawanie):");
    		poprz = biezacy;
    	}
    	fclose(fp);
    }
    
    //-------------------------------------------------------------------------------------------
    

    Pozdrawiam serdecznie i życzę Szczęśliwego Nowego Roku 2008, Krzysiek
  • Pomocny post
    #4 4639541
    Seba85
    Poziom 17  
    Posty: 110
    Pomógł: 24
    Nie wiem, co rozumiesz, przez przepisywaniem wszystkich wskaźników, przecież właśnie zaletą listy jest to, że wystarczy "przepiąć" wskaźnik z elementu poprzedzającego usuwany element na następny:
    
    if(poprzedni != 0)
      poprzedni->nastepny = biezacy->nastepny;
    else
      glowny = biezacy->nastepny;
    
    przedmiot* temp = biezacy;
    biezacy = biezacy->nastepny;
    free(temp);


    Problem jest taki, że w pliku nie zostanie usunięty odpowiedni element.

    Ja proponuje ten problem rozwiązać tak: kiedy usuwasz jakiś element z listy, to wywołujesz funkcję, która na nowo zapisuje wszystkie elementy do pliku, tzn. zamiast robić append, tworzysz nowy plik.

    Jeżeli jeszcze mogę coś zasugerować to proponuje zrobić metody, które dodają/usuwają element do listy, ale oprócz tego nie robią niczego innego, tzn. nie wypisują nic na ekran ani nie wymagają podania niczego do użytkownika. te metody mogą być potem wywoływane z wnętrza funkcji, które to robią.

    Już całkiem super rozwiązaniem byłoby oddzielenie danych przechowywanych wewnątrz listy od samej listy:

    typedef struct {
      char nazwa[ROZMIAR];
      char producent[ROZMIAR];
      int liczba;
    } przedmiot;
    
    typedef struct element_{
      przedmiot* dane;
      struct element_* nast;
    } element;
    
    element* glowny;
    
    void dodaj(element* glowny, przedmiot* dane);
    void usun(element* glowny, element* usuwany);
    void wyczysc(element* glowny);
    

    Poza tym funkcje wczytujące dane:
    
    wczytaj_z_pliku(char* nazwa, element* glowny);
    zapisz_do_pliku(char* nazwa, element* glowny);
    

    Chociaż, jeżeli mam być szczery, to mi by się nie chciało przerabiać kodu, który już mam ;)
REKLAMA