Imas li primjer tog koda? Pa ti onda lako objasnimo u cemu je stvar.
Programiranje u C++-u - pitanja i odgovori
- poruka: 7.284
- |
- čitano: 1.948.639
- |
- moderatori:
XXX-Man
- +/- sve poruke
- ravni prikaz
- starije poruke gore
Imam neki uvjet
if ((b[i] == 'a') || (b[i] == 'e') || (b[i] == 'i') || (b[i] == 'o') || (b[i] == 'u')) *a++;
Zasto ova sintaksa ne radi i ne podize mi varijablu? Ako napisem ++*a, onda radi uredno.
EDIT:
Za ovaj program povise, tebi on podize _upisao za svaki broj koji upises, ukljucujuci i nulu. Pa ako upises 5 brojeva i nulu, on ti to izbroji kao 6. Provjera jesi li upisao 0 se dogadja tek pri ulasku u petlju, a do tada ti je brojac vec podignut i za tu nulu koju si upisao. To mozes rjesiti tako da u while petlji napises jos jedan uvjet prije _upisao++, koji bi glasio:
if(_broj==0) {
break;
}
else
_upisao++
Na ovaj nacin ti petlja svaki put provjerava jeli uneseni broj 0 prije negoli dodje do dijela di se brojac podize, a ako nije, tek onda ti dize brojac. Break znaci da ce izaci iz petlje kad se uvjet ostvari.
Imam neki uvjet
if ((b[i] == 'a') || (b[i] == 'e') || (b[i] == 'i') || (b[i] == 'o') || (b[i] == 'u')) *a++;
Zasto ova sintaksa ne radi i ne podize mi varijablu? Ako napisem ++*a, onda radi uredno.
Te provjere možeš napraviti i pomoću switcha. Također ti ne trebaju zagrade (b[i] == '0').
@To smo sredili tako da je početna vrijednost bila -1 a ne nula.
Evo koda i test
Pa ovaj kod radi upravo to sto i pise. Ceka upis broja, nakon toga poveca brojac za 1.
S tim da ovo nije najsretnije napravljeno jer varijabla _broj nije inicijalizirana i u njoj se nalazi smece. Moze se nekim cudom dogoditi da to smece bude bas nula. Kad se to dogodi petlja ce biti preskocena bez da se upise i jedan broj. To je jedan od onih suptilnih bugova kod kojih sve radi sto puta, a stoprvi sve se srusi. Tako da varijablu _broj treba inicijalizirati na neku vrijednost koja nije 0.
U tvom primjeru pretpostavimo da je _broj neka vrijednost koja nije nula. Ulazi se u while petlju i provjerava se uvjet koji je istinit i petlja nastavlja s izvrsavanjem. Upises 1, uveca se brojac (sad je 1), provjerava se uvjet koji je istinit jer je _broj == 1. Upises opet 1, uveca se brojac (sad je 2), provjerava se uvjet, istinit je. Upises opet 1, uveca se brojac (sad je 3), provjerava se uvjet, istinit je. Upises opet 1, uveca se brojac (sad je 4), provjerava se uvjet, istinit je. Sad upises 0, uveca se brojac (sad je 5 - obrati paznju na ovo), provjerava se uvjet (znaci tek sad se provjerava uvjet kad su se sve naredbe u cijeloj petlji izvrsile), uvjet je laz jer _broj vise nije razlicito od 0, izlazi se iz petlje i ispisuje se 5.
Imam neki uvjet
if ((b[i] == 'a') || (b[i] == 'e') || (b[i] == 'i') || (b[i] == 'o') || (b[i] == 'u')) *a++;
Zasto ova sintaksa ne radi i ne podize mi varijablu? Ako napisem ++*a, onda radi uredno.
Isprobaj sto se dogodi ako napises (*a)++.
EDIT:
Objasnjenje: kod ovoga *a++, plusplus je ovdje postfiks operator, dakle, uvecat ce se tek nakon svega odradenog. No, trebas imati na umu prednost operatora.
Tako da, ovo kompajler interpretira kao *(a++) jer postfiks ++ ima vecu prednost od operatora dereferenciranja. Sto znaci sljedece: uvecaj adresu pokazivaca a, ali tek NAKON sto se cijela naredba zavrsi. Dereferenciraj staru vrijednost pokazivaca (prije uvecavanja). Tek u sljedecem retku koda a ce biti uvecan i pokazivati tko zna gdje (ne znam da li je to polje ili varijabla).
Kod ++*a, rijec je o prefiks operatoru, a prefiks operator i operator dereferenciranja imaju jednaku prednost, no asocijativnost im je s desna na lijevo sto znaci da kompajler ovo interpretira kao ++(*a), drugim rijecima, uvecaj ODMAH dereferenciranu vrijednost.
S takvim izrazima moras biti jako oprezan jer kao sto vidis ovisno o prednostima pojedinih operatora ove dvije naredbe rade sasvim razlicite stvari. Jedna uveca adresu pokazivaca, druga vrijednost na koju pokazivac pokazuje.
Zato sam ti prvo i napisao sto se dogodi ako stavis (*a)++ jer na taj nacin dajes jasno do znanja kompajleru kojim redom zelis da se izvrsavaju operacije.
Ako je meni a 2, koji broj će biti nakon *a++?
Ako je meni a 2, koji broj će biti nakon *a++?
Procitaj ovaj EDIT koji sam napisao pa probaj skuziti sam.
No ako cemo cjepidlaciti, nece se dogoditi nista, jer ako je a = 2 onda je to varijabla, a ne pokazivac, a varijablu ne mozes dereferencirati. 
Na goto ti se gleda kao na nesto negativno u programerskom svijetu i kao nesto sto treba izbjegavati jer unosi nered u kod.
Na goto ti se gleda kao na nesto negativno u programerskom svijetu i kao nesto sto treba izbjegavati jer unosi nered u kod.
Ali zašto? Kako da sad ja taj kod vratim nazad?
Nije bez razloga da postoje 3 vrste petlji u C++u. U ovom tvom slučaju idealna je petlja do-while.
Na goto ti se gleda kao na nesto negativno u programerskom svijetu i kao nesto sto treba izbjegavati jer unosi nered u kod.
Ali zašto? Kako da sad ja taj kod vratim nazad?
Goto je ostavstina programiranja u assembleru. U to vrijeme su se petlje izvodile na nacin usporedjivanja dvaju brojeva, te ovisnosti o rezultatu te usporedbe, program je negdje "skakao"(Goto). Uvodom standardnih petlji u modernim programskim jezicima potreba za skakanjem je nestala, kod bi nakon petlje nastavio prema svom kraju i ti si tocno znao gdje se nalazis u kodu. U assembleru to nisi mogao znati jer se program izvrsava tako da "skakuce" na razne adrese. Evo ti primjer if petlje u assembleru i u C++:
If:
cjne r0,#001h,skok
radi nesto
skok:
ret
C++
if (a==1){
radi nesto
}
Izvedbom if petlje u cpp-u ti znas da ides na sljedecu liniju koda, izvedbom assembler verzije ti nemas pojma gdje te skok vodi, mozes skociti na pocetak ili jednako na kraj programa. Zamisli sad program od 1000 linija koda koji svako malo skakuce na razne svoje dijelove, to je teski clusterfuck.
Koja je svrha koristenja underscora ('_') u C/C++-u kao pocetni znak imena identifikatora? To sam vidio na par mjesta, cini mi se u nekim STL implemntacijama.
Je li to nekakva konvencija (kao camel case?
Pa koristis npr. do - while petlju
int broj;
do{
cin >> broj;
}while(broj < 0);
Koja je svrha koristenja underscora ('_') u C/C++-u kao pocetni znak imena identifikatora? To sam vidio na par mjesta, cini mi se u nekim STL implemntacijama.
Je li to nekakva konvencija (kao camel case?
Primjerice, atributi (članske varijable) klase mogu imati underscore prije imena tako da ih se lakše razlikuje od parametara metoda koje koriste ista imena. Npr.:
class Osoba {
public:
string _ime;
string _prezime;
Osoba(string ime, string prezime) : _ime(ime), _prezime(prezime) {}
};
Petlja for: kada se zna koliko puta se nešto treba dogoditi.
Petlja while: kada se ne zna koliko puta se nešto treba dogoditi.
Petlja do-while: kada se nešto treba dogoditi barem 1 puta.
Svaku od ovih petlji je moguće napisati preko neke druge petlje, ali u pravilu ih je najlakše koristiti prema namjeni.
Zdravo, tu se nalazi program koji smo dobili na pismenom ispitu na kojem smo trebali napisati ispis.
Imam neke nejasnoće pred kraj zadatka, pa me zanima zna li neko da objasni.
#include <iostream>
using namespace std;
class Foo {
int x, y;
public:
Foo() { cout << "A" << endl; x = 1; y = 2; }
Foo(int x, int y) { cout << "B" << endl; Foo::x = x; Foo::y = y; }
void Modify(int z) { x *= z; y *= z; }
int GetX() { return x + 10; }
int GetY() { return y - 5; }
void Display() { cout << x + y << " " << x - y << endl; }
};
class Bar {
int x;
Foo y;
public:
Bar(int y) { cout << "C" << endl; x = y; }
Bar(int x, int y, int z) : y(x, z) { cout << "D" << endl; Bar::x = y; }
int GetX() { return x; }
Foo GetY() { return y; }
void Display() { cout << x << endl; y.Display(); }
};
int main() {
Foo a;
Foo b(3, 2);
cout << a.GetX() << " " << a.GetY() << endl;
cout << b.GetX() << " " << b.GetY() << endl;
a.Display();
b.Display();
Foo c = a;
c.Modify(2);
a.Display();
c.Display();
Bar d(2);
Bar e(1, 5, 3);
cout << d.GetX() << " " << d.GetY().GetX() << " " << d.GetY().GetY() << endl;
e.Display();
Foo f[4];
Foo g[3] = { Foo(3, 2), Foo(1, 1), Foo(2, 2)};
f[2].Display();
g[1].Display();
Foo *p;
Foo *q;
p = new Foo(10, 10);
q = p;
q->Modify(3);
p->Display();
return 0;
}
Ovo je ispis cijelog zadatka:
A
B
11 -3
13 -3
3 -1
5 1
3 -1
6 -2
A
C
B
D
2 11 -3
5
4 -2
A
A
A
A
B
B
B
3 -1
2 0
B
60 0
Meni je nejasan zadatak tj. ispis zadatka od ovog dijela pa nadalje:
Bar d(2);
Bar e(1, 5, 3);
cout << d.GetX() << " " << d.GetY().GetX() << " " << d.GetY().GetY() << endl;
e.Display();
Foo f[4];
Foo g[3] = { Foo(3, 2), Foo(1, 1), Foo(2, 2)};
f[2].Display();
g[1].Display();
Foo *p;
Foo *q;
p = new Foo(10, 10);
q = p;
q->Modify(3);
p->Display();
A ispis od ovog dijela je:
A
C
B
D
2 11 -3
5
4 -2
A
A
A
A
B
B
B
3 -1
2 0
B
60 0
Molim vas iskreno ako iko zna da mi pomogne, već u utorak mi je drugi ispit...
S obzirom da dio razumiješ, nisi od jučer tu evo objašnjenja. Napisao sam na brzinu pa ako mi se omakla koja greškica javite mi pa popravim ;) Nije nigdje oslobođena memorija za dinamički stvoren objekt. Može samo komentar gdje je postavljen ovaj zad?
// Bar d(2);
/*
Stvara se objekt d Bar klase, par. ctorom koji ima jedan argument. Kod svakog stvaranja Bar objekta tim ctorom
mora se najprije defaultnim konstruktorom kreirati njegov podatkovni član koji je Foo objekt, jer nije eksplicitno
navedeno koji ctor se koristi, zato se ispisuje A - poziva se def. ctor. klase Foo
*/
>> A
/*
Sad se poziva konstruktor Bar s jednim parametrom, kao argument je dan 2, pa je pod. član x postavljen na 2.
*/
>> C
// Bar e(1, 5, 3);
/*
Kreira se objekt e Bar klase par. ctorom. U inic. listi tog ctora eksplicitno je navedeno koji se ctor koristi
za Foo objekt, a to je: y(x, z) Taj ctor koristi argumente 1 i 3, ispisuje B i onda postavlja pod. članove na dane vrijednosti.
*/
>> B
/*
Nakon što je završio konstruktor za pod. član, nastavlja se tijelo ctora klase Bar. Ispiuje D i postavlja
vrijednost pod. člana.
*/
>> D
// cout << d.GetX() << " " << d.GetY().GetX() << " " << d.GetY().GetY() << endl;
/*
Ako se pogleda konstruiranje stvari kako je gore opisano, d ima u x pohranjeno 2 - to je prva ispisana vrijednost.
U istom objektu imamo Foo objekt stvoren def. ctorom koji ima atribut x postavljen na 1. Kad se na tom objektu pozove
getX() vraća se x + 10, što je 11 - drugi ispisan broj.
Također, def ctorom je y dio tog unutarnjeg objekta je postavljen na 2. getY na tom objektu vraća y - 5 što je -3
i ujedno i posljednji broj koji se ispisuje.
*/
>> 2 11 -3
// e.Display();
/*
Metoda Display pozvana je na Bar objektu e, najprije ispisuje x vrijednost, koja je 5. (Par. ctor je postavio kad smo
kreirali objekt s 1 5 3). Nakon toga poziva se Display na unutarnjem objektu Foo klase. Ta metoda ispisuje x+y x-y što je
1+3 i 1-3, vidi par. ctor i opis iznad.
*/
>> 5
>> 4 -2
// Foo f[4];
/*
Stvara se polje objektata na stacku od 4 elementa, moraju se pozvati def. ctori za svaki pa onda imamo
*/
>> A
>> A
>> A
>> A
// Foo g[3] = { Foo(3, 2), Foo(1, 1), Foo(2, 2)};
/*
Sad se stvara polje od 3 elementa, ali se koriste par. ctori pa je ispis
*/
>> B
>> B
>> B
// f[2].Display();
/*
Cijelo f polje popunjeno je objektima stvorenim def. ctorima, a ispis daje van x+y x-y. To je 1+2 1-2 pa je
ispis
*/
>> 3 -1
// g[1].Display();
/*
g[1] je drugi element u tom polju (prvi ima indeks 0), a to je Foo(1, 1). Ispis je isti kao gore, dakle 1+1 1-1
*/
>> 2 0
// Foo *p;
// Foo *q;
/*
Ovo je samo deklaracija pokazivača, nema nikakvog ispisa
*/
// p = new Foo(10, 10);
/*
Sad se stvara novi objekt par. ctorom.
*/
>> B
// q = p;
/*
Uzima se adresa pohranjena u pointeru p i pohranjuje u pointer q, nema ispisa. Oba pointera pokazuju na isti objekt.
*/
// q->Modify(3);
/*
Poziva se metoda modify preko pointera. Svaki član unutar objekta množi se s argumentom i pohranjuje se vrijednost.
Argument je 3. Što znači da taj objekt sada ima atribute 30 30. Ova metoda ne ispisuje ništa.
*/
// p->Display();
/*
Zove se Display na pointeru p, no sjeti se iz ranijeg koraka da p i q pokazuju na isti objekt koji je izmijenjen.
Display ispisuje x+y x-y a to je 30+30 30-30 što je i vidljivo dolje
*/
>> 60 0
Hvala puno na izdvojenom vremenu i jasnom objašnjenju.
A za Vaše pitanje gdje je postavljen zadatak, navela sam već u postu da mi je zadatak dat na pismenom testu da napišem njegov ispis..
Vidio sam to, zanimala me ustanova ;)
SSST - Sarajevo School of Science and Technology 
Situacija je sljedeća:
Taj dan sam izostao iz škole jer sam ujutro išao na operaciju, a popodne sam imao školu. Javlja meni frend da riješim sljedeći zadatak.
"Odredi najmanji prirodni broj kod kojem je umnožak znamenaka 5040"
I ništ, riješim ja taj zadatak brzo, malo sam se mučio s rastavljanjem znamenaka na pojedinačni znak, no savladao sam to.
Sad mene zanima, dali ima još neki način da se riješi ovaj zadatak? Ovi iz razreda govore da ne razumiju tu ništa, šta se tu radi. Ja sad gledam, dal ja ne znam(a bavim se programiranjem već duže vrijeme) ili je profa neki Einstein pa je našao lakši način za riješiti ovaj zadatak.
Rješenje je inače 25789.
int kandidat = 0, umnozak;
do{
umnozak = 1;
int pom = ++kandidat;
while (pom){
umnozak *= pom % 10;
pom /= 10;
}
}while (umnozak != 5040);
cout << kandidat;
int kandidat = 0, umnozak;
do{
umnozak = 1;
int pom = ++kandidat;
while (pom){
umnozak *= pom % 10;
pom /= 10;
}
}while (umnozak != 5040);
cout << kandidat;
Hvala ti, vidjet ću kako je to profa sklepao. 
Može se efikasnije riješiti zadatak
zadani broj se može raspisati na proste faktore
Riješenje su zapravo ti prosti brojevi stavljeni na najveću potenciju (a da su u int [2,9] s kojom su još uvijek djeljivi s tim brojem
Evo i koda za par minuta
Edit:
Ujutro ipak, ali može se jednostavnije
Može se efikasnije riješiti zadatak
zadani broj se može raspisati na proste faktore
Riješenje su zapravo ti prosti brojevi stavljeni na najveću potenciju (a da su u int [2,9] s kojom su još uvijek djeljivi s tim brojem
Evo i koda za par minuta
Edit:
Ujutro ipak, ali može se jednostavnije
Mislim da može i bez rastavljanja na proste faktore. Funkcija vraća -1 u slučaju da rješenje ne postoji.
int func(int number) {
int result = 0, base = 1;
for (int i = 9; i > 1; i--) {
while (number % i == 0) {
result += base * i;
number /= i;
base *= 10;
}
}
return number == 1 ? result : -1;
}
Na goto ti se gleda kao na nesto negativno u programerskom svijetu i kao nesto sto treba izbjegavati jer unosi nered u kod.
Ali zašto? Kako da sad ja taj kod vratim nazad?
zato (probaj pratiti kod..)
- osim drugih načina do-until-while s izlazom na vrhu ili dnu, pa i exitom u sredini.. početni kod ako se već tako dobije vježba jednostavno ispis umanjiš za jedan... bez gotoa i sl. (ako se druge petlje ne dozvoljavaju, zbog učenja).
- zapravo, svejedno koji način, ti biraš.. i za vježbu trebaš napraviti na sve načine, od samog naziva varijabli nadalje. Svtar je čitljivosti, urednosti.. i timskog rada, netko mora taj kod održavati, debugirati.. pa i sam autor, lakše je kad se držiš 'nepisanih' pravila, ne treba izmišljati toplu vodu. :)
Pokušao string.h i string includati ali i dalje kaže da string _rezultat nije definiran
#include <stdio.h>
#include <conio.h>
#include <string>
#include <algorithm>
int main()
{
string _rezultat = "";
int _broj;
printf("Upisi broj:\n");
scanf("%d", &_broj);
do
{
if (!(_broj & 1)) _rezultat += "0";
else _rezultat += "1";
_broj >>= 1;
}
while(_broj);
reverse(_rezultat.begin(), _rezultat.end());
printf("%s\n", _rezultat);
getch();
return (false);
}
using namespace std;
Pokušao string.h i string includati ali i dalje kaže da string _rezultat nije definiran
...
Normalno da nije kad mu nisi dao kojeg je tipa varijabla. Nije ti ovo Python. :D

