Wywołanie malloc() zatrzymuje program

Wywołanie malloc() zatrzymuje program
Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:293
0

Panowie, potrzebuję znowu pomocy. Otóż modyfikuję sobie programik bo chcę uzyskać implementację tablicy z tzw. haszowaniem i funkcją haszującą z wykorzystaniem dynamicznie tworzonych list. Na instrukcji malloc() program zatrzymuje swoje działanie, czy ktoś może mi powiedzieć dlaczego tak się dzieje (a dzieje się to wówczas gdy wciskam "1" czyli insertujemy nowy element i wpisuję np. 15464 a potem 23).
Przedstawiam kod:

Kopiuj
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

/* Node for storing an item in a Linked List */
struct node
{
    int key;
    int value;
    struct node *next;
};

/* For storing a Linked List at each index of Hash Table  */
struct arrayitem
{
    struct node *head;
    /* head pointing the first element of Linked List at an index of Hash Table */

    struct node *tail;
    /* tail pointing the last element of Linked List at an index of Hash Table */
};

struct arrayitem *array;

int size = 0;         /* Determines the no. of elements present in Hash Table */
int max = 10;	      /* Determines the maximum capacity of Hash Table array */


struct node* get_element(struct node *list, int find_index);
void remove_element(int key);
void rehash();
void init_array();
int find(struct node *list, int key);


/* This function creates an index corresponding to the every given key */
int hashcode(int key)
{
    return (key % max);
}

void insert(int key, int value)
{
    float n = 0.0;
    /* n => Load Factor, keeps check on whether rehashing is required or not */

    int index = hashcode(key);

    /* Extracting Linked List at a given index */
    struct node *list = (struct node*) array[index].head;

    printf("Test");

    /* Creating an item to insert in the Hash Table */
    struct node *item = (struct node*) malloc(sizeof(struct node));

    printf("Test2");

    item->key = key;
    item->value = value;
    item->next = NULL;

    if (list == NULL)
    {
        /* Absence of Linked List at a given Index of Hash Table */
        printf("Inserting %d(key) and %d(value) \n", key, value);
        array[index].head = item;
        array[index].tail = item;
        size++;
    }
    else
    {
        /* A Linked List is present at given index of Hash Table */
        int find_index = find(list, key);

        if (find_index == -1)
        {
            /* Key not found in existing linked list , Adding the key at the end of the linked list	*/
            array[index].tail->next = item;
            array[index].tail = item;
            size++;
        }
        else
        {
            /* Key already present in linked list , Updating the value of already existing key */
            struct node *element = get_element(list, find_index);
            element->value = value;
        }
    }

    //Calculating Load factor
    n = (1.0 * size) / max;
    if (n >= 0.75)
    {
        //rehashing
        printf("going to rehash\n");
        rehash();
    }
}

void rehash()
{
    struct arrayitem *temp = array;
    /* temp pointing to the current Hash Table array */

    int i = 0, n = max;
    size = 0;
    max = 2 * max;

    /* array variable is assigned with newly created Hash Table with double of previous array size */
    array = (struct arrayitem*) malloc(max * sizeof(struct node));
    init_array();

    for (i = 0; i < n; i++)
    {
        /* Extracting the Linked List at position i of Hash Table array */
        struct node* list = (struct node*) temp[i].head;
        if (list == NULL)
        {
            /* if there is no Linked List, then continue */
            continue;
        }
        else
        {
            /* Presence of Linked List at i Keep moving and accessing the Linked List item until the end.
             *Get one key and value at a time and add it to new Hash Table array. */
            while (list != NULL)
            {
                insert(list->key, list->value);
                list = list->next;
            }
        }
    }
    temp = NULL;
}

/* This function finds the given key in the Linked List Returns it's index , Returns -1 in case key is not present */
int find(struct node *list, int key)
{
    int retval = 0;
    struct node *temp = list;
    while (temp != NULL)
    {
        if (temp->key == key)
        {
            return retval;
        }
        temp = temp->next;
        retval++;
    }
    return -1;
}

/* Returns the node (Linked List item) located at given find_index  */
struct node* get_element(struct node *list, int find_index)
{
    int i = 0;
    struct node *temp = list;
    while (i != find_index)
    {
        temp = temp->next;
        i++;
    }
    return temp;
}

/* To remove an element from Hash Table */
void remove_element(int key)
{
    int index = hashcode(key);
    struct node *list = (struct node*) array[index].head;

    if (list == NULL)
    {
        printf("This key does not exists\n");
    }
    else
    {
        int find_index = find(list, key);
        if (find_index == -1)
        {
            printf("This key does not exists\n");
        }
        else
        {
            struct node *temp = list;
            if (temp->key == key)
            {
                array[index].head = temp->next;
                printf("This key has been removed\n");
                return;
            }

            while (temp->next->key != key)
            {
                temp = temp->next;
            }

            if (array[index].tail == temp->next)
            {
                temp->next = NULL;
                array[index].tail = temp;
            }
            else
            {
                temp->next = temp->next->next;
            }

            printf("This key has been removed\n");
        }
    }
}

/* To display the contents of Hash Table */
void display()
{
    int i = 0;
    for (i = 0; i < max; i++)
    {
        struct node *temp = array[i].head;
        if (temp == NULL)
        {
            printf("array[%d] has no elements\n", i);
        }
        else
        {
            printf("array[%d] has elements-: ", i);
            while (temp != NULL)
            {
                printf("key= %d  value= %d\t", temp->key, temp->value);
                temp = temp->next;
            }
            printf("\n");
        }
    }
}

/* For initializing the Hash Table */
void init_array()
{
    int i = 0;
    for (i = 0; i < max; i++)
    {
        array[i].head = NULL;
        array[i].tail = NULL;
    }
}

/* Returns size of Hash Table */
int size_of_array()
{
    return size;
}

int main()
{
    int choice, key, value, n, c;
    system("cls");

    array = (struct arrayitem*) malloc(max * sizeof(struct arrayitem*));
    printf("xz\n");
    init_array();
    printf("xyz");
    do {

        printf("Implementation of Hash Table in C chaining with Singly Linked List \n\n");
        printf("MENU-: \n1.Inserting item in the Hash Table"
                              "\n2.Removing item from the Hash Table"
                              "\n3.Check the size of Hash Table"
                              "\n4.To display a Hash Table"
               "\n\n Please enter your choice -: ");

        scanf("%d", &choice);

        switch(choice)
        {
            case 1:
              printf("Inserting element in Hash Table\n");
              printf("Enter key and value-:\t");
              scanf("%d", &key);
              scanf("%d", &value);
              insert(key, value);
              break;

            case 2:
              printf("Deleting in Hash Table \nEnter the key to delete-:");
              scanf("%d", &key);
              remove_element(key);
              break;

            case 3:
              n = size_of_array();
              printf("Size of Hash Table is-:%d\n", n);
              break;

            case 4:
              display();
              break;

            default:
              printf("Wrong Input\n");
              break;
        }

        printf("\nDo you want to continue-:(press 1 for yes)\t");
        scanf("%d", &c);
    }
    while(c == 1);

    getch();
    return 0;
}

Wyświetla się "Test", ale już nie "Test2".
Proszę również zignorować to że nie ma zwalniania pamięci w programie, to tylko test, docelowo będzie oczywiście, nie chciało mi się tego wstawiać na razie.
Może ktoś to przetestować na swoim kompie wpisując te dane i sprawdzając czy "test2" się pojawi czy nie...?

edytowany 6x, ostatnio: Adamos19
Zobacz pozostałe 8 komentarzy
enedil
Undefined Behaviour, poszukaj
Miang
oznacza że @enedil chce sie z kimś pokłó.... podyskutować
Adamos19
wiem co to undefined behaviour ale skąd mam wiedzieć że akurat UB oznacza właśnie to. Kiedyś oznaczało to coś innego... hehe
enedil
@Miang: to ty jesteś akurat tutaj zaczepna
enedil
@Adamos19: jestem na tyle młody, że nie kojarzy mi się automatycznie z tym o czym myślałeś
enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:3 dni
  • Postów:1027
5
Kopiuj
xz
=================================================================
==296357==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x607000000070 at pc 0x000000402290 bp 0x7ffc92efe7e0 sp 0x7ffc92efe7d8
WRITE of size 8 at 0x607000000070 thread T0
    #0 0x40228f in init_array() /tmp/xd.cc:243
    #1 0x402446 in main /tmp/xd.cc:260
    #2 0x7f556f04a50f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #3 0x7f556f04a5c8 in __libc_start_main_impl ../csu/libc-start.c:381
    #4 0x400bf4 in _start (/tmp/a.out+0x400bf4)

0x607000000070 is located 0 bytes to the right of 80-byte region [0x607000000020,0x607000000070)
allocated by thread T0 here:
    #0 0x7f556feba6af in __interceptor_malloc (/lib64/libasan.so.8+0xba6af)
    #1 0x402430 in main /tmp/xd.cc:258
    #2 0x7f556f04a50f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow /tmp/xd.cc:243 in init_array()
Shadow bytes around the buggy address:
  0x0c0e7fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0e7fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0e7fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0e7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0e7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c0e7fff8000: fa fa fa fa 00 00 00 00 00 00 00 00 00 00[fa]fa
  0x0c0e7fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==296357==ABORTING

napraw to

Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:293
0

W jaki sposób? Czy ktoś może mi powiedzieć w jaki sposób to naprawić? Zauważyłem dodatkowo że po usunięciu dwóch linii kodu, ale tylko printf z początku:

Kopiuj
    printf("xz\n");

    printf("xyz");

to w ogóle przestało mi w ogóle wyświeltać informację z opisem, a więc wnioskuję (być może błędnie) że po usunięciu tych dwóch linii kodu z tylko i wyłącznie rozkazami printf, nie działa początkowy malloc. A zatem pytanie brzmi: jaki związek ma printf z mallociem bo ja go w ogóle nie widzę i kompletnie nie rozumiem z czego wynika i jak naprawić ten problem z przepełnieniem sterty.
Potrzebuję pomocy fachowca.

Tak więc teraz mam taki kod i już nie wyświetla się nic i program po odpaleniu się kończy niezwłocznie nic nie wypisując nawet:

Kopiuj
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

    /* Node for storing an item in a Linked List */
    struct node
    {
    	int key;
    	int value;
    	struct node *next;
    };

    /* For storing a Linked List at each index of Hash Table  */
    struct arrayitem
    {
    	struct node *head;
    	/* head pointing the first element of Linked List at an index of Hash Table */

    	struct node *tail;
    	/* tail pointing the last element of Linked List at an index of Hash Table */
    };

    struct arrayitem *array;

    int size = 0;         /* Determines the no. of elements present in Hash Table */
    int max = 10;	      /* Determines the maximum capacity of Hash Table array */


    struct node* get_element(struct node *list, int find_index);
    void remove_element(int key);
    void rehash();
    void init_array();
    int find(struct node *list, int key);


    /* This function creates an index corresponding to the every given key */
    int hashcode(int key)
    {
    	return (key % max);
    }

    void insert(int key, int value)
    {
      	float n = 0.0;
      	/* n => Load Factor, keeps check on whether rehashing is required or not */

    	int index = hashcode(key);

    	/* Extracting Linked List at a given index */
    	struct node *list = (struct node*) array[index].head;

    	printf("Test");

    	/* Creating an item to insert in the Hash Table */
    	struct node *item = (struct node*) malloc(sizeof(struct node));

    	printf("Test2");

    	item->key = key;
    	item->value = value;
    	item->next = NULL;

    	if (list == NULL)
        {
    		/* Absence of Linked List at a given Index of Hash Table */
    		printf("Inserting %d(key) and %d(value) \n", key, value);
    		array[index].head = item;
    		array[index].tail = item;
    		size++;
    	}
        else
        {
        	/* A Linked List is present at given index of Hash Table */
    		int find_index = find(list, key);

    		if (find_index == -1)
    		{
    			/* Key not found in existing linked list , Adding the key at the end of the linked list	*/
    			array[index].tail->next = item;
    			array[index].tail = item;
    			size++;
    		}
    		else
            {
    			/* Key already present in linked list , Updating the value of already existing key */
    			struct node *element = get_element(list, find_index);
    			element->value = value;
            }
    	}

    	//Calculating Load factor
    	n = (1.0 * size) / max;
    	if (n >= 0.75)
        {
    		//rehashing
    		printf("going to rehash\n");
    		rehash();
    	}
    }

    void rehash()
    {
    	struct arrayitem *temp = array;
    	/* temp pointing to the current Hash Table array */

    	int i = 0, n = max;
    	size = 0;
    	max = 2 * max;

    	/* array variable is assigned with newly created Hash Table with double of previous array size */
    	array = (struct arrayitem*) malloc(max * sizeof(struct node));
    	init_array();

    	for (i = 0; i < n; i++)
        {
    		/* Extracting the Linked List at position i of Hash Table array */
     		struct node* list = (struct node*) temp[i].head;
    		if (list == NULL)
    		{
    			/* if there is no Linked List, then continue */
    			continue;
    		}
    		else
    		{
    			/* Presence of Linked List at i Keep moving and accessing the Linked List item until the end.
    			 *Get one key and value at a time and add it to new Hash Table array. */
    			while (list != NULL)
    			{
    				insert(list->key, list->value);
    				list = list->next;
    			}
    		}
    	}
    	temp = NULL;
    }

    /* This function finds the given key in the Linked List Returns it's index , Returns -1 in case key is not present */
    int find(struct node *list, int key)
    {
    	int retval = 0;
    	struct node *temp = list;
    	while (temp != NULL)
    	{
    		if (temp->key == key)
    		{
    			return retval;
    		}
      		temp = temp->next;
    		retval++;
    	}
    	return -1;
    }

    /* Returns the node (Linked List item) located at given find_index  */
    struct node* get_element(struct node *list, int find_index)
    {
    	int i = 0;
    	struct node *temp = list;
    	while (i != find_index)
    	{
    		temp = temp->next;
    		i++;
    	}
    	return temp;
    }

    /* To remove an element from Hash Table */
    void remove_element(int key)
    {
    	int index = hashcode(key);
    	struct node *list = (struct node*) array[index].head;

    	if (list == NULL)
    	{
    		printf("This key does not exists\n");
    	}
    	else
    	{
    		int find_index = find(list, key);
    		if (find_index == -1)
    		{
    			printf("This key does not exists\n");
    		}
    		else
    		{
     			struct node *temp = list;
    			if (temp->key == key)
    			{
      				array[index].head = temp->next;
    				printf("This key has been removed\n");
    				return;
    			}

    			while (temp->next->key != key)
    			{
     				temp = temp->next;
    			}

      			if (array[index].tail == temp->next)
      			{
    				temp->next = NULL;
    				array[index].tail = temp;
    			}
      			else
      			{
    				temp->next = temp->next->next;
    			}

    			printf("This key has been removed\n");
    		}
    	}
    }

    /* To display the contents of Hash Table */
    void display()
    {
    	int i = 0;
    	for (i = 0; i < max; i++)
    	{
    		struct node *temp = array[i].head;
    		if (temp == NULL)
    		{
    			printf("array[%d] has no elements\n", i);
    		}
    		else
    		{
    			printf("array[%d] has elements-: ", i);
    			while (temp != NULL)
    			{
    				printf("key= %d  value= %d\t", temp->key, temp->value);
    				temp = temp->next;
    			}
    			printf("\n");
    		}
    	}
    }

    /* For initializing the Hash Table */
    void init_array()
    {
    	int i = 0;
    	for (i = 0; i < max; i++)
    	{
    		array[i].head = NULL;
    		array[i].tail = NULL;
    	}
    }

    /* Returns size of Hash Table */
    int size_of_array()
    {
    	return size;
    }

    int main()
    {
    	int choice, key, value, n, c;
    	system("cls");

    	array = (struct arrayitem*) malloc(max * sizeof(struct arrayitem*));
    	init_array();
    	do {

    		printf("Implementation of Hash Table in C chaining with Singly Linked List \n\n");
    		printf("MENU-: \n1.Inserting item in the Hash Table"
                                  "\n2.Removing item from the Hash Table"
                                  "\n3.Check the size of Hash Table"
                                  "\n4.To display a Hash Table"
    		       "\n\n Please enter your choice -: ");

     		scanf("%d", &choice);

     		switch(choice)
     		{
     			case 1:
    		      printf("Inserting element in Hash Table\n");
    		      printf("Enter key and value-:\t");
    		      scanf("%d", &key);
    		      scanf("%d", &value);
    		      insert(key, value);
    		      break;

     			case 2:
     			  printf("Deleting in Hash Table \nEnter the key to delete-:");
    		      scanf("%d", &key);
    		      remove_element(key);
    		      break;

     			case 3:
    		      n = size_of_array();
    		      printf("Size of Hash Table is-:%d\n", n);
    		      break;

     			case 4:
    		      display();
    		      break;

     			default:
    		      printf("Wrong Input\n");
    		      break;
    		}

    		printf("\nDo you want to continue-:(press 1 for yes)\t");
    		scanf("%d", &c);
    	}
    	while(c == 1);

    	getch();
    	return 0;
    }

edytowany 1x, ostatnio: Adamos19
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
2

Masz strasznie przekombinowane funkcje.
Ponad 10 wierszy - trzeba dzielić - pamiętaj, dziel i rządź!
Używaj wyjątków (assert) zamiast ifologii połączonej ze smarowaniem po konsoli.
To samo da się zapisać co najmniej 5 razy krócej, przy czym odzyskując kontrole nad kodem.
Teraz to on cię kontroluje.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
Althorion
Kod jest w C — wyjątki raczej odpadają.
_13th_Dragon
asserty to można powiedzieć C - wyjątki :D Chodzi o to że jak program dal plamę to nie ma sensu smarować po konsoli.
Althorion
Napatrzyłem się w tym tygodniu na przepiękny kod z longjmpami i bałem się przez moment, że to to proponujesz. 😅
_13th_Dragon
Nie, owszem nie jestem zbyt normalny (jak każdy informatyk) ale jeszcze nie tyle odpłynąłem :D Poprawiłem!
Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:293
0

Niestety ale muszę przyznać się że nie potrafię jeszcze tego zrobić. Przeczytałem tylko to: https://pl.wikibooks.org/wiki/C/assert
Niestety nie rozumiem jak miałbym wyłapać "wyjątek" związany z mallociem w kodzie używając takiego asserta.

edytowany 2x, ostatnio: Adamos19
IN
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 2 lata
  • Postów:60
0

Po pierwsze, podziel program na logiczne części. Przy każdej dawaj printf() i niech wypisuje co się dzieje. I sprawdzaj kolejno czy wszystko jest w porządku. Krok po kroku. Od deklaracji zmiennych, przez przypisywanie im wartości, przez alokowanie pamięci, przez ustawianie wskaźników po czyszczenie pamięci. I przyzwyczajaj się do takiego pisania dokąd się nie nauczysz/nie nabierzesz doświadczenia w praktyce gdzie w 90% przypadków będzie to już dla Ciebie zbędne.

Mam pytanie, po co Ci funkcja "size_of_array()"? W programowaniu obiektowym to by miało sens, bo zabezpieczenia mogłyby krzyczeć ale tutaj? (chyba, że zamierzasz ją dopiero tworzyć).

edytowany 2x, ostatnio: infinityhost
Adamos19
Ale moim zdaniem kod jest podzielony na logiczne części. A jeśli coś jest wg Ciebie nielogiczne to umotywuj to proszę jakoś. Fazę nauczania której podstawą jest debugowanie kodu i potwierdzania wykonania się każdej instrukcji już przechodziłem, nie wiem dlaczego teraz miałbym do tego wracać. Czy to rzeczywiście jest w tym wypadku konieczne?
Adamos19
Funkcja size_of_array() jest po to bo wartość "size" może ulegać zmianie w programie.
IN
Piszesz, że program nie działa. Kompilator Ci to sam pokazuje. Gdyby program był napisany prawidłowo, nie byłoby problemu.
IN
Pytałem, czy zamierzasz ją dokańczać czy zostawiać tak jak jest. Nie wiem na jakim etapie pisania jesteś, czy skopiowałeś skądś niepełny kod i jest bo jest, czy zaplanowałeś go dokończyć. Jeśli zamierzasz wypełnić tą funkcję to mógłbyś dać komentarz np. //tutaj będzie zliczana ilość elementów typu node w programie.
IN
Co to jest "struct arrayitem *array;" czemu nie napisałeś do czego ma służyć ta zmienna?
IN
Czy nie uważasz, że element *head powinien być zadeklarowany w programie na samym początku? Od niego będziesz zapewne zaczynał dużo działań(jeśli nie wszystkie).
IN
Robisz dynamiczną tablicę czy nie? Jeśli tak to rób wywołanie "malloc" dla każdego elementu "node", nie za bardzo ogarniam ten Twój programik ale dla mnie takie właśnie rozwiązanie by miało sens. Tworzysz procedurę "add_new_node()" w niej wczytujesz zawartość tego nowego "node" potem alokujesz pamięć, zamieniasz ostatni element w tablicy (jego wskaźnik "next" na ten nowo utworzony, a wskaźnik "next" nowo utworzonego na null. Jeśli operacja się powiodła dajesz printf("%s","New item added!"); Inkrementujesz zmienna "size" w programie.
Adamos19
Trochę pomyliłeś pojęcia. To nie jest lista dwukierunkowa, tylko tablica z haszowaniem i tylko oparta o dynamicznie tworzone listy. Funkcję size_of_array() może zmodyfikuję może nie, zobaczymy. Zostawiam sobie do tego furtkę, podobnie jak do modyfikacji innych części tego kodu. "Gdyby program był napisany prawidłowo, nie byłoby problemu" - tak, też w to wierzę. struct arrayItem *array to właśnie wskaźnik do tablicy haszującej opartej o dynamicznie tworzone listy. Żaden element *head nie istnieje dopóki nie włączysz programu i nie zrobisz inserta, panie kolego.
Adamos19
Strasznie się rozkręciłeś a problem jest gdzie indziej bo terminuje się przy początkowej inicjalizacji wskaźników.
IN
Taki już jestem, łatwo się rozkręcam. Wiesz jak rozwiązali ten problem twórcy C# ? Jak chcesz usunąć element to we wbudowanej funkcji podajesz wskaźnik do elementu typu jakiego jest ta tablica obiektów. Ja też uważam, że podawanie indexu nie jest złe, oni wpadli na taki pomysł. Chcesz ich uczyć jak się powinno usuwać elementy? Bo tutaj używasz indexu jeśli dobrze widzę. Ja bym chyba użył wskaźnika do obiektu.
IN
get_element(struct node *list, int find_index) co robi parametr node *list?
IN
A nie myślałeś o tym, żeby zakomentować całość poza definicją struct *node{} deklaracją node *arrayitem i tym pierwszym malloc i od tego zacząć?
IN
W jakim celu umieszczasz na stercie ten obiekt array? Przecież tam masz tylko 2 elementy.
enedil
get_element(struct node *list, int find_index) co robi parametr node *list? a umiesz czytać kod? Jak najbardziej coś robi
IN
@enedil: a widzisz obiekt arrayitem i jego element head? Masz dostęp do niego cały czas. Więc po co drugi taki wskaźnik do początku? (chyba, że chłopak planuje działania na kilku listach typu *node). Ale wtedy by utworzył strukturę do tych list. Moim zdaniem duplikuje wskaźniki do obiektów a to świadczy, że nie ma kontroli nad kodem.
enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:3 dni
  • Postów:1027
1

Wrócmy jeszcze raz do tego:

Kopiuj
==296357==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x607000000070 at pc 0x000000402290 bp 0x7ffc92efe7e0 sp 0x7ffc92efe7d8
WRITE of size 8 at 0x607000000070 thread T0
    #0 0x40228f in init_array() /tmp/xd.cc:243
    #1 0x402446 in main /tmp/xd.cc:260
    #2 0x7f556f04a50f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #3 0x7f556f04a5c8 in __libc_start_main_impl ../csu/libc-start.c:381
    #4 0x400bf4 in _start (/tmp/a.out+0x400bf4)

0x607000000070 is located 0 bytes to the right of 80-byte region [0x607000000020,0x607000000070)
allocated by thread T0 here:
    #0 0x7f556feba6af in __interceptor_malloc (/lib64/libasan.so.8+0xba6af)
    #1 0x402430 in main /tmp/xd.cc:258
    #2 0x7f556f04a50f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

tutaj komunikat mówi, że zapisujesz coś za tablicą (0 bajtów na prawo od regionu 80-batjowego). Zastanów się, czemu w init_array byś miał zapisywać coś na bajcie 80 (80==80+0).

Nie rozumiem wniosków na temat usuwania printfów. Wyjaśnisz? Poza tym, z pewnością masz świadomość, że printf wcale nie gwarantuje, że dane które wypisujesz znajdą się natychmiastowo na konsoli? One mogą być buforowane - to znaczy, że dopóki danych jest dostatecznie mało, może się zdarzyć tak, że się będą agregować w tablicy, i dopiero jak się zbiorą, zostaną wszystkie naraz wypisane. Chociaż tutaj akurat pewnie tak się nie dzieje.

edytowany 1x, ostatnio: enedil
Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:293
1

Wiecie co, dziękuję wszystkim za chęć pomocy. Poradzę sobie z tym sam, bo dopiero teraz widzę że printf nie mają tutaj nic do rzeczy.
Kwestia czasu.
Pozdrawiam.

Zobacz pozostały 1 komentarz
IN
Wracaj tu tchórzu! xD
Adamos19
Panowie spokojnie, wymyślę to przyjdę i poinformuję jak rozwiązałem problem. Oczywiście zrobię to z myślą o Was drodzy koledzy bo naprawdę Was lubię i szanuję. Jestem także wdzięczny za chęci pomocy i obiecuję że wrócę z rozwiązaniem problemu. Pozdrawiam.
_13th_Dragon
Dokładnie! O problemach raportować po wykonaniu zadania! :D
Adamos19
A mam jakieś inne wyjście ?! :D
IN
Zawsze możesz się poddać. xD
Adamos19
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Postów:293
0

Dobra Panowie. Problem zidentyfikowany, o jedną gwiazdkę za dużo było. Teraz powinno być ok:

Kopiuj
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <assert.h>

/* Node for storing an item in a Linked List */
struct node
{
	int key;
	int value;
	struct node *next;
};

/* For storing a Linked List at each index of Hash Table  */
struct arrayitem
{
	struct node *head;
	/* head pointing the first element of Linked List at an index of Hash Table */

	struct node *tail;
	/* tail pointing the last element of Linked List at an index of Hash Table */
};

struct arrayitem *array;

int size = 0;         /* Determines the no. of elements present in Hash Table */
int max = 10;	      /* Determines the maximum capacity of Hash Table array */

struct node* get_element(struct node *list, int find_index);
void remove_element(int key);
void rehash();
void init_array();
int find(struct node *list, int key);


/* This function creates an index corresponding to the every given key */
int hashcode(int key)
{
	return (key % max);
}

void insert(int key, int value)
{
	float n = 0.0;
	/* n => Load Factor, keeps check on whether rehashing is required or not */

	int index = hashcode(key);

	/* Extracting Linked List at a given index */
	struct node *list = (struct node*) array[index].head;

	/* Creating an item to insert in the Hash Table */
	struct node *item = (struct node*) malloc(sizeof(struct node));

	item->key = key;
	item->value = value;
	item->next = NULL;

	if (list == NULL)
	{
		/* Absence of Linked List at a given Index of Hash Table */
		printf("Inserting %d(key) and %d(value) \n", key, value);
		array[index].head = item;
		array[index].tail = item;
		size++;
	}
	else
	{
		/* A Linked List is present at given index of Hash Table */
		int find_index = find(list, key);

		if (find_index == -1)
		{
			/* Key not found in existing linked list , Adding the key at the end of the linked list	*/
			array[index].tail->next = item;
			array[index].tail = item;
			size++;
		}
		else
		{
			/* Key already present in linked list , Updating the value of already existing key */
			struct node *element = get_element(list, find_index);
			element->value = value;
		}
	}

	//Calculating Load factor
	n = (1.0 * size) / max;
	if (n >= 0.75)
	{
		//rehashing
		printf("going to rehash\n");
		rehash();
	}
}

void rehash()
{
	struct arrayitem *temp = array;
	/* temp pointing to the current Hash Table array */

	int i = 0, n = max;
	size = 0;
	max = 2 * max;

	/* array variable is assigned with newly created Hash Table with double of previous array size */
	array = (struct arrayitem*) malloc(max * sizeof(struct node));

	init_array();

	for (i = 0; i < n; i++)
	{
		/* Extracting the Linked List at position i of Hash Table array */
		struct node* list = (struct node*) temp[i].head;
		if (list == NULL)
		{
			/* if there is no Linked List, then continue */
			continue;
		}
		else
		{
			/* Presence of Linked List at i Keep moving and accessing the Linked List item until the end.
			 *Get one key and value at a time and add it to new Hash Table array. */
			while (list != NULL)
			{
				insert(list->key, list->value);
				list = list->next;
			}
		}
	}
	temp = NULL;
}

/* This function finds the given key in the Linked List Returns it's index , Returns -1 in case key is not present */
int find(struct node *list, int key)
{
	int retval = 0;
	struct node *temp = list;
	while (temp != NULL)
	{
		if (temp->key == key)
		{
			return retval;
		}
		temp = temp->next;
		retval++;
	}
	return -1;
}

/* Returns the node (Linked List item) located at given find_index  */
struct node* get_element(struct node *list, int find_index)
{
	int i = 0;
	struct node *temp = list;
	while (i != find_index)
	{
		temp = temp->next;
		i++;
	}
	return temp;
}

/* To remove an element from Hash Table */
void remove_element(int key)
{
	int index = hashcode(key);
	struct node *list = (struct node*) array[index].head;

	if (list == NULL)
	{
		printf("This key does not exists\n");
	}
	else
	{
		int find_index = find(list, key);
		if (find_index == -1)
		{
			printf("This key does not exists\n");
		}
		else
		{
			struct node *temp = list;
			if (temp->key == key)
			{
				array[index].head = temp->next;
				printf("This key has been removed\n");
				return;
			}

			while (temp->next->key != key)
			{
				temp = temp->next;
			}

			if (array[index].tail == temp->next)
			{
				temp->next = NULL;
				array[index].tail = temp;
			}
			else
			{
				temp->next = temp->next->next;
			}

			printf("This key has been removed\n");
		}
	}
}

/* To display the contents of Hash Table */
void display()
{
	int i = 0;
	for (i = 0; i < max; i++)
	{
		struct node *temp = array[i].head;
		if (temp == NULL)
		{
			printf("array[%d] has no elements\n", i);
		}
		else
		{
			printf("array[%d] has elements-: ", i);
			while (temp != NULL)
			{
				printf("key= %d  value= %d\t", temp->key, temp->value);
				temp = temp->next;
			}
			printf("\n");
		}
	}
}

/* For initializing the Hash Table */
void init_array()
{
	int i = 0;
	for (i = 0; i < max; i++)
	{
		array[i].head = NULL;
		array[i].tail = NULL;
	}
}

/* Returns size of Hash Table */
int size_of_array()
{
	return size;
}

int main()
{
	int choice, key, value, n, c;
	system("cls");

	array = (struct arrayitem*) malloc(max * sizeof(struct arrayitem));

	init_array();
	do {

		printf("Implementation of Hash Table in C chaining with Singly Linked List \n\n");
		printf("MENU-: \n1.Inserting item in the Hash Table"
				"\n2.Removing item from the Hash Table"
				"\n3.Check the size of Hash Table"
				"\n4.To display a Hash Table"
				"\n\n Please enter your choice -: ");

		scanf("%d", &choice);

		switch(choice)
		{
			case 1:
				printf("Inserting element in Hash Table\n");
				printf("Enter key and value-:\t");
				scanf("%d", &key);
				scanf("%d", &value);
				insert(key, value);
				break;

			case 2:
				printf("Deleting in Hash Table \nEnter the key to delete-:");
				scanf("%d", &key);
				remove_element(key);
				break;

			case 3:
				n = size_of_array();
				printf("Size of Hash Table is-:%d\n", n);
				break;

			case 4:
				display();
				break;

			default:
				printf("Wrong Input\n");
				break;
		}

		printf("\nDo you want to continue-:(press 1 for yes)\t");
		scanf("%d", &c);
	} while(c == 1);

	getch();
	return 0;
}

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

Znacznie lepiej, ale nadal za długie te funkcje.

Np:

Kopiuj
struct node
{
    int key;
    int value;
    struct node *next;
};

Zamieniamy na:

Kopiuj
typedef struct _node
{
    int key;
    int value;
    struct _node *next;
} node;

Więc dalej zapominamy o słowie struct

Np:

Kopiuj
    	struct node *item = (struct node*) malloc(sizeof(struct node));

    	printf("Test2");

    	item->key = key;
    	item->value = value;
    	item->next = NULL;
Kopiuj
node *makenode(int key,int value,node *next)
{
    node *item=(node*)malloc(sizeof(node));
    assert(item!=NULL);
    item->key=key;
    item->value=value;
    item->next=next;
    return item;
}

oraz użycie:

Kopiuj
    	struct node *item=makenode(key,value,NULL);

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
Zobacz pozostałe 3 komentarze
_13th_Dragon
Owszem tego assert nie wyłapie, ale wyłapie twoje oko kiedy funkcje będą któtkie.
Adamos19
Ok, teraz załapałem ;) dzięki za wyjaśnienia. Pozdrawiam.
IN
I możesz dać getch() zamiast scanf(), ale przy tym kodzie to najmniejszy problem.
IN
Ty tworzysz statyczną tablicę obiektów czy mi się wydaje? I po co Ci wkaźnik "next" skoro masz tablicę obiektów?
IN
/* Key not found in existing linked list , Adding the key at the end of the linked list */ array[index].tail->next = item; array[index].tail = item; size++; -- ja to robiłem w taki sposób, że "tail" był zawsze NULL, a element ostatni podstawiałem za ostatnim (proste podstawienie i zamiana miejscami) słowem tworzysz funkcję node *find_last(); last->next=item;item->next=null;size++; i bez żadnych indexów.
IN
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 2 lata
  • Postów:60
0

Tutaj masz przykład jak można to zrobić (bez usuwania pojedyńczego elementu(chyba) - może potem to dodam, za to z usuwaniem wszystkich na koniec, no i może zliczę rozmiar pamięci aktualnie używanej przez listę oraz dodam opcję sortowania). Umieszczam na stercie tylko nowe elementy typu struct *node. Pojedyńczo. Jakieś tam drobne mankamenty są ale mniej więcej o coś takiego mi chodziło.

Kopiuj
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

/* Node for storing an item in a Linked List */
struct node
{
    int key;
    int value;
    int index;
    struct node *next;
};

/* For storing a Linked List at each index of Hash Table  */
struct arrayitem
{
    struct node *head;
    /* head pointing the first element of Linked List at an index of Hash Table */

    struct node *tail;
    /* tail pointing the last element of Linked List at an index of Hash Table */
};

struct arrayitem array;

int size = 0;         /* Determines the no. of elements present in Hash Table */
int max = 10;	      /* Determines the maximum capacity of Hash Table array */

// wyszukanie ostatniego elementu
struct node *find_last(){
	struct node *tmp_node;
	tmp_node=array.head;
	for(tmp_node=array.head;tmp_node->next!=NULL;tmp_node=tmp_node->next)
	{
	}
	return tmp_node;
}


// sprawdzenie czy istnieje juz obiekt o wpisanej przez uzytkownika wartosci pola "key"
struct node *check_list(int key_to_find){
	struct node *tmp_node;
	struct node *out_node=NULL;
	for(tmp_node=array.head;tmp_node->next!=NULL;tmp_node=tmp_node->next)
	{
		if(tmp_node->key==key_to_find){out_node=tmp_node;
		}
	}
	return out_node;
}

// prosta metoda wyswietlajaca pobiera element i dodaje pobrany opis
void print_item(struct node *tmp_node,char arr[20]){
printf("%s%d%s%d%s%d%s"," item with index ",tmp_node->index,"  with key ",tmp_node->key,"  and value ",tmp_node->value,arr);}

/* For initializing the Hash Table */
void init_array()
{
        array.head = NULL;
        array.tail = NULL;
 
}
// dodajemy nowy element
void insert(int key, int value)
{   
	struct node *tmp_node,*tmp_node_2,*item;
	
	if(size<max){ // skoro tak boisz się maxa

if(array.head==NULL){
		item = (struct node*) malloc(sizeof(struct node));

		item->key = key;
		item->value = value;
		item->next = NULL;
		item->index=size;
		printf("Inserting %d(key) and %d(value) \n", key, value);
		array.head = item;
		size++;
		}	
	else
	{	
		tmp_node_2 = check_list(key);
		
		// jesli element zostal znaleziony to podmieniamy wartosc value
		if(tmp_node_2!=NULL){
			
		tmp_node_2->value=value;	
		}
		else
		{
		item = (struct node*) malloc(sizeof(struct node));	
		item->key = key;
		item->value = value;
		item->next = NULL;
		item->index=size;	
		size++;	
		tmp_node_2 = find_last();	
		tmp_node_2->next = item;	
		}
	}
}
system("cls");
}

void display(){
system("cls");
struct node *tmp_node;
tmp_node=array.head;
printf("%s%d%s","Size of the list is  ",size,"\n");
if(array.head==NULL){
	printf("There are no items to view.");
	getch();
system("cls"); 
}else{

for(tmp_node=array.head;tmp_node!=NULL;tmp_node=tmp_node->next)
	{
		printf("%s%d%s%d%s%d%s","Index of element is ",tmp_node->index," with key ",tmp_node->key,"  has a value ",tmp_node->value,"\n");
	}	
	printf("Press any key to continue.");
	getch();
system("cls");	
}	
	
	
}
// funkcja zwalniajca pamiec

void freedom_for_lists(){

//usuwanie listy
int removed_size=0;
if(array.head!=NULL && array.head->next!=NULL){
	
struct node *tmp_node=array.head;
struct node *tmp_node_2;	
do{
tmp_node_2 = tmp_node;
tmp_node=tmp_node->next;
print_item(tmp_node, " shall be free!\n");
free(tmp_node_2);
removed_size++;	
}while(tmp_node!=NULL);	
	
}else{
if(size>1)	{removed_size=2;
print_item(array.head->next, " shall be free!\n");
free(array.head->next);
print_item(array.head, " shall be free!\n");
free(array.head);
}else{print_item(array.head, " shall be free!\n");removed_size=1;
free(array.head);
}}
printf("%s%d%s","Removed ",removed_size," items\n");
getch()	;
system("cls");
}




int main(int argc, char** argv) {

 	int choice, key, value, n, c;//choice=0;
   
	init_array();
	
	
	do {
	

					printf("Implementation of Hash Table in C chaining with Singly Linked List \n\n");
					printf("MENU-: \n1.Inserting item in the Hash Table"
				"\n2.Removing item from the Hash Table"
				"\n3.Check the size of Hash Table"
				"\n4.To display a Hash Table"
				"\n5.To quit press 0\n\n Please enter your choice -: ");

choice=getch();

switch(choice)
		{
			case 49:
			    system("cls");
				printf("Inserting element in Hash Table\n");
				printf("Enter key-:\n");
				scanf("%d", &key);
				printf("Enter value-:\n");
				scanf("%d", &value);
				insert(key, value);
				break;

			case 50:
				printf("Deleting in Hash Table \nEnter the key to delete-:");
				scanf("%d", &key);
			//	remove_element(key);
				break;

			case 51:
			//	n = size_of_array();
				printf("Size of Hash Table is-:%d\n", n);
				break;

			case 52:
				display();
				break;

			default:
				printf("Wrong Input\n");
				break;
		}

	

	
	}while(choice!=48);
	freedom_for_lists();
	return 0;
}
edytowany 1x, ostatnio: infinityhost
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
1
infinityhost napisał(a):
Kopiuj
struct arrayitem
{
    struct node *head;
    struct node *tail;
};

Widzę że masz wskaźnik na ostatni element, to dobrze.

infinityhost napisał(a):
Kopiuj
// wyszukanie ostatniego elementu
struct node *find_last(){
	struct node *tmp_node;
	tmp_node=array.head;
	for(tmp_node=array.head;tmp_node->next!=NULL;tmp_node=tmp_node->next)
	{
	}
	return tmp_node;
}

Doprawdy? A nie:

// wyszukanie ostatniego elementu
struct node *find_last() { return array.tail; }

Kopiuj

?

Za wcześnie dla ciebie kogoś nauczać.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Zobacz pozostałe 5 komentarzy
IN
I co tam wymyśliłeś nowego? Co jest czego mój kod nie robi? xD Na pierwszy rzut oka widzę, że dodałeś czyszczenie ekranu. Im więcej piszesz tym coraz mniejszą funkcjonalność Twoje rozwiązanie ma xD Możesz nawalić tego kodu w megabajtach ale czy wtedy cokolwiek będzie on jeszcze robił? Cokolwiek? xD A najlepsze, że wbiłeś sobie do głowy, że będziesz mnie pouczał. xD
_13th_Dragon
Zyskałeś 16 bajtów sprowadzając algorytm który ma działać w czasie O(1) do czasu O(N) i uważasz to za zaletę? Idź podstawy algorytmiki czytać.
IN
A Ty pozbywając się getcha i czekając na enter ile czasu marnotrawisz? Pomnóż razy ilość osób które potencjalnie by z tego korzystały i ich zdrowie biorąc pod uwagę frustrację która narasta w wyniku potrzeby klikania w klawisz który jest zbędny. Działasz jak jakiś wirus.
IN
Czekanie na wciśnięcie klawisza enter to jest 1msek czy 2msek? Kompletnie nie rozumujesz jak osoba która chce tworzyć oprogramowanie dla użytkowników. Na końcu programu jest człowiek i jego czas, tego nie bierzesz pod uwagę.
_13th_Dragon
Ten main nie jest dla użytkownika! Ocknij się trollu!
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

@infinityhost:
Albo ten tail używasz albo nie, bo jak masz ten tail którego ustawienie po każdym wstawianiu oraz usuwaniu ma koszt O(1) to nie ma co się zastanawiać i wyszukiwać ten koniec z kosztem O(N) Usuwanie tail!?!?
Puknij się w łeb pisanie kontenera który ma koszt wstawienia O(1) i używania w nim funkcji z kosztem O(N) - wylewasz kąpiel z dzieckiem!
Algorytmika się kłania! Na robocie to ty na 100% się nie znasz!
Różnica między nami jest taka że ja programuję zawodowo zaś ty znasz kilka instrukcji i tyle.
Do sprawdzenia służą testy jednostkowe a nie sam kod. Ja kontroluję kod podczas pisania czyli ten tail będzie zawsze odpowiedni i aktualizowany z kosztem O(1).
Zobacz jak ładnie działa tail myślący inaczej noob nieprogramisto:

Kopiuj
#include <stdio.h>
#include <stdlib.h>

#define GROWUP 1.8
#define SINKDOWN 0.4

typedef struct node
{
    int key;
    int value;
    struct node *next;
} node,*pnode;

typedef struct arrayitem
{
    pnode head,tail;
} arrayitem,*parrayitem;

typedef struct hashmap
{
	int listsize,size;
	parrayitem list;
} hashmap,*phashmap;

int hashcode(phashmap map,int key) { return key%(map->listsize); }

parrayitem listbykey(phashmap map,int key) { return map->list+hashcode(map,key); }

phashmap makemap(int listsize)
{
	phashmap ret=(phashmap)malloc(sizeof(hashmap));
	ret->listsize=listsize;
	ret->size=0;
	ret->list=(parrayitem)calloc(listsize,sizeof(arrayitem)); // wyzeruje
	return ret;
}

void freelist(parrayitem list)
{
	while(list->head)
	{
		pnode n=list->head;
		list->head=n->next;
		free(n);
	}
}

void freearray(parrayitem list,int listsize)
{
	for(int i=0;i<listsize;++i) freelist(list+i);
	free(list);
}

void freemap(phashmap map)
{
	freearray(map->list,map->listsize);
	free(map);
}

pnode makenode(int key,int value,pnode next)
{
    pnode ret=(pnode)malloc(sizeof(node));
    ret->key=key;
    ret->value=value;
    ret->next=next;
    return ret;
}

int containskey(parrayitem list,int key)
{
	for(pnode n=list->head;n;n=n->next) if(n->key==key) return 1;
	return 0;
}

int insertlist(parrayitem list,pnode item)
{
	if(list->tail) list->tail->next=item;
	else list->head=item;
	list->tail=item;
	return 1;
}

int insertnode(phashmap map,int key,int value)
{
    parrayitem list=listbykey(map,key);
	if(containskey(list,key)) return 0;
    insertlist(list,makenode(key,value,NULL));
    return 1;
}

void rehash(phashmap map,int newsize)
{
	phashmap tmpmap=makemap(newsize);
	int tmplistsize=map->listsize; // wymiana rozmiarów
	map->listsize=tmpmap->listsize;
	tmpmap->listsize=tmplistsize;
	parrayitem tmplist=map->list; // wymiana list
	map->list=tmpmap->list;
	tmpmap->list=tmplist;
    for(int i=0;i<tmpmap->listsize;++i)
    {
    	parrayitem list=tmpmap->list+i;
    	while(list->head)
		{
			pnode n=list->head;
			list->head=n->next;
			n->next=NULL;
			insertlist(listbykey(map,n->key),n);
		}
    }
    free(tmpmap->list);
}

int insertkey(phashmap map,int key,int value)
{
	if(!insertnode(map,key,value)) return 0;
    if(++map->size>=GROWUP*map->listsize) rehash(map,(map->listsize)<<1);
    return 1;
}

int removekey(phashmap map,int key)
{
	parrayitem list=listbykey(map,key);
	for(pnode p=NULL,n=list->head;n;p=n,n=n->next)
	{
		if(n->key==key)
		{
			if(p) p->next=n->next;
			else list->head=n->next;
			if(!n->next) list->tail=p;
			free(n);
			if(--map->size<=SINKDOWN*map->listsize) rehash(map,(map->listsize)>>1);
			return 1;
		}
	}
	return 0;
}

void display(phashmap map)
{
    for(int i=0;i<map->listsize;++i)
    {
    	parrayitem list=map->list+i;
	   	printf("list[%d]={",i);
	   	int first=1;
    	for(pnode n=list->head;n;n=n->next)
		{
			if(first) first=0; else printf(",");
			printf(" %d=>%d",n->key,n->value);
		}
		printf(" }\n");
    }
}

int main()
{
	phashmap map=makemap(1);
    printf("Implementation of Hash Table in C chaining with Singly Linked List\n\n");
    for(;;)
	{
        printf
		(
			"MENU:\n"
			"1. Inserting item in the Hash Table\n"
            "2. Removing item from the Hash Table\n"
            "3. To display a Hash Table\n"
            "0. Koniec\n"
		);
        int choice;
        while((printf("Please enter your choice: "))&&(scanf("%d",&choice)!=1)) while(getchar()!='\n') {}
        switch(choice)
	    {
    	    case 1:
    	    {
            	printf("Inserting element in Hash Table\n");
    	    	int key,value;
		        while((printf("Enter key and value: "))&&(scanf("%d%d",&key,&value)!=2)) while(getchar()!='\n') {}
	            if(insertkey(map,key,value)) display(map);
				else printf("Key %d already contains\n",key);
    	        break;
			}
            case 2:
            {
				printf("Deleting in Hash Table\n");
				int key;
        		while((printf("Enter the key to delete: "))&&(scanf("%d",&key)!=1)) while(getchar()!='\n') {}
				if(removekey(map,key)) display(map);
				else printf("Not found key %d\n",key);
				break;
			}
            case 3:
            {
            	display(map);
            	break;
			}
			case 0:
			{
				freemap(map);
			    return 0;
			}
            default:
            {
				printf("Wrong Input\n");
        		break;
			}
        }
    }
}

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Zobacz pozostałe 60 komentarzy
IN
@enedil: no uzyskujesz dostęp do każdego elementu. Nie rozumiem co tu jest niejasne. Dziękuję za wyrozumiałość, smoczek chciał, żeby nie pozwalać mi tu pisać.xD
enedil
@infinityhost no to pozdro, zmieniaj sobie tę listę w trakcie iteracji, jak uważasz że masz kontrolę
enedil
To się nie nazywa kontrola, to się nazywa wolny kod
enedil
Ale w sumie po tym jak to napisałeś, to już jestem przekonany, że trollujesz (wcześniej tylko to podejrzewałem)
enedil
Więc jak dla mnie EOT
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)