Problem z lista

0

Program kompiluje się bez najmniejszych problemów, tylko w trakcie działania pojawia się błąd.

 
#include <stdio.h>
#include <stdlib.h> // malloc()

struct lista
{

    int wartosc;
    struct lista *next_el;

};


struct lista *head;
// funkcja wyszukujaca konkretna wartosc. Wartosc zwracana
// xszukana wartosc w liscie
// 1 gdy wartosc zosta³a znaleziona
// 0 gdy wartosc nie zosta³a znaleziona

int find( int x)
{
struct lista *current_ptr;
current_ptr = head;

    while( current_ptr != NULL)
    {

        if(current_ptr->wartosc == x) return 1;
        current_ptr = current_ptr->next_el;


    }

return 0;
}

int main()
{

struct lista head;
struct lista *new_ptr;
struct lista *new_ptr2;
struct lista *new_ptr3;

    head.next_el = NULL;

    new_ptr = malloc(sizeof(struct lista));
    new_ptr->wartosc= 12;
    head.next_el = new_ptr; // poczatek listy wskazuje na pierwszy element
    new_ptr = NULL;

    //dodanie 2elem
    new_ptr2 = malloc(sizeof(struct lista));
    new_ptr2->wartosc = 3;
    new_ptr->next_el = new_ptr2;
    new_ptr2 = NULL;
    //dodanie 3 elementu
    new_ptr3 = malloc(sizeof(struct lista));
    new_ptr3->wartosc = 9;
    new_ptr2->next_el = new_ptr3;
    new_ptr3 = NULL;

    if(find(29))
    {

        printf("znalazllem szukanej liczby");

    }
    else
    {

        printf("Nie znalazlem szukanej liczby");

    }

free(new_ptr);
free(new_ptr2);
free(new_ptr3);

return 0;
}

0
  1. Nazwy struktur są zupełnie niewspółmierne do ich zastosowania. (Lista nie składa się z wartości i wskaźnika do następnego elementu, z tego składa się węzeł listy. Lista składa się ze wskaźnika na head i ew na tail)
  2. Jak będziesz chciał(a) dodać 10 elementów to sobie ten kawałek kodu znów skopiujesz? A jak 100? A jak milion? Rozumiem że o czymś takim jak funkcje nie słyszano?
  3. Nigdzie nie ustawiasz tego globalnego wskaźnika struct lista *head; więc jak się do niego w find() odnosisz to leci naruszenie ochrony pamięci. Co więcej, zrobiłaś też zmienną o tej samej nazwie, za co powinno być biczowanie.
0

Poprawiłam, ale dalej jest nie wiadomy błąd. Po prostu program się zawiesza w trakcie wykonywania.

 
#include <stdio.h>
#include <stdlib.h> // malloc()

struct lista
{

    int wartosc;
    struct lista *next_el;

};




// funkcja wyszukujaca konkretna wartosc. Wartosc zwracana
// xszukana wartosc w liscie
// 1 gdy wartosc zosta³a znaleziona
// 0 gdy wartosc nie zosta³a znaleziona

int find( int x, struct lista *poczatek)
{
struct lista *current_ptr;
current_ptr = poczatek;

    while( current_ptr != NULL)
    {

        if(current_ptr->wartosc == x) return 1;
        current_ptr = current_ptr->next_el;


    }

return 0;
}

int main()
{

struct lista *head;
head->next_el = NULL;
struct lista *new_ptr;
struct lista *new_ptr2;
struct lista *new_ptr3;



    new_ptr = malloc(sizeof(struct lista));
    new_ptr->wartosc= 12;
    head->next_el = new_ptr; // poczatek listy wskazuje na pierwszy element
    new_ptr = NULL;

    //dodanie 2elem
    new_ptr2 = malloc(sizeof(struct lista));
    new_ptr2->wartosc = 3;
    new_ptr->next_el = new_ptr2;
    new_ptr2 = NULL;
    //dodanie 3 elementu
    new_ptr3 = malloc(sizeof(struct lista));
    new_ptr3->wartosc = 9;
    new_ptr2->next_el = new_ptr3;
    new_ptr3 = NULL;

    if(find(29, head))
    {

        printf("znalazllem szukanej liczby");

    }
    else
    {

        printf("Nie znalazlem szukanej liczby");

    }

free(new_ptr);
free(new_ptr2);
free(new_ptr3);

return 0;
}
0

Nawiązując do tego co Shalom powiedział. (zaraz będzie, że znowu zamiast przeczytać jego posta piszę swoje, ale po raz kolejny on pisze szybciej niż ja wysyłam posta)
Nie wiem co robi u Ciebie funkcja find, ale raczej nie szuka. Napisałem to dla Ciebie, ale zamiast użyć tego jako gotowca, przepisz ten kod i postaraj się zrozumieć jak on funkcjonuje. Wydaje mi się, że nie ma żadnych memleaków, w razie czego ktoś poprawi.

#include <iostream>
using namespace std;

//na początek typedef się przyda
typedef struct list List;
struct list
{
     int value;
     List* nxt;
};

List* AddNewElement(List* root, int value)
{
	List* temp = root;
	while(temp->nxt != NULL)
		 temp = temp->nxt;
     
	 List* _new = (List*)malloc(sizeof(List));
	 temp->nxt = _new;
     _new->value = value;
     _new->nxt = NULL;

     return root;     // zwracamy korzeń, bo to lista jednokierunkowa, nie mamy możliwości powrotu do korzenia w inny sposób jak właśnie przez zwrócenie korzenia w funkcji
}

List* SeekValue(List* root, List* temp, int x)
{
	if(temp == NULL)
		return root;

	if(temp->value == x)
		return temp;
	else
		SeekValue(root, temp->nxt, x);
}

void DeleteAllMembers(List* root)
{
	if(root->nxt != NULL)
		DeleteAllMembers(root->nxt);

	free(root);
}

int main(int argc, char* argv[])
{
	List* root = (List*)malloc(sizeof(List));
	root->nxt = NULL;
	root->value = 1;
	AddNewElement(root, 2);
	AddNewElement(root, 3);				// opcjonalnie tak,
	root = AddNewElement(root, 4);		// lub tak. Daje to ten sam wynik

	cout << root->nxt->nxt->nxt->value << endl;
	
	List* find = SeekValue(root, root, 3);

	find == root ? cout << "Nie ma takiej wartosci" << endl : cout << "Ta wartosc to: " << find->value << endl;
	cout << "To wciaz ten sam korzen " << root->value << endl;
	getchar();
	
	DeleteAllMembers(root);

	return 0;
}
0

Funkcje dodajaca zrobię jak zrozumiem ten przykład.

  1. pyt czemu musi we wyszukiwaniu być rekuręcja, a nie wystarczy petla while?
    2)List* SeekValue(List* root, List* temp, int x) czemu jest zwracany wskaźnik do list, skoro ja chce żeby powidział mi czy dana liczba istnieje? i zwrócił 0 lub 1
0
Madziaq napisał(a)
  1. pyt czemu musi we wyszukiwaniu być rekuręcja, a nie wystarczy petla while?

Nie musi być rekurencji, można poradzić sobie z pętlą, ale uważam, że rekurencja jest znacznie wygodniejsza

Madziaq napisał(a)

2)List* SeekValue(List* root, List* temp, int x) czemu jest zwracany wskaźnik do list, skoro ja chce żeby powidział mi czy dana liczba istnieje? i zwrócił 0 lub 1

bool SeekValue(List* root, List* temp, int x)
{
	if(temp == NULL)
		return 0;

	if(temp->value == x)
		return 1;
	else
		SeekValue(root, temp->nxt, x);
}
//...
bool find = SeekValue(root, root, 0);
find == 0 ? cout << "Nie ma takiej wartosci" << endl : cout << "Jest taka wartosc" << endl;
0

a bez rekurecji to mój program dokładnie wygląda jak twój, tylko nieiwem czemu się wiesza.

 
#include <stdio.h>
#include <stdlib.h> // malloc()


struct lista
{

    int wartosc;
    struct lista *next_el;

};




// funkcja wyszukujaca konkretna wartosc. Wartosc zwracana
// xszukana wartosc w liscie
// 1 gdy wartosc zosta³a znaleziona
// 0 gdy wartosc nie zosta³a znaleziona

int find( int x, struct lista *poczatek)
{
struct lista *current_ptr;
current_ptr = poczatek;

    while( current_ptr != NULL)
    {

        if(current_ptr->wartosc == x) return 1;
        //current_ptr = current_ptr->next_el;
        find(x, current_ptr = current_ptr->next_el);


    }

return 0;
}

int main()
{

struct lista *head;
head->next_el = NULL;
struct lista *new_ptr;
struct lista *new_ptr2;
struct lista *new_ptr3;



    new_ptr = malloc(sizeof(struct lista));
    new_ptr->wartosc= 12;
    head->next_el = new_ptr; // poczatek listy wskazuje na pierwszy element
    new_ptr = NULL;

    //dodanie 2elem
    new_ptr2 = malloc(sizeof(struct lista));
    new_ptr2->wartosc = 3;
    new_ptr->next_el = new_ptr2;
    new_ptr2 = NULL;
    //dodanie 3 elementu
    new_ptr3 = malloc(sizeof(struct lista));
    new_ptr3->wartosc = 9;
    new_ptr2->next_el = new_ptr3;
    new_ptr3 = NULL;

    if(find(29, head))
    {

        printf("znalazllem szukanej liczby");

    }
    else
    {

        printf("Nie znalazlem szukanej liczby");

    }

free(new_ptr);
free(new_ptr2);
free(new_ptr3);

return 0;
}

0

Czy identycznie, to bym kontemplował ;-)

Dodaj w tej pętli while taką linię:

cout << "next" << endl;

Twoja pętla wykonuje się w nieskończoność

0
Madziaq napisał(a)

a bez rekurecji to mój program dokładnie wygląda jak twój, tylko nieiwem czemu się wiesza.
nie wygląda. jest napisany schludniej i przede wszystkim skuteczniej.

while( current_ptr != NULL)
    {
 
        if(current_ptr->wartosc == x) return 1;
        //current_ptr = current_ptr->next_el;
        find(x, current_ptr = current_ptr->next_el);
 
 
    }

pętla, której warunkiem zakończenia jest current_ptr == null, a w środku tej pętli nigdzie nie zmieniasz wartości current_ptr. jak więc ma się zakończyć ta pętla?

MJay napisał(a)
Madziaq napisał(a)
  1. pyt czemu musi we wyszukiwaniu być rekuręcja, a nie wystarczy petla while?

Nie musi być rekurencji, można poradzić sobie z pętlą, ale uważam, że rekurencja jest znacznie wygodniejsza
pętla jest szybsza i mniej pamięciożerna, szczególnie w tak prostym zastosowaniu.

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