Új hozzászólás Aktív témák
-
Sk8erPeter
nagyúr
Valószínű elég láma kérdés, de kezdő vagyok C-ben, két feladatom van:
1.) Kör egyenlete alapján karakteresen kirajzolni egy kört (pl. mittudomén, X-ekkel ) (persze nyilván nem lesz egy szép kör, de nem baj)
2.) Mondjuk 5 db egymásban elhelyezkedő téglalapot kirajzolni szintén karakteresen (szintén mondjuk X-ekkel), lehetőleg rekurzívan (de nem rekurzív megoldás is jöhet)
Most gyorsan lerajzoltam Paint-ben, valami ilyesmire gondolok:
Csak a téglalap oldalai X-ekkel kirajzolva.
De ha sima négyzettel jóval egyszerűbb, akkor akár az is jó.Ilyen tök alap (ANSI) C utasításokra gondoljatok, semmi komplikált, ezekkel kellene tudni megoldani a feladatot.
Előre is köszönöm!
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Jester01 #958 üzenetére
Lehet, hogy triviális, csak nem számomra.
Nem tanultunk setpixel függvényről, ami azt jelenti, hogy jelen esetben nem is kéne használni, hanem csak olyan alap függvényekkel és utasításokkal kellene megoldani, amiket az elején tanul az ember, kb. printf, scanf, for és (do-)while ciklusok, if/else, tömbök meg hasonlók szintjén, szóval tényleg nagyon amatőr módon, meg olyan headereket include-olva, mint az stdio.h, string.h, stdlib.h, esetleg math.h, vagy ha nagyon kell, a kevésbé független conio.h, stb...
Ilyen megoldás elképzelhető?Egyébként köszi, hogy ilyen gyorsan válaszoltál!
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Jester01 #967 üzenetére
Mi így oldottuk meg az ékezetes karakterek helyes megjelenítését:
char * magyarit(const char * src){
unsigned i;
static char dest[2000];
for(i=0;src[i];i++){
switch(src[i]){
case 'á': dest[i]=160; break;
case 'é': dest[i]=130; break;
case 'í': dest[i]=161; break;
case 'ó': dest[i]=162; break;
case 'ö': dest[i]=148; break;
case 'ő': dest[i]=139; break;
case 'ú': dest[i]=163; break;
case 'ü': dest[i]=129; break;
case 'ű': dest[i]=251; break;
case 'Á': dest[i]=181; break;
case 'É': dest[i]=144; break;
case 'Í': dest[i]=214; break;
case 'Ó': dest[i]=224; break;
case 'Ö': dest[i]=153; break;
case 'Ő': dest[i]=138; break;
case 'Ú': dest[i]=233; break;
case 'Ü': dest[i]=154; break;
case 'Ű': dest[i]=235; break;
default: dest[i]=src[i];
}
}
dest[i]=0;
return dest;
}Aztán printf-nél meg így hivatkozom rá, pl.:
printf(magyarit("Nettó ár: "));
Ez itt nem lenne jó?
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Jester01 #962 üzenetére
Bocs, de mi az az "r=0..2 PI"?
Elsőre úgy értelmezném, hogy a 2kPi-t akarja jelenteni, ahol k=0,1,2, de ennek a körnél semmi értelme, mert a sugár nem 2kPi.
A kör egyenlete alapján kéne megoldanom a feladatot:
ha C(u,v) a kör középpontja, és P(x,y) a kör egyik pontja, akkor az egyenlet:
CP^2 = r^2 = (x-u)^2 + (y-v)^2De nem igazán tudom, hogy is oldjam meg ez alapján a feladatot.
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Jester01 #974 üzenetére
Értem, de sajnos egyelőre így sincs elképzelésem, hogy hogyan kéne megcsinálni ezt a feladatot, meg szerintem nem is totál kezdőnek való feladat, de persze lehet, hogy csak én vagyok a béna.
Mondjuk itt ezt sem értem: "double fi = i / 100.0 * 2 * M_PI;" Növelgetjük egészen 99-ig i-t (for(i = 0; i < 100; i++)), de nem tudom, miért.
Sk8erPeter
-
Sk8erPeter
nagyúr
Hali!
Van néhány txt-fájlom, amelyeknek minden sorában az első 4 karaktert szeretném kitörölni.
Mi lenne ennek a legegyszerűbb módja?
1.) Milyen függvénnyel lenne a legjobb beolvastatni a szöveget? (soronként olvassa be, és tárolja el? vagy hogy?)
2.) Ezen belül a fájlok elérési útját hogyan adom meg?
3.) Hogyan születik meg a javított kimeneti fájl?Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Benmartin #1102 üzenetére
Hali!
Köszi, hogy megírtad, de ez a program igen érdekes dolgokat csinál
A végeredmény az lesz, hogy MINDEN karakter után tesz egy szóközt. Egy fájlnál az összes sortörést is kitörölte (mondjuk nem értem, hogy ezt a másiknál miért nem tette).
Szemléltetésként ilyen lesz: [link] (itt épp php-kódokat másoltam ki pdf-ből, a sorszámozást ki akartam szedni, de ez a lényeg szempontjából tök mindegy)Első lefordításnál ilyen hibát dob:
(már a while(!feof(filelist))-nél baja van)
Gondolom ezért is működik hibásan többek közt...
Aztán már le sem akar fordulni (létrehozni az exe-t), na mindegy, itt valami nagyon nem jó...
De azért thx. Egy javított verzió jól jönne... Előre is köszi!Egyébként az "általános kérdéseket" hajnali fél 5 közeledtével fogalmaztam meg, így simán elképzelhető, hogy hülye kérdést tettem fel...
(#1103) doc: igazából mindkettő... de inkább gyakorolni szeretnék C-ben.
Nem használok Linuxot (egyelőre). Tehát elsősorban a C-s megoldás érdekelne.
Nyilván létezik egyébként olyan külső program (pl. Lupas Rename), amivel lazán megoldható, de abból nem lehet tanulni.(#1104) Jester01: Esetleg tudnál egy javított változatot mutatni?
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Benmartin #1109 üzenetére
"mert nem volt '\n' a sor végén." De itt pont különálló, sortöréssel elválasztott sorokról van szó... bár lehet, hogy félreértelek...
Milyen fordítóval próbáltad? Nálam most Visual Studio 2003 van fent (azért használom ezt egyelőre, mert egyetemen is ezt használják szoftver laboron, nem akarom, hogy a fordító különbözősége miatt ott jelentkezzen egy hiba, amire nem számítok)
Most még mindig csak azt nem tudom, hogyan is kéne akkor megoldani a feladatot, na majd próbálkozom...
Azért kérdeztem egyébként, hogy mivel olvastassam be az adatokat, mert lehetne fscanf(), fgets(), fgetc(), fread(), és még ki tudja, hány függvénnyel is elvégeztetni ezt a feladatot (fgetc nyilván nem jó, meg fscanf sem, asszem annak is van valami szóköz-problémája).
Valami olyasmire gondoltam egyébként, hogy a progi a beolvasáskor az első /n-ig elmegy, eltárol egy sort valamilyen tömbbe vagy akármibe, és ezt úgy adja ki, hogy az 5. karaktertől lesz kiírva. Végül is ha tömbként kezelem, akkor elvileg a 0. elemtől kezdi, akkor elég lenne csak hozzáadni +4-et, hogy kezdje onnan, nem?Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Jester01 #1113 üzenetére
Bocsi, hogy csak most válaszolok, nem nagyon voltam gépközelben!
Köszönöm, hogy megírtad, ez nagyon faszán működik!
Pár rövid pluszkérdés:
1.) Ami érdekességet (számomra érdekes) felfedeztem, hogy ha sima Notepad-del, Unicode kódolással mentek egy fájlt, akkor nem működik a program, és egy 0 bájtos verziót készít el, míg az ANSI kódolásúakkal nincs probléma. Ez mitől van?
(Ha Notepad++-szal készítem el ugyanazt a fájlt, amiért a sima Notepad pampog, hogy elveszhetnek egyes karakterek, ha nem Unicode-ban mentem, akkor semmi para. Gondolom alapvetően a Notepad++ ANSI kódolással készíti el a fájlt, nem?)
2.) A "const int column" miért fontos, hogy const legyen?
3.) A "char infilename[MAX_FILENAME_LENGTH + 1];" sornál miért kell a +1?
4.) Ugyanígy ott van a plusz 1 a "char outfilename[MAX_FILENAME_LENGTH + 9]; /* a +8 a _jav.txt miatt */" sorban.
5.) A többin még gondolkozom...Még egyszer köszönöm, hogy megírtad!
Sk8erPeter
-
Sk8erPeter
nagyúr
Tényleg, ha már pointerek és tömbök hasonlóságáról van szó, kérdeznék: tanultuk, hogy hasonlóság van a kettő között, de van különbség memóriakezelésben. Milyen szempontból?
Ha pointerként hivatkozol (pl. int *p) az elvileg ugyanazt adja, mint a tömb első (nulladik) elemének címe. De akkor mi a jelentős különbség?Sk8erPeter
-
Sk8erPeter
nagyúr
"míg a pointer szabadon módosítható, a tömbváltozó nem, konstans értéke van."
Most ezt nem nagyon értem: a tömbváltozó is módosítható. Mármint a tömbben tárolt érték. Nyilván a pointer átállítható, hogy más elem címére mutasson.
Na de akkor mi a releváns különbség a memóriakezelésben?(#1383) shev7 : ezt sem értem, mert dinamikusan is, futásidőben is lehet memóriát foglalni tömbnek, attól függően, hogy mondjuk mekkora egy másik tömb, aminek az elemeit át szeretnénk másolni egy új tömbbe, attól függően módosítjuk a foglalt memóriaméretet.
_______________________________________________________
(#1380) cellpeti: nem értem, minek állítgattad át? Letöltöd, telepíted, működik. Tök felesleges állítgatni valamit, ha nem tudod, mi az...
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Akkor lehet, hogy valami fogalmi képzavar esete forog fenn nálam, vagy nem vágom,
de az alábbi példaprogram jól szemlélteti a dinamikus memóriafoglalást, amire gondoltam, itt az eredeti tömbből egy új tömbbe gyűjti az eredeti tömbben szereplő, átlag alatti számokat, és pont akkora memóriát foglalunk le az új tömbnek, amennyire szükség van, nem többet, nem kevesebbet:#include <stdio.h>
#include <stdlib.h>
double *atlagalatt(double tomb[], int meret, int *ujmeret){
double *ujtomb;
int i, db, to;
double szum, atlag;
/* mi az atlag */
szum=0;
for (i=0; i<meret; ++i)
szum+=tomb[i];
atlag=szum/meret;
/* hany olyan van */
db=0;
for (i=0; i<meret; ++i)
if (tomb[i]<atlag)
db++;
/* foglalas es paranoia */
ujtomb=(double*)malloc(db*sizeof(double));
if (!ujtomb) {
*ujmeret=0;
return NULL;
}
/* masolas */
to=0;
for (i=0; i<meret; ++i)
if (tomb[i]<atlag)
ujtomb[to++]=tomb[i];
*ujmeret=db;
return ujtomb;
}
int main(){
double eredeti[100];
double *uj;
int ujmeret;
int i;
for (i=0; i<100; ++i)
eredeti[i]=rand()%100/10.0;
uj=atlagalatt(eredeti, 100, &ujmeret);
for (i=0; i<ujmeret; ++i)
printf("%4.2g ", uj[i]);
free(uj);
}Szerk.: Forrás: [link]
Sőt, ha már linkeltem, itt látható a 4-es feladatban a futásidőben történő memóriafoglalás:
#include <stdio.h>
#include <stdlib.h>
char ** darabol(char *s,char *m,int *db){
int n=0,i,last=0;
char **p;
// szavak számolása
for(i=0;s[i]!=0;i++){
int j;
for(j=0; m[j]!=0 && s[i]!=m[j]; j++);
if(m[j]!=0 && i!=last){
n++;
last=i+1;
}
}
p=(char**)malloc(n*sizeof(char*));
if(p==NULL)exit(-1);
for(i=n=last=0;s[i]!=0;i++){
int j;
for(j=0; m[j]!=0 && s[i]!=m[j]; j++);
if(m[j]!=0 && i!=last){
p[n]=(char*)malloc(i-last+1);
if(p[n]==NULL)exit(-1);
for(j=last;j<i;j++)p[n][j-last]=s[j];
p[n][j-last]=0;
n++;
last=i+1;
}
}
*db=n;
return p;
}
int main(int db,char ** par){
FILE * fp;
char sor[1025];
int meret;
if(db<3)return -1;
fp=fopen(par[1],"rt");
if(fp==NULL)return -1;
while(fgets(sor,1025,fp)!=NULL){
char **p=darabol(sor,par[2],&meret);
while(meret--)free(p[meret]);
free(p);
}
}[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Sk8erPeter #1399 üzenetére
Most akkor itt megállt a tudomány? Mert a kérdésre még akkor mindig nem tudom a választ a dinamikus memóriafoglalással kapcsolatban.
Mármint hogy tömb-nem tömb, futásidőben történő méretnövelés, stb... Amiről korábban szó volt, hogy állítólag nem lehet tömbnek futásidőben változtatni a méretét. Most akkor mi van? Fogalmi képzavar?(#1403) Karma: OK, köszi, nem sürgetésképpen írtam, csak azt hittem, hogy akkor skippeltétek a hsz.-t, mert túl hosszúra sikerült a példák miatt.
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
A kolléga itt azt mondja, nem lehet futásidőben növelni a tömb méretét. De most akkor itt nem éppen az történik? Itt tulajdonképpen pointerrel és/vagy tömbbel játszik, de a kettő bizonyos szempontból hasonló, mégis más a kettő, és most már akkor kezdem azt sem érteni, amit azt hittem, eddig értettem Tehát itt a mutatott példában pl. egy új tömbnek már futásidőben foglal akkora memóriát, amekkora számára szükséges. A másikban meg még bővíti annyival, amennyi kell, mivel csak egyszer olvashatjuk be az állományt. Ugyanúgy kezeli, mint egy tömböt. De akkor most mi is az igazság?
Sk8erPeter
-
Sk8erPeter
nagyúr
Huhh. No, akkor valóban vannak homályos foltok.
Megpróbálom értelmezni akkor a lényegi kérdést, kérlek javíts, ha valamit rosszul gondolok:
A double *ujtomb; sorban tehát deklarálunk egy pointerváltozót ujtomb néven, aminek csak később foglaljuk le a szükséges memóriát, először még csak meghatározzuk, hogy "lesz ilyen". Amikor megtudtuk az eredeti tömb számunkra szükséges elemeit megszámolva, mekkora új tömbre van szükségünk, azután lefoglaltuk neki a számára szükséges memóriát. Ezután tömbként és egyben pointerként használtuk fel a későbbiekben, rakosgattunk bele elemeket, és itt ez most kicsit zavaros számomra, hogy akkor most melyik fogalmat is használjuk, ami helytálló. Mert tömbnek foglalunk helyet, de pointertömb...
A második feladatban már megint ez a fogalmi zavar a bajom. (pointer, tömb, pointertömb...)
Ráadásul - bocsi az értetlenkedésért, csak vannak ilyen homályos pontok - akkor a memóriafoglalással ezek szerint nem "méretezünk", hanem nem tudom, mit csinálunkÉs még egy pluszkérdés: a main()-ben free-vel felszabadítjuk a memóriát, de ekkor nem "szabadulunk meg" egyben az adatszerkezet már korábban eltárolt értékeitől is?
Bocs a sok kérdésért, és köszönöm az eddigi és további segítséget.
(#1411) shev7: pont most küldtem a hsz.-t. köszi, rögtön végiggondolom, hogy leülepedjen. És igen, jól látod, még nem jött át, kicsit zavar van most az agyamban. De már dereng valami!
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Szóval akkor pl. az általam mutatott példában az ujtomb nevű tömb nem tömb, hanem pointer. De a tömb olyan, mint egy pointer, mert pl. függvénynek már eleve a címet adjuk át, ha tömböt adunk át. De a pointernek mások a tulajdonságai, szabadon, futásidőben változtatható a memóriaigénye, ide-oda állítgatható, stb., míg a tömbnek már fordításkor meghatározott a memóriaigénye, akármilyen adatot pakolászunk is bele (persze a megadott típus szerinti méretkorlátokon belül). Tehát a tömbnek ha megszakadunk, sem tudunk változtatni futásidőben a memóriaszükségletén.
Az eddigiek helytállóak? És "csupán" ilyen szempontból van eltérés?Szerk.: jól "egyszerre" írtuk a hsz.-eket, olvasom is a válaszaitokat.
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Köszi a válaszokat, Karma és shev7, azt hiszem, már nagyjából értem.
"magát a pointert sikeresen definiáltuk, 4 byte-ot kapott a stacken (vagy globálisan), mint egy átlagos változó. De ezt most felejtsük el egy pillanatra, mert irreleváns." És hogy is van tovább?
"Dehogynem. Amire meghívod a free-t, az felszabadul, az értékei érvénytelenné és elérhetetlenné válnak."
Mondjuk jelen esetben a példaprogramnál ez nem volt világos, hogy minek foglaltunk akkor helyet az adatoknak, ha utána rögtön az eltárolás után meg is szabadultunk tőle. Igaz, erre lehetne azt mondani, hogy mivel nem volt része a feladatnak az, hogy tovább tárolgassuk, és még csináljunk vele valamit, csak a szavakra darabolás.(#1413) shev7: "Ott a kovetkezo egyenloseg igaz: p[5] = *(p+sizeof(int)*5)" Ettől egy kicsit megijedtem, mivel pont nem ezt tanultuk, hanem azt, hogy azzal egyenlő, hogy *(p+5). De látom később megbeszéltétek, hogy valóban az utóbbi a jó.
Itt viszont nem értettem az összefüggést: "ja es ezert indexeljuk 0-tol a tomboket C-ben" azzal, amit ezelőtt írtál.
Egyébként számomra az is újdonság volt, hogy lehet deklarálni úgy egy változót, hogy byte *p; . Ez mire jó ebben a formában? Még konkrét programban kevésszer láttam így deklarálva egy változót, de valamilyen szempontból nyilván hasznos lehet.Köszi nektek a türelmes válaszokat!
Sk8erPeter
-
Sk8erPeter
nagyúr
Nem a * operátor sorrendjén voltam meglepődve, hanem magán a "byte" típuson. Eddig nem használtam, és nem is igazán láttam gyakorlati feladatokban konkrétan ezt a típust. Szóval erre kérdeztem, hogy mire jó.
Egyébként jó, hogy felhívtad a figyelmem, hogy attól még, hogy a csillagot a típus mögé rakom közvetlenül, nem lesz a következő változó is automatikusan pointer (mondjuk ez viszonylag egyértelműnek látszik, de nehogy elcsesszem valamikor - most már nem fogom)
Köszi a választ ismét!(#1422) Karma: neked is köszi! Ez mitől lesz egyébként "fésűs adatszerkezet"?
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Értem, köszi!
(#1428) 3man: még C++-hoz nem konyítok, de csak érdeklődésképp kérdezem, hogy miért nem egyszerűbb a túlindexelés elkerülésére osztály létrehozása helyett mindig "kényszerűen" átadni a tömbméretet is mondjuk függvénynek, vagy végigszaladni a tömbelemeken a lezáró nulláig, hogy megtudjuk, hány eleme van, és utána ezzel dolgozzunk?
Sk8erPeter
-
Sk8erPeter
nagyúr
Abból indultam ki, hogy nekünk azt erőltették, hogy ha akár statikus tömbökkel is dolgozunk (persze, nem a pointertömbökre gondoltam ), és azokat adjuk át a függvényeknek, akkor lehetőleg adjuk át a méretét is, mert így könnyebb kezelni (pl. ha iterátorral rohangászol végig a tömbelemeken, akkor mittomén, for ciklusban a feltétel lehet az, hogy i<meret, stb. - persze úgy is lehetne, hogy tomb[i] != '\0' ), nem kell a függvényen belül is sizeof()-fal p×csölni, és így esetleg pl. main()-ben mondjuk elég egyszer sizeof-olni (talán ez gyorsaság szempontjából is érdekes lehet, fene tudja). Ez nem lehet elfogadható szempont? A 2-3. pont mondjuk teljesen igaz.
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Nem, BME-n kifejezetten és erősen tiltják a goto utasítás használatát! Ezt a tanárok "halálfejes hibának" nevezik, ha ilyet teszel a ZH-dba, akkor rárajzolnak egy halálfejet (egyébként tényleg rárajzolják, ZH-megtekintésnél pár papíron láttam is ), és arra a feladatra - akármilyen szép is a többi része - eleve 0 pontot adnak. (olyan esetekben is kapsz ilyet, ha nem szabadítod fel a dinamikusan lefoglalt memóriát, amikor kellene, vagy inicializálatlan változóval dolgozol, stb.)
Elképzelhető, hogy régebben volt olyan tanár, akinek nem verték a fejébe, hogy goto-t nem használunk, de szerintem most már selejtezik az ilyeneket.
Pascalt nem is tudom, tanítanak-e még egyáltalán... Villamosmérnöki és Informatikai Karon biztos, hogy nem, ott C-vel kezdenek. De én úgy tudom, hogy még az építészek is alap C-t tanulnak. Pascalról mostanában egyáltalán nem hallottam, hogy valahol tanítanának még BME-n.A lényegre térve nem igazán értem, miért olyan nagyon hibás az elképzelés, hogy kívülről adjuk meg a függvénynek a méretet. Jahh, de az utolsó bekezdésben azt írod, hogy végül is van elfogadható érvelés erre is: akkor tehát mégis jó úgy?
Az "iterátor" szót lehet, hogy rosszul használtam, de arra az elemre gondoltam, amivel bejárod a tömböt.A goto utasításra visszatérve: tudom, hogy a használata egy undormány-hányadék hiba, és soha nem is tettem, mert direkt meg se néztem, hogy kell azt egyáltalán De érdekelne, konkrétan milyen szempontból oltári baromság a goto használata. Úgy emlékszem, hogy futásidejű összeomlásokat eredményezhet, meg hasonlókat, de a pontos érveket már elfelejtettem.
(#1442) 3man: értem, köszi. Tehát akkor érdemes mégis kézzel átadni (ha sima C-ben programozol) a tömbméretet, ugye?
(#1446) bama: most mi a kérdés? Egyébként ha ez egy prímtesztelő függvény, akkor szvsz elég furcsa, minek kell 4-gyel shiftelni a számot...
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
dabadab, Karma, kovsol: köszi a válaszokat!
Nálunk mondjuk a gyorsrendezés algoritmusánál sem használtak goto-t. Úgyhogy asszem maradok továbbra is annál, hogy NEM használok goto-t, amíg nem jön elő olyan helyzet, hogy mindenképp arra lesz szükségem - amit meg kétlek, hogy előállna.KISS filozófia, ez tetszik
A cikket pedig majd elolvasom, ha lesz időm, köszi.(#1451) grabber: miért használsz mindenhol exit(0)-t? Miért nem return 0; vagy return 1-et? Mi ez az exit-mánia?
Sk8erPeter
-
Sk8erPeter
nagyúr
válasz dabadab #1455 üzenetére
"Mert kezdő "
Mondjuk így se igazán értem, mert nálunk kezdetektől fogva azt verték a fejünkbe, hogy return. Sőt, azért is szóltak, hogy külön függvény se lépjen ki hasonló módon, idézek:
"Függvény ne hívjon kilépéssel, hasonlókkal kapcsolatos dolgokat, mert a felsőbb szintű kódot ez meglepetéssel fogja érinteni (fájlok lezárása, takarítás elmarad). Ha szükséges, akkor legyen a programnak valami fatal_error() függvénye, azt hívjuk."
(Forrás: http://infoc.eet.bme.hu/gyakorlatok/)"Az exit() használata tulajdonképpen ugyanannyira problémás, mint a goto, ugyanazon okok miatt."
Akkor ezt most megjegyeztem, hogy az exit() függvényt se fogom sosem használni.(#1459) Karma: titeket is Poppe tanított? Első alkalommal (tavaly) minket is, de nekem annyira megtetszett a tantárgy, hogy felvettem idén is. Ugyebár nincs kereszt progból... és Poppe órái szvsz olyan szinten unalmasak voltak, hogy egyáltalán nem keltette fel az érdeklődésem a programozás iránt (előtte középsuliban persze egyáltalán nem volt programozás), és ezzel még kb. az évfolyam fele így volt. Aztán amikor nyáron elkezdtem a PHP-vel foglalkozni, akkor rájöttem, hogy a programozás jó dolog. És most már ráfeküdtem a C-re is, aláírás megvan, már csak a vizsgára kell gyakorolni, mint egy elmebeteg.
[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
"a függvényeknek csak egyetlen returnje legyen"
Na jó, de mondjuk egy prímtesztelő függvénynél pl. azt szeretnénk, hogy 1-gyel térjen vissza, ha egy szám prím, 0-val, ha nem az, hát ott kapásból a 0-nál vagy 1-nél 0-val kell, hogy visszatérjen, tehát ott már lesz egy return 0; , ha viszont az jött ki, hogy a szám prím, akkor ugye return 1;. És akkor már két return van a függvényben Vagy nem így értetted? Mert ez szerintem még bőven átlátható, és erre az átláthatóság nem jó érv szerintem...Ezek szerint annyira neked sem jöttek be az órái. Az mondjuk valóban nagy előny, ha előtte jól toltad legalább Pascalban, mert akkor csak át kell szokni a másik nyelv szintaktikájára. Hát nekem nem volt túl egyszerű a 0-ról megtanulni programozni, ilyen tanárokkal... Mondjuk most kifogtunk egy nagyon jó gyakvezt (Lengyel László, hátha ismered), aki végre úgy magyaráz, hogy az követhető, és egyáltalán nem unalmas, ráadásul bevon mindenkit a feladatmegoldásba, nem úgy ülsz ott órán, hogy mikor lesz már végre vége a gyaknak. Az nagy előny.
Sk8erPeter
-
Sk8erPeter
nagyúr
Dehát ez már kapásból nem jó, ha 0-t vagy 1-et adsz be a függvénynek, hiszen ezekre is azt fogja mondani a függvény, hogy prím, és nem tételezheted fel, hogy nem fog a felhasználó beadni 0-t vagy 1-et... És ugye a 0 vagy az 1 nagyon nem prímszám...
Pontosan ezen csodálkoztam a Prog honlapján fenn lévő MINTAmegoldásoknál, hogy rossz a prímtesztelő függvény... ---> [link]
Itt így csinálták meg a függvényt:
int prime(int a){
int i,max=(int)(sqrt(a)+1);
for(i=2;i<a;i++)if(a%i==0)return 0;
return 1;
}
És ez is rohadtul mindig 1-et fog visszaadni eredményül, ha 0 vagy 1 a számunk... Ja, és még egyet igencsak elbaszarintottak benne: létrehozták a max változót, de sehol sem használják fel...
Tőlünk ugye elvárják a hibátlan megoldásokat, de ők a MINTAként feltett ZH-ban két ilyen üvöltő hibát elkövethetnek. Kicsit gáz.[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Gondolkoztam még ezen, hogy miért lesz átláthatóbb a függvény, ha egyetlen return van, de nem látom be, miért is lenne ez jó. Szerintem azonnal áttekinthetővé válik a dolog, hogy ha valami feltétel, amire várunk, már az elején teljesül, akkor ne is folytassa tovább a vizsgálgatást, ez gondolom akár gyorsaság szempontjából sem lehet elhanyagolható. Jester01-gyel értek egyet, sokkal kevésbé lesz átlátható a függvény a sok if-else elágazás miatt. A tanított anyagokban is mindenhol akár több return utasítás is van bizonyos feltételek teljesülése esetén.
De most tényleg, miért lenne baj, ha több return van?
___________________
"Auto-pointereknél nem para a felszabadítás több return esetén, de pl. CleanupStacknél sokkal bonyolultabb a memóriát karban tartani."
Ebből sokat nem értettem, ezt röviden el tudod magyarázni?Sk8erPeter
-
Sk8erPeter
nagyúr
Köszi a magyarázatot, ezt mondjuk biztos jobban meg fogom érteni, amikor a C++-t tanulom.
Te egyébként hogyan tanultad meg ilyen alaposan a nyelve(ke)t? Mert én mondjuk attól függetlenül, hogy mondjuk meg tudok oldani pár programot (ha meg tudok ), a hátterével ilyen szépen nem vagyok tisztában, csak úgy nagyjából... Amúgy programozóként is dolgozol, hogy ilyen frissen élnek az emlékek? (ha nem baj, hogy kérdezem) Persze gondolom az évek meg a tapasztalat... Ja, de most jut eszembe, hogy írtad, hogy "Tudom hogy VIK-en mi a helyzet, én is informatikus-hallgató vagyok (félig)", akkor még mindig BME-s vagy? Hogy érted, hogy félig informatikus hallgató?[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Mondjuk azt megértem, hogy meló mellett már rohadtul nincs kedved még este leülni tanulni, amikor nap végére úgy érzed magad, mint akinek kiszívták az agyát... (Legalábbis amikor én sokat melóztam egymás után (mondjuk igaz, a melónak köze nem volt az informatikához), akkor kábé ilyen voltam nap végére... )
Egyelőre úgy vagyok vele, hogy elvégzem a BSc-t, és mindenképp kipróbálom magam a munkaerőpiacon, aztán majd meglátom, kell-e az MSc, vagy sem. Vagy a legjobb lenne, ha munkáltató támogatná majd egy kis ott töltött idő után a továbbtanulásomatAmúgy visszatérve C-re, nekem az a bajom a "dolgok mögé nézéssel", hogy egyszerűen nincs rá időm a rengeteg tantárgy mellett. Tök szívesen gyakorolnék is rengeteget programozásból, meg foglalkoznék még sok egyébbel, de valahogy képtelen vagyok BME mellett beosztani az időmet úgy, hogy ALAPOSAN, és ne csak gyorsan, felületesen tanuljak meg mindent... Ilyen szempontból igencsak hátrányos szerintem ez a tempó, amit itt diktálnak. Persze a májereknek, akiknek a tudást már középsuliban a fejükbe verték, jóval könnyebb dolga van. Nekem a középsuli konkrétan a szak szempontjából szart se ért (humán tagozat ).
Sk8erPeter
-
Sk8erPeter
nagyúr
"Egyébként mi értelme van az MScnek?" Pont ezért mondtam, hogy előbb elvégzem az alapképzést, elkezdek melózni, és majd meglátom, kell-e az egyáltalán. Közel sem biztos, hogy szükség lesz rá, mivel ez ismét csak egy papír, amivel kitörölheted a seggedet, ha nincs mögötte releváns háttértudás. Ugyanez igaz a BSc-s alapképzésre is. Felsőbbévesek mondják mindig, hogy az egyetemen lényegében semmit nem lehet megtanulni, aminek gyakorlati hasznát veszed, legfeljebb az elméleti hátteret adja meg, de ahol igazán fejlődni lehet, azok a szakkörök, meg különböző szakprogramok, amiken fakultatív módon részt lehet venni egyetemi órák helyett/után, de persze megint felmerül a probléma, hogy ki a francnak van mindkettőre energiája.
Sk8erPeter
-
Sk8erPeter
nagyúr
"egyébként nem értem hogy vállalsz te php-t, ha egy ilyen feladat nem megy magadtól"
Pont ugyanezen voltam kiakadva, PHP topicban ennél durvább alap kérdést tett fel (persze szokás szerint arra is b@szott válaszolni )... Érdekes, amikor ennyire alapdolgokon elakadtam, eszem ágába nem jutott volna vállalni komolyabb munkát PHP-ben... Na jó, flame off[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
Na, most eszembe jutott, hogy ha már volt szó róla, gyakorlásként gyorsan összecsapom az arab számból római számba átváltó programot, bocs, ha nem túl szép megoldás, de most kissé késő van, és túl gyorsan csináltam, így szebbre most nem futotta. Holnap még úgyis eszembe fog jutni ezer dolog, amit sokkal szebben lehetett volna csinálni, de Ti is szólhattok ezért. (A méretmegadásoknál nem szarakodtam túl sokat, egyből a végső sztringnek 100-at adtam, az biztos elég.)
// Arab számból római szám
#include <stdio.h>
#include <string.h> /* a strcat miatt */
int main(){
int arab, temp, szamjegy;
char romai[100];
char egyesek[][10] = {"I","II","III","IV","V","VI","VII","VIII","IX"};
char tizesek[][10] = {"X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
char szazasok[][10] = {"C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
char ezresek[][4] = {"M","MM","MMM"};
printf("Az arab szam: ");
scanf("%d",&arab);
if(arab<4000)
{
temp=arab;
szamjegy=0;
while(temp>0)
{
temp/=10;
szamjegy++;
}
if(szamjegy==4)
{
strcat(romai,ezresek[arab/1000-1]);
arab-=(arab/1000)*1000;
szamjegy--;
}
if(szamjegy==3)
{
strcat(romai,szazasok[arab/100-1]);
arab-=(arab/100)*100;
szamjegy--;
}
if(szamjegy==2)
{
strcat(romai,tizesek[arab/10-1]);
arab-=(arab/10)*10;
szamjegy--;
}
if(szamjegy==1)
{
strcat(romai,egyesek[arab-1]);
}
printf("A romai szam: %s\n", romai);
}
else printf("\n4000 alatti szamot adj meg!");
getchar();
}Sk8erPeter
-
Sk8erPeter
nagyúr
válasz Jester01 #1539 üzenetére
Mindegyikben igazad van. Késő volt Köszi, hogy szóltál!
A bemeneti adatok ellenőrizgetésével azért nem foglalkoztam, mert most csak a program megírására helyeztem a hangsúlyt, persze ettől függetlenül szükséges.
Amúgy ahogy teszteltem, jól működik a progi, azt csinálja, amit kéne."Egyébiránt pár oldallal korábban már volt itt ilyen kód "
Most rákerestem, erre gondoltál? Akkor már nem tömörebb (persze nem tökéletes) az enyém?Sk8erPeter
-
Sk8erPeter
nagyúr
Ezt nem értem, ez micsoda?
{"", "M","MM","MMM", "/(IV)", "/(V)", "/(VI)", "/(VII)", "/(VIII)", "/(IX)"}
A végén mik ezek a "/(IV)", "/(V)",, stb.?
Vagy ezeket csak azért tetted oda, hogy "kitöltsék" a tömböt?"még a tízezres/százezreseknek is van római megfelelője"
És az micsoda? Tényleg érdekelne.Egyébként tényleg szebb, tömörebb.
Amúgy minket a pow függvénytől igencsak óva intettek, a következő indokkal:
[link]
"Az se érjen meglepetésként senkit, hogy ha egész szám egész hatványát pow függvénnyel számolja ki, akkor egy halálfejet talál a feladata mellett. 2 az n-ediken-t így számoljuk: ketto_az_n_ediken=1<<n;, nem pedig hatványozással! Ha nem kettő hatványát számoljuk, azt meg lehet oldani szorzással. A pow függvény double értéket ad vissza, ami akkor is lehet pontatlan, ha egész számokat hatványozunk, mert a pow az exp és a log függvények segítségével számol hatványt. Így előfordulhat, hogy ha pl. 8 lenne az eredmény, 7.99999-et ad, és ez int-ként használva bizony csak 7."
___________________________________________________________________(#1545) Jester01: ha az #include <stdlib.h> sort hozzáadom, CodeBlocks akkor is fordítási hibát dob. A helyiertek változónak milyen típust kellene adni (hogy ne dobjon cannot convert `char* (*)[10]' to ... kezdetű hibát)?
fputs((*helyiertek)[d.quot], stdout); sorra pedig ezt a hibát adja:
invalid type argument of `unary *',
persze ha változtatok a típusdeklaráción, akkor más jellegű hibát ad.Amúgy még ez a rész számomra nem tiszta:
helyiertek = romai + 3,
a romai változó egy karaktertömb, ami tárolja a római számokat, most annak a 0. eleméhez miért adsz hozzá 3-at?[ Szerkesztve ]
Sk8erPeter
-
Sk8erPeter
nagyúr
argc, argv:
Vegyük azt, hogy a main függvényednek így néz ki a fejléce:
int main(int argc, char *argv[])
{
/* blabla */
}Itt az argc azt határozza meg, hány paramétered van+1. Azért +1, mert ebben a számban benne van magának a futtatandó programodnak a neve is (pl. akarmi.exe a futtatandó fájlod; de NEM maga a programnév, mint string van benne, hanem csak plusz egy "paraméter").
Az argv pedig sztringre mutató mutatók tömbje, azért char * argv[] (ez ekvivalens ezzel: char **argv); ez megmondja, hány string szerepel a parancssorban. A 0. index maga a program neve (a korábban említett akarmi.exe), mint string, az 1. index (és az azt követő indexek) pedig az(ok), ami(ke)t a fájl neve mögé írtál: akarmi.exe parameter1 (parameter2 parameter3...)Eszerint ellenőrizgethetsz: pl. azt is csekkolhatod ilyen módon, hogy a program neve után pontosan annyi paramétert adtak-e meg, mint amennyit elvártál, és/vagy a paraméter(ek) neve megegyezik-e valamilyen értékkel, amitől függően hajtasz végre mondjuk egy műveletet, stb...
A Te esetedben ("min és max érték között kikeresi és listázza a primszámokat") pl. így hívod meg a programot a parancssorból:
akarmi.exe 10 50Még az elején include-old az stdlib-et, és akkor átalakíthatod a paraméterként kapott sztringet egész számmá az atoi függvénnyel:
#include <stdlib.h>Végezz egy ellenőrzést, hogy a paraméterek száma nem kisebb-e a szükségesnél (kell a min és a max is):
if(argc<3)
/* hibaüzenetek, kilépés hibával */;A korábban int-ként deklarált min és max változóknak pedig add át a megfelelő értékeket:
min = atoi(argv[1]);
max = atoi(argv[2]);Ezt követően pedig végezd el a prímtesztelést.
Összefoglalva (a konkrét kiegészítés már a Te dolgod):
#include <stdio.h>
#include <stdlib.h>int main(int argc, char *argv[])
{
int min, max;
if(argc<3)
/* hibaüzenetek, kilépés hibával */;
min = atoi(argv[1]);
max = atoi(argv[2]);
/* ide jöhet a prímtesztelés */
}Sk8erPeter
Új hozzászólás Aktív témák
● olvasd el a téma összefoglalót!
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!