PDA

Prikaži potpunu verziju : Dinamičko menjanje dužine niza


Bolton
4.5.2011, 17:34
Imam sledeći zadatak: U niz x[20] unose se slucajni brojevi od 1-30. U niz y upisati samo neparne brojeve. Ispisati niz y.
int[] x = new int[20];
int[] y;
int brojac = 0;
Random nasumicanBroj = new Random();
for (int i = 0; i < x.Length; i++)
{
x[i] = nasumicanBroj.Next(0, 30) + 1;
if(x[i] % 2 != 0)
{
brojac++;
y = new int[brojac]; // duzina niza ce se povecavati svaki put kada se pojavi neparan broj
y[brojac-1] = x[i];
}
}
foreach(int broj in y)
{
Console.WriteLine("Niz y: {0}",broj);
}

Svaki put kada se poveća dužina niza njegovi članovi se resetuju na 0. Kako je moguće dinamički menjati dužinu niza a da se ne brišu njegovi članovi? Da li postoji neki drugi (jednostavan) način kako se ovaj zadatak može rešiti?

Sass Drake
4.5.2011, 17:46
Ako sam te dobro shvatio hoćeš da promijeniš dužinu niza da bude <>20. Ne znam da li je to C# ili Java, ali mogu ti reći da je to u C/C++ nemoguće uraditi „jednostavnom naredbom”. Ovako bi išao C++ pseudokod za mijenjanje dužine niza (napravi kopiju, izbriši original, kopiraj kopiju u novi, izbriši kopiju):


x = new int[n] ;
.
.
.
temp = new int[n] ;
for ( i=0 ; i < n ; i++)
temp[i] = x[i] ;
delete [] x ;
x = new int[m] ;
for ( i=0 ; i < n ; i++)
x[i] = temp[i] ;
delete [] temp ;
Ako negdje ima greška, recite. :kreza:

EDIT:
Savjet, da ne bi pri svakom unošenju jednog člana niza radio veliko kopiranje, neka ti nova dužina niza bude za 5-10 duža. Naravno, ne zaboravi ubaciti i brojač koji govori koliko je niz popunjen.

Bolton
4.5.2011, 17:56
Potrebno je da u drugi niz stavim samo neparne brojeve. Unapred ne mogu znati koliko će neparnih brojeva biti generisano, a na osnovu promenljive "brojac" mogu da menjam dužinu tog niza u zavisnosti od toga koliko se neparnih brojeva pojavljuje, jedino je problem što kada se dužina niza promeni gubim prethodne neparne brojeve koje sam smeštao u taj niz. Inače, ovo je C#. :)

MG-RAY
4.5.2011, 18:04
Imaš Array.Resize (http://msdn.microsoft.com/en-us/library/bb348051.aspx) ako već insistiraš na tom pristupu.

Lakše ti je (i u ovom slučaju verovatno brže) da koristiš List<T> i samo dodaješ elemente...

Array.Resize je za .net 3.5 i 4.0.

Za starije frameworke, uradi kako ti je Sass Drake rekao... :)

Ili jednostavno napravi drugi niz da bude iste dužine kao i prvi i ograniči ispis, pretpostavljam da je i to opcija...

Bolton
4.5.2011, 18:19
Probao sam Array.Resize i radi isto što sam i već probao sa y = new int[brojac], međutim problem je što se opet svi članovi niza resetuju na 0 svaki put kad se dužina niza promeni. Ne bih koristio nikakve "naprednije" metode jer profesor/asistent traži da radimo zadatke na osnovu njegovih tutorijala, bez obzira na to što ovakav zadatak nije pokazivao.

MG-RAY
4.5.2011, 18:55
Nemoguće je da ne radi:

int[] x = new int[20];
int[] y = new int[0];
int brojac = 0;
Random nasumicanBroj = new Random();
for (int i = 0; i < x.Length; i++)
{
x[i] = nasumicanBroj.Next(0, 30) + 1;
if (x[i] % 2 != 0)
{
brojac++;
Array.Resize(ref y, brojac);
y[brojac - 1] = x[i];
}
}
foreach (int broj in y)
{
Console.WriteLine("Niz y: {0}", broj);
}

Todors
4.5.2011, 19:00
Dužina niza ne može da se dinamički menja. Zbog toga je i uvedene klasa ArrayList koja je u stvari dinamički niz. Tako da ćeš morati ili da se odlučiš za ovu klasu ili da kreiraš još jedan niz gde ćeš svaki put da čuvaš prethodno stanje i da updejtuješ novo, ali to rešenje baš i nije praktično.

Bolton
4.5.2011, 19:12
E sad radi! :D Našao sam grešku: nisam odredio dužinu niza (iako će ona biti 0), pre nego što sam koristio Array.Resize metod, već sam stavio da je ona y = new int[brojac]. Hvala svima na odgovorima. :ciao:

irreal
4.5.2011, 19:12
ja sam jednom prilikom koristio Array.Resize u .net 2.0 projektu, tako da ne razumem zasto kazes samo za 3.5 i 4.0


i ne, array.resize ne resetuje sve na 0, ako tebi, Bolton, array.resize resetuje na 0, znaci da si negde drugde ostavio ono "= new"

@Todors, ja nisam sto posto siguran sta array.resize radi u pozadini, nije me previse zanimalo, ali ono sto je bitno je rezultat pozivanja te funkcije, a to je array drugih dimenzija koje su promenjene dinamicki.

e sad, dal on kreira novi pa prekopira stare vrednosti automatski ili ne, ne znam.


inace, ako bas hoce da koristi obican array, ok, samo napred, al naravno da treba forsirati List<T> kad god je moguce.

MG-RAY
4.5.2011, 19:23
Označeno je da je dodat naknadno u .net 2.0, pa nisam ni primetio, ali da, u pravu si, postoji i tamo.

Inace, Array.Resize pravi novi niz, prekopira vrednosti i promeni referencu...

@Bolton Zaobiđi ovaj metod ako nije neophodno da ga koristiš, kada bi pokušavao da resizeuješ niz dužine nekoliko miliona, načekao bi se...

Todors
4.5.2011, 19:48
inace, ako bas hoce da koristi obican array, ok, samo napred, al naravno da treba forsirati List<T> kad god je moguce.
Potpuno se slažem! :)

Bolton
4.5.2011, 19:54
@irreal
Da, to je i bio problem (odgovorismo u isto vreme, pa nisi stigao da pročitaš :))
@MG-RAY
Ovako sam morao da odradim samo zato što tako profesor traži, a i to radim za drugara kome je i ovo previše :D
@Todors
I ja se slažem! :ciao:

chaami
4.5.2011, 20:26
@Sass Drake
U C++-u je sasvim normalno korišćenje dinamičkih nizova i iskren da budem ja uglavnom i koristim te dinamičke koji se zovu vector:D.

enaB
4.5.2011, 21:10
Ne znam da li je to C# ili Java, ali mogu ti reći da je to u C/C++ nemoguće uraditi „jednostavnom naredbom”.
Moguće je, postoji funkcija realloc();

Sass Drake
5.5.2011, 9:28
@Sass Drake
U C++-u je sasvim normalno korišćenje dinamičkih nizova i iskren da budem ja uglavnom i koristim te dinamičke koji se zovu vector:D.

Gdje sam ja napisao da nije normalno? :icon_scra

Moguće je, postoji funkcija realloc();

U C-u da, ali za C++ nije baš najsrećnije rješenje. (iako će u većini slučajeva raditi sa nizovima osnovnih tipova, dok za nizove objekata baš i nisam siguran da će raditi).

EDIT: Sad sam baš provjerio sa objektima koji imaju statičke podatke članove. realloc će kopirati stare članove niza, ali tokom proširivanja, konstruktori novih neće biti izvršeni, pa ako objekat ima poneki dinamički podatak član biće šta će biti. Ako se skraćuje, onda destruktori neće biti izvršeni. :kreza:

chaami
5.5.2011, 11:20
Gdje sam ja napisao da nije normalno? :icon_scra

Ja nisam ni rekao da si TI napisao da nije normalno. Samo sam pokušao da objasnim onima koji ovo čitaju da se mogu koristiti vektori, posto vidim da si naveo kako je to u C++ nemoguće uraditi "jednostavnim komandama". Ipak ovaj forum čitaju i ljudi koji su slabije upućeni u programiranje, pa mislim da ne bi bilo dobro da steknu pogrešno mišljenje o nekim sasvim NORMALNIM i jednostavnim komandama.

Sass Drake
5.5.2011, 11:45
Ja nisam ni rekao da si TI napisao da nije normalno. Samo sam pokušao da objasnim onima koji ovo čitaju da se mogu koristiti vektori, posto vidim da si naveo kako je to u C++ nemoguće uraditi "jednostavnim komandama". Ipak ovaj forum čitaju i ljudi koji su slabije upućeni u programiranje, pa mislim da ne bi bilo dobro da steknu pogrešno mišljenje o nekim sasvim NORMALNIM i jednostavnim komandama.

Pod „jednostavnim komandama” sam konkretno mislio na standardni tip niza bez upotrebe magičnih klasa. Trebalo je da to naglasim.
Kad se samo sjetim koliko sam relativno kratko ostajao na labovima zahvaljujući toj magičnoj klasi. :to_care:

Belphegor
5.5.2011, 15:29
Mislim da ponasanje realloc-a zavisi od fragmentacije heap-a, koliko sam razumeo trebalo bi da radi inplace dodelu produzavanje (ili skracivanje) memorijskog bloka ako ima mesta za taj niz u protivnom postavlja ceo novi blok na drugo mesto. Ispravite ako gresim.

offtopic
Blago vama vi ste to imali u skoli, mojom krivicom ja to nisam jer sam se zaj**vao u to vreme (idiot).:D Pa sad kad sam omatorio (relativno:o) odlucio sam se da mi C++ bude hobi pa mi ucenje ide sporije nego vama,
ali ipak mi se svidja ukus zadovoljstva svaki put kad naucim nesto novo i funkcionalno pored muke citanja tudjeg koda i knjiga na engleskom jeziku. S'obzirom da imam veoma lose drustvo ja sam dobro prosao i C++ mi dodje kao dobra terapija.

Sass Drake
5.5.2011, 16:02
^ Mislim da je baš problem u tome, što radi samo to, dok konstruktori i destruktori ostaju neizvršeni što je u C++ ne čini pogodnom.

offtopic:
Ja sam to učio na faksu. :D

Mr.Deeds
29.10.2011, 13:50
Ja sam takve zadatke imao u srednjoj skoli :)
A ovo vase je, zasto jednostavno kad moze komplikovano :D
#include<stdio.h>
main()
{
int x[20],y[20],i,j=0,n;
printf("Unesite n");//n-proizvoljan broj od 1 do 20
scanf("%d",&n);
printf("Unesite brojeve od 1-30");
for(i=0;i<n;i++)
scanf("%d",&x[i]);
for(i=0;i<n;i++)
if(x[i]%2==1)
{
y[j]=x[i];
j++;
}
for(i=0;i<j;i++)
printf("%d",y[i]);
}

Zar nije lakse bilo ovako uraditi? :)

chaami
29.10.2011, 17:53
@Mr.Deeds lakše možda i jeste ali je zato veoma pogrešno. Da ne ulazimo u to da su traženi random brojevi a ne korisnički unos, poenta priče je upravo na korišćenju dinamičkih nizova. U tvom primeru ti ograničavaš korisnika na niz od 20 elemenata, ali šta ako ja želim da unesem mnogo veći niz. Kako ćeš onda da rešiš taj problem. Da li ćeš možda da pokušaš da predvidiš koliki bi mogao biti maksimalni unos. Možda recimo milion elemenata. U takvoj situaciji tvoj kod postaje strahovitio komplikovan ako ne i nemoguć. Dinamički nizovi to vrlo jednostavno rešavaju i oslobađaju nas svih komplikacija.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
int d;
cout << "unesi broj elemenata ";
cin >> d; // od jedan do ???????? (koliko ima slobodne memorije)
vector<int>x;
vector<int>y;
srand(time(0));
for (int i=0;i<d;++i)
{
x.push_back((rand()%30)+1);
if (x.back()%2)y.push_back(x.back());
}
for (unsigned int i=0;i<y.size();++i)
cout << y.at(i) << " ";
return 0;
}Naravno, i ovde treba ubaciti proveru dostupne memorije ali sam samo hteo da ti dam primer rešavanja problema sa dinamičkim nizovima koje je zapravo jako jednostavno i funkcionalno za razliku od rešenja sa standardnim fiksnim nizovima.

Mr.Deeds
30.10.2011, 10:36
Ja sam samo dao primer za ono sto je on postavio kao zadatak, jer ako je niz x[20] trazen, onda sigurno nece biti uneseno vise elemenata. Bezveze komplikovati zadatak sa dinamickim nizovima kad je trazena konkretna stvar... ;)

Bolton
30.10.2011, 15:14
Onda nisi dobro pročitao zadatak. Ti si unapred odredio dužinu y niza iako broj njegovih elemenata još uvek nije poznat. x niz je dužine 20, a da sam na taj način hteo da rešim zadatak onda ne bi ni postavljao temu, jer sam lako mogao da stavim da dužina y niza bude jednaka dužini x niza. Kolika je verovatnoća da će svih 30 brojeva biti neparni? Znaš i sam, zato bi svi preostali elementi bili popunjeni nulama, a to nije najbolje rešenje. chaami je u pravu. ;) Pored toga, u pitanju je bio zadatak iz C#, a ne iz C-a. :ciao: