Novo

Forum kao aplikacija na telefonu

Dodajte forum na početni ekran i koristite ga kao aplikaciju, sa menijem na dnu ekrana.

  • 61 odgovor
  • 15.505 pregleda

Najnovija ↓

Ponavljanje main funkcije 23.10.2012. u 18:27 · pre 170 meseci #1
Kako u programu staviti da se po obavljenom zadatku ponavlja main funkcija ?

Code:
#include <stdio.h>

// Napisati program koji odredjuje da li je uneti broj paran ili neparan.

main()
{
      int x;
      printf("Unesi broj :\n");
      scanf("%i",&x);
      if(x%2==0)
      printf("PARAN");
      else
      printf("NEPARAN");
      scanf("%i");
}


Znači ... Primer : Ukucam broj 23, program ispiše da je taj broj NEPARAN. I kako odmah posle toga opet pokrene tu main funkciju, tj. da opet ispiše da se unese broj i da ponovo ako ukucam primer 24, ispise da je PARAN ?

Mislim da sam bio jasan. :D
Re: Ponavljanje main funkcije 23.10.2012. u 18:29 · pre 170 meseci
izmenjeno 1 put, poslednji put maksvel 23.10.2012. u 18:43
  1. maksvel23.10.2012. u 18:43zapis iz teksta poruke
#2
Ne treba ti još jedan main, stavi petlju, na primer while i neka vrti, dok se ne unese broj "za izlaz iz petlje", na primer nula.
Npr:
Code (c):


main()
{
      int x;
while(1)
{    
      printf("Unesi broj (za izlaz unesi 0) :\n");
      scanf("%i",&x);
     if(x==0)
          break;
      if(x%2==0)
      printf("PARAN\n");
      else
      printf("NEPARAN\n");

}
     
}
 

Petlja radi non-stop (while (1)), dok se ne unese nula, kada prestaje.
Re: Ponavljanje main funkcije 24.10.2012. u 00:59 · pre 170 meseci #3
A možeš i bez petlje
Code:

#include <stdio.h>

int main()
{
    int x;
    {
        printf("Unesi broj (za izlaz unesi 0) :\n");
        scanf("%i",&x);
        if(x%2==0) printf("PARAN\n");
        else printf("NEPARAN\n");
    }
    return x==0 ? x:main();
}

čisto da se malo bolje upoznaš sa C jezikom.
Re: Ponavljanje main funkcije 24.10.2012. u 11:07 · pre 170 meseci #4
Treba imati u vidu da rekurzivno pozivanje funkcije mora da ima neki kraj, to jest ne može funkcija da se u nedogled poziva rekurzivno. Postoji fizičko ograničenje pozivnog steka, i kad program nesputanim rekurzivnim pozivima dođe do kraja steka onda program "puca". Ovde upravo imamo takav slučaj, kada bi neki korisnik bio dovoljno zaludan da koristi program dovoljno dugo, nikad ne unevši nulu.
Re: Ponavljanje main funkcije 24.10.2012. u 14:57 · pre 170 meseci #6
@Mihajlo neće se stek nikad popuniti jer ga return prazni od predhodne funcije tako da možeš do penzije da unosiš brojeve (uključi debug i videćeš da je uvek samo jedna funkcija na steku).

@Goran upravo zato i jeste "lepo" jer rekurziju koristimo bukvalno kao goto ;)
Sviđa mi se2
Re: Ponavljanje main funkcije 24.10.2012. u 15:14 · pre 170 meseci #7
Stek će se u jednom trenutku napuniti. Stek se ne prazni kad se pozove return, nego kad se taj return izvrši, a u ovom slučaju da bi se izvršio potrebno je da se prvo ponovo pozove main, u krug. Možeš da probaš, napravi tekstualni fajl sa par miliona jedinica, po jedna u redu, i izvrši ovaj program preusmeravajući standardni ulaz da ide preko tog fajla, proba.exe < mnogo_jedinica.txt, i vidi šta će se desiti.

Ili, uključi debug i videćeš da je mnogo funkcija na steku.
Re: Ponavljanje main funkcije 24.10.2012. u 16:02 · pre 170 meseci
izmenjeno 2 puta, poslednji put chaami 24.10.2012. u 16:29
  1. chaami24.10.2012. u 16:29zapis iz teksta poruke
  2. chaami24.10.2012. u 16:29zapis iz teksta poruke
#8
Mihajlo, ne mogu da tvrdim za MS kompajler (voleo bi da neko proveri jer me od njih ništa ne bi čudilo) ali što se GCC tiče stek se definitivno prazni. Onog trenutka kad kompajler kao povratni rezultat neke funkcije ima drugu funkciju automatski prestaje potreba za pozivnom funkcijom i ona se briše. Ne pričam ti ništa napamet. Sve sam proverio sa debugerom, kao što sam ti i rekao u prethodnom postu. Uostalom, povedi se zdravom logikom, što bi kompajler čuvao funkciju za kojom je prestala potreba.

EDIT: evo ga jednostavan primer. Imamo 1000 milijardi pozivanja funkcije main i u svakoj pravimo lokalnu promenljivu c.
Code:

#include <stdio.h>
int x,y;
int main()
{
    int c;
    ++y;
    c=y;
    if (c>1000000){y=0;++x;printf("%d\n", x);}
    return x==1000000 ? x:main();
}
Re: Ponavljanje main funkcije 24.10.2012. u 16:33 · pre 170 meseci #9
A dobro, to je ono što zovu tail call optimization. Na to sam zaboravio. U ovom slučaju je moguće napraviti kod tako da se ne troši stek, ali to nije moguće u svakoj rekurziji.
Re: Ponavljanje main funkcije 26.10.2012. u 12:23 · pre 170 meseci #10
chaami, nisi u pravu. Stek se itekako puni i puca, a program ti nije dobar. Na početku izvršavanja x i y sadrže đubre (često nulu, ali ne uvek), tako da ti program ima nedefinisano ponašanje. Osim toga, ne znam da li si ga probao, ali kod mene puca (Ubuntu 11.04, gcc/g++ 4.6.3). Stavio sam da se x i y inicijalizuju na nulu.

Probao sam ovaj program:
Code (cpp):

int counter = 1000000;

int main() {
    return --counter == 0 ? 0 : main();
}

Rezultat je

Segmentation fault (core dumped)


Isti rezultat daje ovaj program:
Code (cpp):

int main() {
    return main();
}
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Ponavljanje main funkcije 26.10.2012. u 15:02 · pre 170 meseci #12
U pravu si. Izgleda da sa njom radi.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Ponavljanje main funkcije 26.10.2012. u 22:18 · pre 170 meseci
izmenjeno 1 put, poslednji put chaami 26.10.2012. u 22:32
  1. chaami26.10.2012. u 22:32zapis iz teksta poruke
#13
Definitivno je potrebna ili O2 ili O3 optimizacija ... eto, a ja sam bio ubeđen da se to podrazumeva. U svakom slučaju, sa O2 optimizacijom svaka funcija može da poziva samu sebe bez opasnosti da će zatrpati stek.
Što se neinicijalizovanih globalnih i statičkih promenljivih tiče, one se isto kao i globalni pointeri smeštaju u .bss segment. Loader programa, odnosno sam OS bi morao da popuni bss segment sa nulama. ISO C standard takođe kaže da će sve neinicijalizovane globalne i statičke promenljive biti postavljene na 0.
Re: Ponavljanje main funkcije 28.10.2012. u 00:43 · pre 170 meseci #14
E vidiš, ovo sad nije tačno, da s optimizacijom svaka funkcija može da poziva samu sebe bez opasnosti po stek. Samo funkcije koje imaju "tail call", ili mogu da se preslože tako da imaju tail call, mogu da se organizuju tako da ne troše stek. Ako posle rekurzivnog poziva funkcije postoji još nešto bitno da se radi u funkciji, onda kompajler ne može da ukloni stek, jer mu stek treba da bi uradio to drugo što je bitno. Pišem napamet, i mrzi me da testiram, ali ko je znatiželjan nek proveri da li sledeći kod puca:

Code:
int proba(int x)
{
  int result = x == 0 ? 0 : proba(x);
  return result + (result ? 1 : -1);
}


Malo sam ga zakomplikovao da prevarim eventualni analizator koda. Pozvati funkciju s bilo kojim parametrom osim nule.
Re: Ponavljanje main funkcije 28.10.2012. u 07:47 · pre 170 meseci #15
Da ... moja greška. Napisao sam "svaka funkcija može da poziva sebe" umesto "svaka funkcija na izlazu može da poziva sebe". Ukoliko stavimo return funkcija() imaćemo beskonačnu petlju.
Re: Ponavljanje main funkcije 28.10.2012. u 12:01 · pre 170 meseci #16
Iskreno, nikad u životu mi nije palo na pamet da pozovem main() iz main()-a :)


Off:
Sećam se mojih prvih programa, na interpreterskom BASIC-u, na jednom domaćem računaru. Često sam imao izraze tipa (radilo se o nekoj bazi podataka):
Code:

...
100 FOR I=1 TO N
110 IF A$(I)=N$ THEN GOTO 500
120 NEXT I
130 REM nastavak, kada se potroši i poslednji "I" (sa brisanjem adrese linije 110, gde je trebalo kod da se vrati), ali se to uglavnom nikada nije dešavalo, jer je izlazak uvek bio ranije
140 GOTO 10

500 REM Neka obrada sa poznatim indeksom I
...


Šta se dešavalo?
Posle izvesnog vremena VIDEO MEMORIJA (izgled ekrana), koja je bila realizovana samo kao kontinualnih 8KB celokupne linearne memorije, je počela da pri vrhu ima neke čudne tačkice. E te tačkice su bile neočišćeni parovi bajtova x broj dolazaka na linije tipa koda koji sam naveo. Ukratko STEK se prelivao na deo koji je pripadao VIDEO MEMORIJI.

Re: Ponavljanje main funkcije 28.10.2012. u 14:00 · pre 170 meseci #18
@X Files

Jesi li imao krme (C64) ili najbolji računar u istoriji, savršenstvo bez mane (ZX Spectrum, 48K)? Mojne samo da mi kažeš da si koristio amSMRAD.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Ponavljanje main funkcije 28.10.2012. u 15:07 · pre 170 meseci #19
Heh :) Koristio sam sve koje si naveo, i još neke starije i novije, a ovo o čemu sam pričao, odnosilo se na ORAO 102:
http://hr.wikipedia.org/wiki/Orao_(računalo)
Mora se ručno dodati desna zagrada. Inače gde li se izgubiše genijalci tog doba: http://rep.hr/vijesti/tehno-i-...leb-i-orao-su-moje-djelo/2335/

Obrati pažnju na ovaj deo sa linka:
Citat:

Memorijska mapa [uredi]
0000 - 03FF - nulti blok (1K)
0400 - 5FFF - korisnički RAM (23K)
6000 - 7FFF - video RAM (8K)

8000 - 9FFF - sistemske lokacije (8K)
A000 - AFFF - proširenje (1K)
B000 - BFFF - DOS (1K)
C000 - DFFF - BASIC ROM (8K)
E000 - FFFF - sistemski ROM (8K)


Dakle, radilo se o prelazu iz segmenta "korisnički RAM" ka segmentu "video RAM". Ali ja to tada nisam kapirao. Kasnije, kada sam se zainteresovao za 6502 asemblere, sa zakašnjenjem sam skapirao šta je bio uzrok.

Video RAM je činilo 8KB, rezolucije 256x256 piksela (podeljeno sa 8 bitova=8192bajta), bez boja, samo crno belo. Idealno projektovano za eksperimente. Zato se sve u vezi grafike prilično brzo izvršavalo za tih 1MHz.

Sviđa mi se1
Re: Ponavljanje main funkcije 28.10.2012. u 15:10 · pre 170 meseci
izmenjeno 1 put, poslednji put Nedeljko 28.10.2012. u 17:40
  1. Nedeljko28.10.2012. u 17:40zapis iz teksta poruke
#20
A, pa to je bio .
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Odgovori
Prijavite se da biste odgovorili u ovoj temi.PrijavaRegistracija

Premeštanje teme