[c]Listy

Draqun

Użytkownik
Dołączył
Sierpień 27, 2007
Posty
67
[c]Listy[SOLVED]

Mam problem. Za diabła nie mogę zrozumieć działania list - znaczy zrobie to na schemacie blokowym ale nie potrafie zaprogramować.

A więc mam program
Kod:
#include<stdio.h>
struct Lista zmienna;
struct Lista{
	char imie[20];
	struct Lista *next;
	};

int main()
{
	int a;
	a=0;
	for(a;a<10;a++)
	{
             /*Brakujacy kod*/
	printf("Podaj imie: ");
	scanf("%s", zmienna.imie);
	}
             /*(tego też brakuje)Przejscie na 1 element listy aby mozna bylo wyswietlic od poczatku*/
	
	while(zmienna.next!=NULL)/*Ma skakac po kolejnych elementach listy i je wyświetlać*/
	{
	printf("%s\n", zmienna.imie);
	}
}

Nie rozumiem zasad dodawania. Wiem, ze trzeba dodać coś w stylu

nowy=malloc(sizeof(struct Lista*);

ale nie bardzo wiem co jak i gdzie? Jak poruszać się po liście. Z tego co widze to przed pobraniem danych do zmiennej musi mi stworzyć nowy element listy i przeszkoczyć na niego. Ale nie wiem jak.
 
Ostatnia edycja:

nowy_me

Użytkownik
Dołączył
Luty 7, 2007
Posty
451
tu mój bardzo prosty program z listami, który kiedyś robiłem na zaliczenie:
Kod:
#include <stdio.h>
#include <stdlib.h>

struct rekord
{
  int x;
  struct rekord *nast;
};

void dodaj(struct rekord **glowa, int x)
{
  struct rekord *nowy;
  nowy=(struct rekord*)malloc(sizeof(struct rekord));
  nowy->x=x;
  nowy->nast=*glowa;
  *glowa=nowy;
}

void wyswietl(struct rekord *glowa)
{
  while(glowa!=NULL)
  {
    printf("%d\n", glowa->x);
    glowa=glowa->nast;
  }
}

void usun(struct rekord **glowa)
{
  struct rekord *pom;
  while(*glowa!=NULL)
  {
    pom=(*glowa)->nast;
    free(*glowa);
    *glowa=pom;
  }
}

int main()
{
  struct rekord *glowa=NULL;
  
  dodaj(&glowa, 2);
  dodaj(&glowa, 8);
  dodaj(&glowa, 4);
  wyswietl(glowa);
  usun(&glowa);
  dodaj(&glowa, 3);
  wyswietl(glowa);
  usun(&glowa);
  
  system("pause");
  return 0;
}
przeanalizuj na spokojnie i powinieneś zrozumieć
 

Draqun

Użytkownik
Dołączył
Sierpień 27, 2007
Posty
67
Nom w międzyczasie nabazgrałem coś i nawet działa, ale nie do końca tak jak chce :)
Kod:
#include<stdio.h>
struct Lista zmienna;
struct Lista{
	char imie[20];
	struct Lista *next;
	};
struct Lista *nowy;
struct Lista *pierwszy;

int main()
{
	int a,koniec;
	a=0;
	koniec=3;
	nowy=(struct Lista*)malloc(sizeof(struct Lista));
	nowy->next=nowy;
	pierwszy=nowy->next;
	
	for(a;a<koniec;a++)
	{
	printf("Podaj imie: ");
	scanf("%s", zmienna.imie);
	nowy->imie;
	nowy->next=nowy;
	if(a==koniec-1)
	{nowy->next=NULL;}
	}
	nowy->next=pierwszy;
	
	while(nowy->next!=NULL)
	{
	printf("%s", zmienna.imie);
	nowy=nowy->next;
	}
}

Chodzi mi o wskaznik na 1 element - Czemu on nie jest przetrzymywany w 'zmiennej' pierwszy? I po 2 czemu mi się zapętla? Przecież ostatni element wskazuje na NULLa prawda?
 

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
Twój kod, linijka ze scanf'em jest podatna na błąd z przepełnieniem bufora:

Kod:
rgawron@foo:~$ ./a.out 
Podaj imie: eeeeeeeeeeeeesdfs786876876666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
Segmentation fault
Jest jeszcze kilka innych błędów:
Kod:
nowy->imie;
ta linijka nic nie robi

Kod:
        while(nowy->next!=NULL)
    {
    printf("%s", zmienna.imie);
    nowy=nowy->next;
    }
Powinieneś wyświetlać imię z komórki w liście a nie ze zmiennej globalnej, do której ją wczytywałeś (swoją drogą zmienne globalne też są tu niepotrzebne, gdyby były lokalne, o błędzie powiadomiłby Cię kompilator)

Za każdym razem, gdy tworzysz nową komórkę w liście musisz jej przydzielić miejsce mallock'iem, w skrócie, to wywołań malloc'a powinno być tyle, ile jest elementów w liście.

Nie zwalniasz elementów listy, co powoduje wycieki pamięci.

Kod od nowy_me jest całkiem OK, na pewno Ci pomoże :) Poniżej wklejam też Twój, lekko poprawiony.

Kod:
#include<stdio.h>
#include <stdlib.h>


struct Lista zmienna;
struct Lista{
    char imie[20];
    struct Lista *next;
    };
struct Lista *pierwszy;

int main()
{
    int a,koniec;
    a=0;
    koniec=3;
    struct Lista *nowy;
    nowy = (struct Lista*)malloc(sizeof(struct Lista));

    pierwszy = nowy;
 
    for(a; a<koniec; a++)
    {
        printf("Podaj imie: ");
        scanf("%s", nowy->imie);

        if(a == koniec-1)
            break;

        struct Lista *tmp;
        tmp = (struct Lista*)malloc(sizeof(struct Lista));
        tmp->next = NULL;
 
        nowy->next = tmp;
        nowy = tmp;
    }

    nowy = pierwszy;
    while(nowy!=NULL)
    {
        printf("%s\n", nowy->imie);
        nowy = nowy->next;
    }

    nowy = pierwszy;
    while(nowy!=NULL)
    {
        struct Lista *tmp = nowy->next;
        free(nowy);
        nowy = tmp;
    }

}
Kod:
rgawron@foo:~$ ./a.out 
Podaj imie: ala
Podaj imie: ola
Podaj imie: tola
ala
ola
tola


na koniec sprawdźmy, czy taka wersja kodu ma wycieki pamięci (ja używam do tego valgrind'a - bardzo dobry i popularny soft):

Kod:
valgrind ./a.out 
==12524== Memcheck, a memory error detector.
==12524== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==12524== Using LibVEX rev 1804, a library for dynamic binary translation.
==12524== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==12524== Using valgrind-3.3.0-Debian, a dynamic binary instrumentation framework.
==12524== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==12524== For more details, rerun with: -v
==12524== 
Podaj imie: ala
Podaj imie: ola
Podaj imie: tola
ala
ola
tola
==12524== 
==12524== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
==12524== malloc/free: in use at exit: 0 bytes in 0 blocks.
==12524== malloc/free: 3 allocs, 3 frees, 72 bytes allocated.
==12524== For counts of detected errors, rerun with: -v
==12524== All heap blocks were freed -- no leaks are possible.

czyli jest ok :)
 
Ostatnia edycja:

Draqun

Użytkownik
Dołączył
Sierpień 27, 2007
Posty
67
Wielkie dzięki. To rozjaśniło mi trochę sprawę. Teraz głębiej przeanalizuje kod krok po kroku aby to lepie zrozumieć. Wielkie dzięki jeszcz raz.
 
Do góry Bottom