• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Usuwanie poszczególnych elementów z tablicy dynamicznej

Object Storage Arubacloud
0 głosów
1,726 wizyt
pytanie zadane 6 grudnia 2018 w C i C++ przez Programmingc100 Bywalec (2,620 p.)
Zaalokowałem dynamicznie tablice dwuwymiarową za pomocą malloc i free.Czy jest taka możliwość żeby usunąć poszczególny element z tablicy np

1111122223

11112

i po usunięciu wyświetla :

111112222

1111
komentarz 6 grudnia 2018 przez RafalS VIP (122,820 p.)
Pokaż kod, którym usunąłeś elementy

1 odpowiedź

+1 głos
odpowiedź 6 grudnia 2018 przez RafalS VIP (122,820 p.)
wybrane 13 lipca 2020 przez Programmingc100
 
Najlepsza

Jeśli chcesz usuwać z końca to możesz po prostu wykorzystywać tylko część tablicy. Jeśli zależy Ci na fizycznym zmniejszeniu takiej tablicy lub usunięciu czegoś ze środka to musisz zaalokować nową mniejszą i przepisać do niej elementy, które mają zostać. Można to zrobić w ten sposób:

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

int main() {
    int n = 10;
    int* tab = malloc(sizeof(int) * n);
    for (size_t i = 0; i < n; i++)
    {
        tab[i] = i;
    }
    n /= 2;
    int *smaller_tab = malloc(sizeof(int)*n);
    memcpy(smaller_tab, tab, n *sizeof(int));
    free(tab);
    for (size_t i = 0; i < n; i++)
    {
        printf("%d ", smaller_tab[i]);
    }
}

 

2
komentarz 6 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Albo użyć realloc.

1
komentarz 6 grudnia 2018 przez RafalS VIP (122,820 p.)
Na śmierć zapomniałem o tej funkcji, bo nie ma odpowiednika w C++, a na codzien raczej w C++ siedze :P
komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
A na czym polega realloc ?
1
komentarz 6 grudnia 2018 przez RafalS VIP (122,820 p.)

W dwóch słowach - realokuje pamięć. Może to zrobić na  kilka sposobów: jesli sie da to rozszerzy / zmniejszy istniejący blok, jesli nie to zaalokuje nowy i przekopiuje dane:

char* small_array = malloc(5);
char* bigger_array = realloc(small_array,10);
komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Kawałek kodu który napisałeś kopiuje mniejszą tablice do większej?
komentarz 6 grudnia 2018 przez RafalS VIP (122,820 p.)
Bierze mniejszą tablice i próbuje zmienić jej rozmiar - w tym przypadku powiększyć - jesli sie da to rozszerzeniem obecnego bloku pamięci, jesli nie to zaalokowaniem nowego i przekopiowaniem zawartosci starej tabicy do nowej.
komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)

@RafalS, Nie wiesz może dlaczego ten kod nie działa. Pojawia się błąd invlalid conversion from void* to int*

komentarz 6 grudnia 2018 przez RafalS VIP (122,820 p.)

Bo kompilujesz to jako c++, a C++ jest bardziej restrykcyjny przy konwersjach niż C.

Skompiluj jako C lub dodaj jawne rzutowania:

	char* small_array = (char*) malloc(5);
	char* bigger_array = (char*) realloc(small_array, 100);

 

komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Chodziło mi ten dłuższy kod powyżej.
komentarz 6 grudnia 2018 przez RafalS VIP (122,820 p.)
Hmm, a nie jestes w stanie sie domyślic :P? malloc, realloc i calloc zwracaja void *, który chcemy przypisać do wskaźnika na jakiś konkretny typ. Co więc należy zrobić, żeby dało się tak przypisać wskaznik jedngo typu do wskaznika drugiego typu?
komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Rzutowanie z void na int?
1
komentarz 6 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Rzutowanie z void* na int*.

komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
tab=(int**)malloc(n*sizeof(int*)); ///alokacja pamieci dla wierszy
    for(int i=0; i<n; i++)
    {
    tab[i]=(int*)malloc(t[i]*sizeof(int)); ///alokacja pamieci dla kolumn
    }
    /// Przypisanie wartoœci
    cout<<endl;
    cout<<"WYPELNIJ KAZDA Z TABLIC: ";
    for(int i=0; i<n; i++)
 {
 tab[i]=(int*)malloc(t[i]*sizeof(int));
 for ( int j = 0; j < t[i]; ++j)
   {
       cout<<"Element nr "<<j<<" :";
       cin>>tab[i][j];
   }
 }

 A czy w ten sposób można zaalokwać tablicę nieregularną?

komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Ktoś może ma jakieś linki do materiałów z realloc iem i z tablicami dynamicznymi bo nic nie mogę znaleźć a nie rozumiem tego do końca.
1
komentarz 6 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Po co to malloc w linii 11? Przecież w linii 4 masz już alokację.

komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
W sensie cała linia 11 jest zbędna?
1
komentarz 6 grudnia 2018 przez j23 Mędrzec (194,920 p.)
Tak. W linii 4 przydzielasz już pamięć dla poszczególnych wierszy. Drugi raz nie trzeba tego robić ;)
komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
A tak ogólnie oprócz tego  przydział jest dobry?
komentarz 6 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Jak użyć realloc do mojej tablicy ?
1
komentarz 7 grudnia 2018 przez j23 Mędrzec (194,920 p.)

W kodzie z komentarza realloc nie ma zastosowania, chyba że chodzi Ci o coś innego. Rozwiń.

komentarz 7 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Chciałbym się dowiedzieć jak zmniejszyć tablicę dynamiczną
1
komentarz 7 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Wywołujesz realloc podając wskaźnik do tablicy, którą chcesz zmniejszyć, i rozmiar odpowiednio pomniejszony. Oczywiście jeśli będziesz zmniejszał tab,  musisz przedtem zwolnić wiersz, żeby nie mieć wycieku pamięci.

komentarz 7 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
realloc(*t[i],t[i]-1);
free(t[i])

Mniej więcej tak?

1
komentarz 7 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Dziwny ten kod...

 

Przykład usuwania ostatniego wiersza:

--n;
free(tab[n]);
tab = (int**)realloc(tab, n * sizeof(int*)); 

 

komentarz 7 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Do czego służy --n?
1
komentarz 7 grudnia 2018 przez j23 Mędrzec (194,920 p.)

W twoim kodzie n zawiera liczbę wierszy w tab, więc zmniejszam n o jeden, bo chcę zmniejszyć tablicę o jeden. Proste.

komentarz 7 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
A nie powinno się zmniejszać o jeden poszczególnej kolumny?
1
komentarz 7 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Pokazałem Ci przykładowe użycie funkcji realloc, gdzie usuwany jest ostatni wiersz. Jak chcesz zmniejszać ilość kolumn, to zrób to w podobny sposób.

komentarz 8 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
Jeśli chcę zmniejszać ilość kolumn dla określonego wiersza to ilość kolumn też musi być zaalokowana dynamicznie?
komentarz 8 grudnia 2018 przez Programmingc100 Bywalec (2,620 p.)
W sumie można by napisać funkcję która będzie zmniejszać wyrzucać jakiś element wraz z wywołaniem.
1
komentarz 8 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Nie rozumiem pytania. Przecież każdy wiersz to tablica intów stworzona na stercie. Oczywiście nie każde usunięcie elementu musi wiązać się z realokacją pamięci, możesz zmniejszyć zmienną określającą długość wiersza. Tak robi np. std::vector (vide capacity i size; z drugiej strony realloc działa na podobnej zasadzie).

1
komentarz 8 grudnia 2018 przez RafalS VIP (122,820 p.)

Dostaje powiadomienia z tego wątku od kilku dni, wiec stwierdziłem, że przypomne sobie C i napisze to na szybko:

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

int** create2d(size_t n, size_t m) {
	int **arr = malloc(sizeof(int*)*n);
	for (size_t i = 0; i < n; i++)
	{
		arr[i] = malloc(sizeof(int)*m);
	}
	return arr;
}

void free2d(int** arr, size_t n) {
	for (size_t i = 0; i < n; i++)
	{
		free(arr[i]);
	}
	free(arr);
}

int** print2d(int **arr, size_t n, size_t m) {
	for (size_t i = 0; i < n; i++)
	{
		for (size_t j = 0; j < m; j++)
		{
			printf("%4d ", arr[i][j]);
		}
		printf("\n");
	}
}

void fillRandomly(int **arr, size_t n, size_t m) {
	for (size_t i = 0; i < n; i++)
	{
		for (size_t j = 0; j < m; j++)
		{
			arr[i][j] = rand() % 100;
		}
	}
}

void removeRow(int ***arr, size_t* n, size_t rowNumber) {
	for (size_t i = rowNumber; i < *n - 1; i++)
	{
		(*arr)[i] = (*arr)[i + 1];
	}
	*n = *n - 1;
	*arr = realloc(*arr, sizeof(int*) * (*n));
}

void removeColumn(int **arr, size_t n, size_t* m, size_t columnNumber) {
	for (size_t i = 0; i < n; i++)
	{
		for (size_t j = columnNumber; j < *m - 1; j++)
		{
			arr[i][j] = arr[i][j + 1];
		}
		arr[i] = realloc(arr[i], sizeof(int) * (*m - 1));
	}
	*m = *m - 1;
}
int main(void)
{
	srand(time(NULL));
	int n = 5, m = 5;
	int** arr = create2d(n, m);
	fillRandomly(arr, n, m);
	print2d(arr, n, m);
	removeRow(&arr, &n, 1);
	printf("\n\n\n");
	print2d(arr, n, m);
	removeColumn(arr, n, &m, 1);
	printf("\n\n\n");
	print2d(arr, n, m);
	free2d(arr, n);
}

Działa w przykładowym happy scenario. Jeśli walnąłem się w jakimś corner case'ie to musisz sam poprawić. W każdym razie mam nadzieje, że widzisz jaka jest idea.

Podobne pytania

0 głosów
1 odpowiedź 370 wizyt
pytanie zadane 7 listopada 2018 w Java przez sebastian970 Użytkownik (710 p.)
+1 głos
1 odpowiedź 654 wizyt
pytanie zadane 4 grudnia 2016 w C i C++ przez niezalogowany

92,596 zapytań

141,445 odpowiedzi

319,719 komentarzy

61,980 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...