funkcija je dela (C++)
No, saj drugače dela, samo zadnji del, ko naj bi izpisala, da je sklad prazen, tega ne naredi, ampak kar zaključi 🙁
//izpis elementa na vrhu sklada
void vrni (int tabela[], int n)
{
int i = 0;
do
{
i = i+1;
}
while (i != n);
if (n >= 1)
{
cout
Ej ti mala štirinožna naprava, kaj pa če bi malce preprogramirala
zadevo, nekako takole (ps. nisem preizkusil, ker sem danes
malce len).
lp
//Misja posla
void vrni (int tabela[], int n)
{
int i = 0;
do
{
i = i+1;
}
while (i != n);
if (n = 0)
{
cout
Ehm, “if (n = 0)” se ne bo ravno obneslo 🙂
Pa tudi sicer, “do” se vsaj enkrat izvede, torej je i vsaj 1 in ni nikoli nič, da bi se izpisalo, da je sklad prazen. Pravzaprav se bo v primeru, ko je n enako 0, vse skupaj zaciklalo (skoraj, ko bo int prišel naokrog, se v resnici bo ustavilo) – programerski nasvet: če je le možno, vedno uporabljaj pogoje tipa < namesto !=, se veliko varneje zaključijo, kadar začneš s kakšno neumnostjo. V zdajšnjih časih, ko lahko pobiješ en proces sicer to ni tak problem, v Dosu si pa v takem primeru lepo iskal gum za reset :-)
Mogoče bo bolj uporaben kakšen stavek “for”?
Jah, lahko vam repato bitje kompletno nalogo (z navodilom vred) tule napiše, pa počaka na pemtne predloge, ker repato bitje nima več nobene pametne ideje, kaj naredit s tem vražjim programom.
No, če je komu dolgčas, eto vam:
Izdelajte statično predstavitev podatkovne strukture sklad. Izdelajte program, ki bo omogočal uporabo osnovnih funkcij (operacij) nad enim od osnovnih podatkovnih tipov. Dodajte tudi podprogram za izpis podatkovne strukture.
#include
//dodajanje elementa na vrh sklada
void dodaj (int tabela[], int& n)
{
n = n++;
cout > tabela[n];
cout = 1)
{
cout = 1)
{
n = n–;
cout > izbira;
switch (izbira)
{
case ‘1’:
{
dodaj (sklad,a);
break;
}
case ‘2’:
{
izpis (sklad,a);
break;
}
case ‘3’:
{
vrni (sklad,a);
break;
}
case ‘4’:
{
brisi (a);
break;
}
case ‘0’:
{
cout
No repatec tukolala, tisto kar dela pač dela, tiste 2 stvari ki ne delajo pa popravi takolele :
//izpis celotnega sklada – TU NE DELA ‘SKLAD JE PRAZEN’
void izpis (int tabela[], int n)
{
int i = 0;
do
{
i = i++;
}
while (i == n);
if (i >= 1)
{
cout 0. Funkcija zgleda nekako takole :
//izpis celotnega sklada – TU ZDAJ DELA ‘SKLAD JE PRAZEN’
void izpis (int tabela[], int n)
{
int i = 0;
if (n >= 1)
{
cout
Ja, ampak zdaj mi v vsakem primeru (tudi ko sklad ni prazen) napiše, da je prazen. Za element na vrhu sklada pa mi, če je sklad poln, napiše neko število v stilu -858993460 (element na vrhu sklada je v resnici 5!)
Veš kaj, saj ni panike. Bom po praznikih asistenta vprašala. Pa naj si on beli glavo 🙂
Hvala vseeno 🙂
Težava je bila tole: “if (n = 0)”, mora biti == pri primerjanju.
“i = i++;” sicer naredi to, kar hočeš, ampak v resnici naredi popolnoma isto že samo “i++;”.
Operator ++ lahko uporabiš tudi znotraj izraza, poglej spodaj v funkciji dodaj.
Dobro napisan program bi sicer moral preveriti še, če je na skladu še kaj prostora, preden dodaja.
Preizkusi tale sir:
#include
//dodajanje elementa na vrh sklada
void dodaj (int tabela[], int& n)
{
cout > tabela[n++];
cout > izbira;
switch (izbira)
{
case ‘1’:
{
dodaj (sklad,a);
break;
}
case ‘2’:
{
izpis (sklad,a);
break;
}
case ‘3’:
{
vrni (sklad,a);
break;
}
case ‘4’:
{
brisi (a);
break;
}
case ‘0’:
{
cout
Zanimivo vprašanje 🙂 Po moje je vseeno v redu v obeh primerih:
n = n++;
n se priredi vrednost n, potem se pa n poveča za 1
n = ++n;
n se poveča za 1, potem se pa n priredi vrednost n (ki je že povečana za 1)
Vsekakor pa nikoli ne smeš napisati česa takega:
x = tabela[n++] + tabela[n++] * 256;
Tukaj je pa rezultat nedefiniran (se lahko spremeni tudi med debug in release verzijo) in ne moreš nikoli vedeti, katero pozicijo v tabeli bo pomnožil z 256 (ker izračunavanje aritmetičnih izrazov v C ni definirano in gre lahko od leve ali od desne).
Lahko pa uporabiš:
if (tabela[n++] && tabela[n++])
pri logičnih izrazih pa je predpisano, da se izvajajo od leve proti desni. Se je pa pametno takim trikom izogibati, da je program bolj razumljiv.
Ja po moje je tud blo vseeno ali uporabljaš prefix ali postfix operator :))
Ampak zanimivo, recimo M$ C++ .NET (kao VC 7) ali pa Bloodshed Dev-C++ sta naredila enako, se pravi jima je vseeno. Digital Mars C/C++ pa n v primeru n = n++; ni povečal, pri prefixu pa ga je. In mišji compiler zgleda tudi, zato je vedno metal ven da je sklad prazen( kar je v bistvu hotela že od samega začetka:)) )
Cela finta okrog tega pa je verjetno dejstvo, da postfix operator vrne vrednost pred spremembo zato se v primeru n = n++; n najprej poveča za 1, nato pa nju priredi vrednost nja pred spremembo(najprej se izvede n++, nato prirejanje vrednosti, ki je v tem primeru pred spremembo)
Zvedavec, super si! Hvala tudi tebi, hmmm, za požrtvovalnost 🙂
Vaju (in klemenaxx) povabim enkrat na sirove štrukle 😉
Če ima kdo kaj preveč prostega časa (ker zdaj, med prazniki, itak ni drugega dela), lahko malo še tegale pogleda. Jaz ne najdem napake, ima pa probleme pri točki tri (izpis zadnjega elementa v skladu).
navodilo (zelo podobno prejšnjemu, samo dinamično namesto statično):
Izdelajte dinamično predstavitev podatkovne strukture sklad. Izdelajte program, ki bo omogočal uporabo osnovnih funkcij (operacij) nad enim od osnovnih podatkovnih tipov. Dodajte tudi podprogram za izpis podatkovne strukture.
moj krumpl od programa:
#include
//definicija kazalca
struct kaz //kaz je kazalec
{
int vred;
kaz *nasl;
};
//kazalci so označeni s črko k in podčrtajem (k_), čemur sledi preostali del kvantifikatorja
//dodajanje elementa na vrh sklada
void dodaj (kaz*& k_a, int n)
{
kaz* k_skl;
k_skl = new kaz;
k_skl -> vred = n;
k_skl -> nasl = k_a;
k_a = k_skl;
}
//izpis celotnega sklada
void izpis (kaz* k_a)
{
if (k_a -> nasl == NULL)
{
cout vred nasl); //rekurzivni klic funkcije izpis
cout vred vred nasl;
}
cout > izbira;
switch (izbira)
{
case ‘1’:
{
cout > n;
dodaj (sklad,n);
cout
>Ampak zanimivo, recimo M$ C++ .NET (kao VC 7) ali pa Bloodshed Dev-C++ sta naredila enako, se pravi jima je vseeno. Digital Mars C/C++ pa n v primeru n = n++; ni povečal, pri prefixu pa ga je. In mišji compiler zgleda
Sumljivo tole, je pa pri teh mejnih stvareh kdaj res vprašanje, kaj je predpisano in kaj ne.
Sem imel nekoč kup težav, ko mi je neki prastari prevajalnik interpretiral vrstico “a=*b;” namesto “a = *b;” v “a *= b;” – originalni KR operator je namreč bil =* in so to šele kasneje popravili v *=, ravno zaradi dvoumnosti najbrž. Podoben problem je bil pri “i=-1;”. Od takrat striktno pišem presledke pri operatorjih.
Eto, sem že tu z novim izzivom za vaju… 😮
Spomnite se na algoritem za izračun hitre potence s prejšnjih predavanj. Napišite še dve različici tega algoritma: rekurziven podprogram in podprogram v katerem so rekurzivni klici nadomeščeni s posegi na sklad.
#include
struct kazalec //definiramo nov podatkovni tip
{
float vrednost;
kazalec *nasl;
};
float Brisi_iz_sklada(kazalec*& p) //brisanje iz sklada
{
float brisi_iz_sklada=p->vrednost;
p=p->nasl;
return brisi_iz_sklada;
}
void Vstavi_na_sklad(kazalec*& p, float m) //vstavljanje podatkov na sklad
{
kazalec* q;
q=new kazalec;
q->vrednost=m;
q->nasl=p;
p=q;
}
float Rekurzivno(float osnova, int eksponent)
{
float rekurzivno=0;
if (eksponent>a;
cout>n;
cout
hehe, izzivi…yeeesss :))
Oki, ne bom se zdaj spuščal v praznično razmišljanje pri programiranju, sama imaš verjetno ideje v glavi in tudi najbolje bo, da jih sama udejaniš.
Če pa so v programu kakšne mahjne logične neumnosti, ti bomo pa že povedal 🙂
No tkole, tukaj je takoj ena za začetek in odgovor zakaj je nekaj na karkoli pri tebi vedno 0:
float S_skladom(float osnova, int eksponent)
.
float b=0;
.
.
b=b*Brisi_iz_sklada(sklad);
b=0 nato b množiš z vrednostmi –> 0*nekaj je pa vedno 0
Verjetno si imela v glavi
float b=1;
Druga stvar v isti funkciji, če je lihi ekponent imaš zanko
do
.
.
while (eksponent==0);
Ta zanka se bo pri danih pogojih izvršila najbrž le 1x, ker če je eksponent 0, potem si že itak postavila, da je vrednost funkcije 1, če ni nič, pa se bo zanka izvršila le enkrat. Verjetno si imela v glavi naj se zanka izvršuje dokler je različno od 0.
Tretja stvar ki pa manjka, pa je del, ko je eksponent sod, v tem primeru ne narediš nič. No sicer tudi za lihi del dela pravilno le za exp 1 in 3, ampak boš že uštimala kajneda 🙂
> Sumljivo tole, je pa pri teh mejnih stvareh kdaj res vprašanje,
> kaj je predpisano in kaj ne.
Pa seveda, koliko striktno se teh predpisov držijo tudi sami prevajalniki.
M$ recimo bi rad razvijanje aplikacij precej poenostavil in olajšal delo razvijalcem, zato določene stvari poenostavijo in jih njihovi prevajalniki z lahkoto prebavijo, kakšen drugi pa bi precej kašljal pri isti kodi.
Podobno je bilo zadnjič s tadejevo random funkcijo, .NETov compiler enostavno sam inicializira generator, njegov ga očitno ni. Tako da vsaj pri razvojnih orodjih se jaz držim Microsofta, konec koncev je njihov oddelek za razvojna orodja daleč najbolj kvaliteten med vsemi, buga v tem programju skoraj ne najdeš, kar drugače tudi ni ravno njihova odlika, programer pa se skoraj počuti kot car, kar za druge njihove uporabnike spet ne bi mogli rečt :))
Še zmerej mi pa ni jasno, zakaj miš na faxu, ki nima blage veze z računalništvom mučijo z c++ 🙂
Miš študira računalništvo in biologijo, dvopredmetno na pedagoški, drugi letnik.
Tudi meni ni jasno, zakaj naj bi bodoči prfoksi (čeprav računalništva) znali programirat, ampak prfoks ne upošteva tega, on hoče programe 🙁
Forum je zaprt za komentiranje.