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:około 19 godzin
  • 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:3 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
Zobacz pozostałe 10 komentarzy
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:około 19 godzin
  • 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:3 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:3 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:3 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.
IN
Zasyfiasz cały ekran i pozbywasz się getch'a podwajając czas potrzebny do obsługi programu DWUKROTNIE(jeśli z tego miałoby korzystać milion osób to przelicz to ile czasu jest tracone) .Ty to chyba jakiś sabotażysta jesteś. Pomyśl logicznie ile ludziom tym byś czasu w życiu zmarnował. I żeby to zobaczyć nie trzeba nawet czytać kodu. I tym się różnimy, że ja jestem poważnym człowiekiem i takich chorych akcji nie odwalam. Jak nie masz świadomości tego co robisz, to tego NIE RÓB!
_13th_Dragon
Ty doprawdy uważasz że w tym kodzie to ten main jest najważniejszy? To tylko test wizualny. Mądralo ty się pozbyłeś historii działań tym cls czyli jak wybierzesz insert 584 => 25654 a potem wybierzesz display i zobaczysz 25854 => 564 to się nawet nie skapujesz że coś poszło nie tak? To jest ta zaleta twego śmieciowego kodu?
IN
Bo użytkownika to najbardziej obchodzi to co robił xD Tutaj tracisz dodatkowo czas na wyszukanie wzrokiem aktualnego wyniku ostatniego działania. Implementacja struktury która będzie zapisywała historię działań i wywoływanie metody ją wyświetlającej albo zapisywanie do pliku jest gorsze od tego zasyfiania ekranu i marnowania czasu które w swoim pato-kodzie zaprezentowałeś? "Test wizualny"? Nawet nie chciało Ci się dodać paru linijek żeby to chociaż próbowało po ludzku wyglądać. I co Ty takimi działaniami chcesz udowodnić?
IN
Mój kod jest estetyczny, czytelny, prowadzi użytkownika za rączke, minimalizuje czas potrzebny na korzystanie z niego, jest bezpieczny, prosty w edycji, gotowy na jego szybkie rozszerzenie. A Twój jaki? Jakie są zalety Twojego?
_13th_Dragon
Nikt nie będzie korzystać z tego main'a co najwyżej na etapie testu. Dalej będą korzystać z funkcji i struktur działających szybko. Natomiast twój kod zmarnuje masę czasu bo będzie działać w czasie O(N) zamiast O(1) ale widzę że nawet nie rozumiesz co to jest więc wyjaśniam. Załóżmy że mój kod O(1) dla 1tyś elementów działa 1 msek, to oznacza że dla 1mln elementów będzie działać 1sek, natomiast jeżeli twój kod O(N) dla 1tyś elementów działa 1 msek, to oznacza że dla 1mln elementów będzie działać 1mln sekund! To dopiero wirus i marnotrawstwo czasu ludzi!
IN
Pytałem w czym Twój kod jest lepszy od mojego. Widzę, że najlepiej się czujesz w operowaniu technologia kopiuj/wklej xD I domyślam się, że to czym próbujesz się chwalić to skopiowane bezmyślnie fragmenty czyichś kodów z internetu. I doszedłeś w tym kopiowaniu do takiego etapu że zacząłeś myśleć, że jesteś w stanie pouczać programistę xD Przypuszczam, że analizy byś nie rozpoznał nawet gdyby ta Ci splunęła w oko.
_13th_Dragon
Lepszy we wszystkim! Najważniejsze zalety (w porównywaniu do twojego): 1. Czas dodawania i usuwania: O(1) 2. Robi rehash przy nadmiarowym zapełnieniu albo przy zbyt małym zapełnieniu. 3. Pozwala usuwać elementy. 4. Robi 5 razy więcej rzeczy a jest krótszy od twojego. 5. Trzyma jednolite formatowanie kody w całym programie. 6. Realizuje ideę hashmap'y zgodnie z pytaniem OT (twój robi jakieś HGW co)
_13th_Dragon
Co do kopiuj/wklej ja mam bardzo specyficzny sposób formatowania, ci co mnie tu znają od lat, potwierdzą że nie ma wątpliwości, iż ten kod jest w 100% mój.
IN
No ja zauważyłem żę głównie zasyfia ekran i marnuje czas. I to zobaczy każdy, nawet nie programista.
_13th_Dragon
Dobra trollu, zostań w swoim wyimaginowanym świecie, jesteś nienauczany i niereformowalny.
IN
Nie no, Twój sposób myślenia mówi wszystko o tym jak jesteś w stanie pisać, dla Ciebie wyrażenie "struct node *find_last() { return array.tail; }" ma sens. Kompletnie nie rozumiesz technik programowania obiektowego, co to ma na celu. Może i byłbyś w stanie to zastosować, gdyby ktoś Ci przystawił rewolwer do skroni, ale po co to się robisz to już nie wiesz. Zastanawia mnie, że "ci co mnie tu znają od lat" nie zwrócili Ci na to uwagi xD Chyba też mają niezłą polewkę czytając co próbujesz płodzić na ogóle. xD
_13th_Dragon
Widzisz to gdzieś w moim kodzie? Zgadnij czemu.
Adamos19
Niestety @infinityhost ja też mam takie wrażenie że Ty bujasz w obłokach. Ze swojej strony dam Ci radę: trochę pokory.
IN
@_13th_Dragon: nie w Twoim kodzie tylko w Twojej wcześniejszej wypowiedzi. Ja czytając co piszesz, rozpoznaję Twój sposób myślenia. Jeśli dochodzisz do określonych wniosków to mogłeś to zrobić tylko w określony sposób operując na określonym zasobie wiedzy. I to mi wystarczy, żeby wyciągnąć wnioski, które są logiczne. Ale z logiką jeszcze chyba nie miałeś wcześniej przyjemności.xD
_13th_Dragon
Jedynie skróciłem i przyśpieszyłem twoją funkcje. "Ale z logiką jeszcze chyba nie miałeś wcześniej przyjemności" - mówi ten kto zmienił algorytm z O(1) na O(n) dla oszczędzenia 16 bajtów i nie jest w stanie zrozumieć czemu to źle? Powinieneś dostać zakazu pisania postów na tym forum.
IN
@Adamos19: i kolejny niewolnik w niewolniczym sposobem myślenia wśród nas to jest to co będzie dla nas dobre? Tak uważasz? W takim towarzystwie się czujesz najlepiej? Wśród takich ludzi chcesz żyć?
IN
@_13th_Dragon: przeczytałeś kod, dokonałeś oceny i zaprezentowałeś wynik. To nie jest przypadek. Za dużo funkcji w głowie musiałeś uruchomić. A te jak zawsze operują na danych (w tym wypadku tych, które są w Twojej dyspozycji). Z czym jeszcze chcesz polemizować?
Adamos19
@infinityhost Jeśli niewolnictwem nazywasz wolność wyboru i myślenia to gratuluję. Mam do Ciebie @infinityhost pytanie: czy zgodziłbyś się z twierdzeniem że to co dla niektórych jest niewolnictwem (co wobec tego odrzucają) dla niektórych jest bazą dodatkowej wiedzy. Teraz pytam Cię tylko o tą jedną rzecz. Odpowiedz proszę.
IN
" dla oszczędzenia 16 bajtów i nie jest w stanie zrozumieć czemu to źle?" - dla możliwości implementacji potencjalnych zabezpieczeń? To Ci przeszkadza w programach? Zabezpieczenia? Przecież operacji wyszukiwania ostatniego elementu można dodać tak wiele rzeczy, że ciężko to sobie wyobrazić. Przecież to jest cały wszechświat możliwości w zasięgu ręki.
_13th_Dragon
@infinityhost, może o tym że w twojej głowie nigdy nie ma za dużo funkcji może być tylko jedna na raz, oraz o tym ze ty niestety nie masz żadnych danych ani wystarczającej wiedzy aby przeczytać kod, dokonać oceny i zaprezentować wynik.
IN
@Adamos19: nie będę oceniał czegoś co dla mnie jest niedopuszczalne. Jak rozważasz w ogóle coś takiego, znaczy że nasz system edukacyjny jest spatologizowany.
_13th_Dragon
@infinityhost, racja! System edukacyjny jest spatologizowany! Zaś ty jesteś na to najlepszym dowodem!
IN
@_13th_Dragon: więc wynikiem czego jest moja wypowiedź "No ja zauważyłem żę głównie zasyfia ekran i marnuje czas" ( i najlepsze - do tego nie muszę czytać kodu, wystarczy, że użyję logicznego myślenia) Tutaj, jak widzisz , mam dostęp do dodatkowej metody i z niej korzystam(bazując oczywiście na mojej wiedzy). I do takiego wniosku powinieneś dojść po tym co Ci napisałem. Ale najwidoczniej przestałeś się uczyć.
IN
@_13th_Dragon: a w którym to miejscu mnie spatologizował? W tym, że wyrażam własne zdanie publicznie, w tym, że koryguje sposób myślenia człowieka który rozważa zalety i wady niewolnictwa, czy w tym, że myśle i na dodatek logicznie albo że jestem w stanie dokonać anlizy na podstawie przedstawionych mi informacji ?(z chęcią źródła lub mimo niej).
_13th_Dragon
Nie jesteś w stanie dokonać analizy na podstawie przedstawionych mi informacji, ponieważ aby tego dokonać trzeba te przedstawione informacje ROZUMIEĆ w przypadku niepoprawnego rozumienia (co w odniesieniu do ciebie oznacza zawsze) całą dalszą analizą o kant d..y potłuc.
IN
Twój sposób myślenia prowadzi donikąd, Twój sposób pisania prowadzi donikąd. I powtórzę - jesteś po prostu leniwy, idziesz na łatwiznę masz w dupie co się uruchomi i jak zadziała. Na dodatek nie reagujesz, kiedy człowiek obok Ciebie rozważa zalety i wady niewolnictwa. Takim jesteś człowiekiem, takim jesteś programistą. Może dlatego "ci co mnie tu znają od lat" Ci nie zwracają uwagi na pewne sprawy, bo co można takiemu człowiekowi powiedzieć?
_13th_Dragon
Widzisz wypowiedź "... że głównie zasyfia ekran ..." oznacza to że nie jesteś w stanie odróżnić bardzo przydatnych informacji od syfu, dla tego że nie rozumiesz pytania OT ani nawet tego co on próbuje zrobić. Ba nie jesteś w stanie nawet wywnioskować tego z działającego kodu, ponieważ nie rozumiesz większości tego co w tym kodzie użyłem. Ludzi co próbują wnioskować na temat czegoś o czym nie mają zielonego pojęcia nazywają ignorantami.
_13th_Dragon
"Na dodatek nie reagujesz, kiedy człowiek obok Ciebie rozważa zalety i wady niewolnictwa" - wiesz po krótkiej rozmowie z tobą każdy zaczyna widzieć w niewolnictwie same zalety :D
IN
Czyli milionowe wyświetlenie menu ma sens? I milion wyświetleń tego menu nie marnuje zasobów? Tak jak pisałem, wszędzie gdzie próbujesz coś pisać widać marnotrawstwo. I tutaj to tak, pozwoliłeś sobie na coś takiego ale wszędzie indziej już nie? Bzdura, na 100% piszesz wszędzie tak samo. I pewnie wszędzie produkujesz masę nikomu nieprzydatnego syfu zajmującego pamięć i marnującego czas.
_13th_Dragon
Dodaj do swego kodu dodatkową pozycję menu, gdzie będą dwie pętli. Jedna doda do twej listy 100tyś losowych kluczy, druga je usunie. Po czym wyświetli czas który na to pójdzie, ja zrobię to samo. Jak to zrobisz to będziesz miał namacalny dowód kto marnuje czas.
IN
Jak chesz możemy policzyć zużycie pamięci przez nasze programy i wszystko będzie jasne. Co Ty na to? xD Jak jesteś pewien, że masz tylko to co potrzebne to chyba luzik co? xD
_13th_Dragon
Ok, tylko że wyniki mają być porównywalne, marnowanie 1min wyceniasz na ile KB straconej pamięci?
IN
Jak na razie to tracimy po sekundzie na czekanie na wciśnięcie klawisza użytkownika, a Ty piszesz o pracy z 100 tysiącem działań. Jak wycenisz 100 000 x 1 sekundę ? xD (plus czas na wyszukanie wzrokiem wyniku działania) x 100 000. Bo to właśnie zaproponowałeś użytkownikowi. Jak wycenisz ten ludzki czas?
CP
@infinityhost: jak chcesz wczytać dane z stdin, a nie ma tych danych to kernel linuxa wykonuje polecenie wait_queue, jakby zwrócił 0 to by oznaczało eof, oddaje czas procesora innym procesom i jak dane pojawią się to jest wykonywanie budzenie procesu z kolejki. To jest normalna operacja czekania na reakcję użytkownika, nie ma w tym nic złego. Nie wiem czy to jest marnowanie czasu czy jego dobre wykorzystanie, jakby to był spin lock to co innego, wtedy czas by się marnował, bo czas reakcji człowieka jest znacznie niższy niż procesora.
_13th_Dragon
@infinityhost, Jaki przelicznik zaproponujesz (tylko że z sensem) taki przyjmiemy. Zmierzymy bardzo proste, trzeba mój program zmusić do wybory tej dodatkowej opcji 100 razy i zmierzyć łączny czas, oraz twój 100 razy ta dodatkowa opcja i zmierzyć łączny czas. Potem odejmujemy kare za ekstra kilobajty i voilà. Więc jaki będzie przelicznik?
IN
@CloudPro: nie wiem jak to jest z linuxem ale teraz chyba jeszcze rozmawiamy o obsłużeniu pojedyńczego wciśnięcia klawisza - a tak ogólnie to o sposobie niechlujnego, niebezpiecznego sposobu pisania przez smoczka xD Właściwie zarzutów wymieniłem kilka.
enedil
Czy ja dobrze rozumiem, że @infinityhost proponuje dodawać mniej funkcjonalności, bo dzięki temu prościej zapewnić bezpieczeństwo? XD
enedil
Czy ty kiedyś napisałeś coś ponad podstawy?
_13th_Dragon
@infinityhost, wymieniłeś jedynie wyssane z palca bzdury. Więc jaki będzie przelicznik? Dwa zarzuty na raz możemy zmierzyć obiektywnie.
IN
@_13th_Dragon: to już nie 100 000 razy? Przyjmijmy, że 1 - Twój program będzie przy każdym przebiegu pętli pauzował przez sekunde, 2 - Policzymy kilobajty. I wtedy policzymy który program się szybciej skończy.
IN
@enedil: raczej na odwrót xD
_13th_Dragon
@infinityhost, Owszem, przecież ty chciałeś dodać uwzględnienie marnowanie czasu użytkownika na dodatkowy klawisz, przecież trzeba jakoś to uwzględnić.
enedil
Edytowałem komentarz. Rozkojarzony jestem
IN
@_13th_Dragon: jakie bzdury, że ekrona podczas działania programu jest flood'owany zbędnym powtarzalnym syfem? I to są "bzdury wyssane z palca"? No przecież to widać gołym okiem.
IN
@_13th_Dragon: i co myślisz, że jak w swoim programi wstawisz sekundową pauzę, to dotrwamy do wyniku? A w rzeczywistości to się stanie, tylko będzie rozłożone na x osób. Powtarzam, działasz jak wirus i sabotażysta. Twoje pisanie prowadzi donikąd, Twoje myślenie prowadzi donikąd, Twoje nauczanie zaprowadziłoby donikąd.
_13th_Dragon
@infinityhost, gdyby nie były bzdurami lub nawet byli zaś ty o tym nie wiedziałeś, to na szybko dodałbyś do swego kodu dodanie 100tyś po czym ich usuwanie i miałbyś dowód - czyli to są bzdury i ty o tym dobrze wiesz.
IN
"byli bzdurami" , "by dodałeś" - przestajesz pisać po polsku. Dla kogo pracujesz? xD
_13th_Dragon
@enedil, on proponuje usunięcie tail z nagłówka listy na rzecz wyszukiwania końca w pętli oraz zastąpienie hashmapy listą jednokierunkową bo tak oszczędza sporo pamięci.
IN
@_13th_Dragon: "ostatniego elementu listy za pomocą pęli" - tak to jest po polsku.
enedil
@_13th_Dragon: no tak, i najbardziej zastanawia mnie argumentacja, że to rzekomo by umożliwić lepsze bezpieczeństwo kodu... smh
enedil
A no właśnie, lista jednokierunkowa to nie jest hashmapa.
_13th_Dragon
@enedil, ale oszczędza sporo bajtów.
IN
@enedil: możliwości jest ogrom, tylko trzeba korzystać z wyobraźni. Pętla to jest możliwość zadziałania na każdym elemencie listy. Kontrola poziom max. xD
enedil
Możnaby oszczędzić więcej stosując kompresję wskaźników
IN
Możliwości są miliony, schodzimy do bitów?
enedil
Dobra, przestań paplać od rzeczy, a przynajmniej zacznij przekazywać to co chcesz przekazać, bo teraz to ja widzę słowną sałatkę. Pętla to jest możliwość zadziałania na każdym elemencie listy. Kontrola poziom max WTF? Co tutaj w ogóle planowałeś powiedzieć? Że chcesz mieć kontrolę w pętli po liście??? W momencie gdy chcesz dostać się do ogona? Pzdr
IN
Jak na razie, moje rozwiązanie to jest rozmiar(int) array (4 bajty) i 12 bajtów przy każdym utworzeniu nowego elementu. I z tym @_13th_Dragon chcesz konkurować?
enedil
@_13th_Dragon: w sumie widać że troll, nie ma co dyskutować. Mi przez jego formatowanie nawet się nie chciało wczytywać (chyba skopiował skądś)
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)