Új hozzászólás Aktív témák
-
maestro87
őstag
válasz buherton #5650 üzenetére
Ezt így nem fordítja le. Szintaktikai hiba, nincs azonosító a deklarációban stb.
Pontosabban az én kódom így néz ki lefordítva erre a példára:header fájlban:
typedef struct
{
int date;
int month;
int year;
} date;
typedef struct
{
char ename[20];
int ssn;
float salary;
date doj[3];
} Employee;
Employee emp;A main függvénybe írva ezt, nem működik:
emp.date[]=
{
{,,},
{,,},
{,,}
};A pointer-est hogy gondoltad?
[ Szerkesztve ]
-
buherton
őstag
válasz maestro87 #5651 üzenetére
Így próbáld meg
mp.doj[]=
{
{,,},
{,,},
{,,}
};Valahogy így:
typedef struct
{
int date;
int month;
int year;
} date;
typedef struct
{
char ename[20];
int ssn;
float salary;
date (*doj)[3];
} Employee;
date foo = ...;
Employee emp;
emp.doj[0] = &foo;Nem próbáltam lefordítani.
tely, baly, fojó, mennyél, mingyárt, telyföl, tolyás, malyd, kapú, egyenlőre, ejsd, jáccani, ahoz, fúj, hüje, muszály, alat, álok, lasan, fojtatás, ál, fontós, költsön, eggyüt, lyob (jobb?), mek, mongyak, milyért - !!! Tanúlyunk már meghejjessen irni... !!!
-
maestro87
őstag
válasz buherton #5653 üzenetére
Nem tudom működésre bírni.
Eddig csak úgy ment, hogy a fő struktúrán kívül is deklaráltam illetve extern taggal kivittem másik fájlba, de akkor szerintem az nem ugyanaz a változó volt mint a struktúrában lévő. Egyébként eeprom-ba íráshoz kellene, hogy a struktúrában lévő elemeket egy függvényhívással be tudjam írni, ne kelljen minden elemnél külön meghívni az eeprom-ba író függvényt. -
dobragab
addikt
válasz maestro87 #5654 üzenetére
emp.doj
egy három elemű tömb, amit inicializálni csak akkor tudsz, amikor létrehozod azemp
változót.Employee emp = {
"John Sample", 0, 2500,
{1, 1, 1970},
{1, 1, 1970},
{1, 1, 1970}
};Külön inicializálni már nem tudod, csak értéket adhatsz neki. Illetve nem is neki, mert C-ben nincs tömbök közötti értékadás, hanem az elemeinek, mégpedig egy létező dátumot:
date date0 = {1, 1, 1970};
Ezután adhatsz értéket az
emp.doj
elemeinek.emp.doj[0] = date0;
emp.doj[1] = date0;
emp.doj[2] = date0;Itt segítségedre lehet a C99 compound literal:
emp.doj[0] = (date){1, 1, 1970};
Ha kinullázni szeretnéd egy struktúra adattagjait, akkor ez nem szabványos, normális fordító nem eszi meg:
date date0 = {};
Ez viszont igen:
date date0 = {0};
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
EQMontoya
veterán
Elég baba lett ez az új formázás.
Same rules apply!
-
dobragab
addikt
Beszélgessünk a
goto
-ról!Általános vélemény a
goto
-ról, hogy kerülni kell, mint egyszeri kockának a napfényt, különben lesül a képünk. Sokan viszont azt mondják, hogy agoto
használata bizonyos esetekben egyszerűsíti és átláthatóbbá teszi a kódot, és egyáltalán nem lesz tőle spagettikód, ha ésszel használjuk. Ugyanúgy, ahogy acontinue
és abreak
is. Utóbbinál szerencsétlen, hogy ciklusoknál ésswitch
-nél tök mást jelent, úgyhogy az szerintem is a gonosztól származik.Nekem erről egyértelmű a véleményem, de előbb halljuk, mit mondtok ti
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
ToMmY_hun
senior tag
válasz dobragab #5657 üzenetére
Nekem az a tapasztalatom, hogy a spagetti kód nem a
goto
miatt lesz olyan, amilyen. A megfelelő szépérzékkel és odafigyeléssel bizonyos esetekben valóban szebb és átláthatóbb kódot lehet írni vele, de amiatt, mert nagyon nagy odafigyelést igényel, a használata nem célszerű. Viszont vannak olyan programnyelvek, amelyeknél agoto
megkerülhetetlen. Ilyen például a VBA (Visual Basic for Applications), amelyben a hibakezeléshez biztosan, de ha jól emlékszem bizonyos esetekben acontinue
helyett is csakgoto
használható. Egyébként egy jól formázott és strukturált kódnál nem hiszem hogy nagy jelentősége lenne a kérdésnek. Nem szokás több száz soros függvényeket írni, sokkal célszerűbb kisebb darabokra vágni azokat, hiszen így sokkal átláthatóbb és nem utolsó sorban könnyen tesztelhető kód lesz az eredmény.C programmers never die, they are just cast into void.
-
maestro87
őstag
-
maestro87
őstag
válasz dobragab #5657 üzenetére
Én ugyan C-ben még nem használtam
goto
utasítást, de sosem értettem, hogy miért félnek tőle az emberek. Még talán assembly-ben is megkérdőjelezik a használatát, pedig ott tudtommal más megoldás nem nagyon van ciklusok létrehozására.Viszont a
continue
utasítást valaki eltudná magyarázni, mert ebből nem nagyon értem. Ugyanaz lesz a kimenetcontinue
-val és nélküle is, akkor meg minek bele? -
ToMmY_hun
senior tag
válasz maestro87 #5661 üzenetére
Nem ugyanaz, mert a 15-öt nem printeli ki,
continue
nélkül pedig megtenné. Annyi a lényege, hogy ciklusmagban lévőcontinue
utasítás hatására a ciklustörzsből azonnal visszaugrik a végrehajtás a ciklus fejére.[ Szerkesztve ]
C programmers never die, they are just cast into void.
-
maestro87
őstag
válasz ToMmY_hun #5662 üzenetére
Lehet online futtatni a kódot és ha kitörlöd a
continue
-t ugyanaz lesz a kimenet. Aza = a + 1
miatt nem printeli ki a 15-öt, nem acontinue
miatt.Értem, tehát akkor a
continue
után elölről kezdődik a ciklus.
Akkor viszont ez a helyes példa kód a használatára:#include <stdio.h>
int main ()
{
/* local variable definition */
int a = 10;
/* do loop execution */
do
{
a++;
if( a == 15)
{
/* skip the iteration */
continue;
}
printf("value of a: %d\n", a);
} while( a < 20 );
return 0;
}Kimenetek:
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19
value of a: 20continue
nélkül itt tényleg kiírja a 15-öt is.Már van is egy ötletem hol tudnám ezt használni a jelenlegi kódom optimalizálására. Köszi.
-
ToMmY_hun
senior tag
válasz maestro87 #5663 üzenetére
"Lehet online futtatni a kódot és ha kitörlöd a continue-t ugyanaz lesz a kimenet."
Ahogy nézem nem fordítja újra a kódot az "Execute" hatására. Kezdőként inkább saját gépen játszadozz, abból is sok hasznos tapasztalatot lehet gyűjteni.
[ Szerkesztve ]
C programmers never die, they are just cast into void.
-
maestro87
őstag
válasz ToMmY_hun #5664 üzenetére
Nem vagyok már annyira kezdő, kb 5 éve hobbi szinten programozgatok mikrokontrollereket.
Nekem újra fordítja (már amikor bírja a szerverük).
De a kedvedért most gyorsan lefuttattam CodeBlocks-ban is, és az van amit mondtam, semmivel sem másabb a kimenetcontinue
nélkül. Szerintem nézd át azt a kódot még egyszer.
Acontinue
itt csak annyit csinál, hogy a feltételt még egyszer leellenőrzi a hatására ami már nem fog teljesülni a feltételben lévőa = a + 1
miatt. Tehát itt semmi szerepét nem látom, ellenben az én példámmal ahol azif
előtt van értékadó utasítás is.[ Szerkesztve ]
-
EQMontoya
veterán
válasz maestro87 #5665 üzenetére
void print_primes(int * primes, int lenght)
{
for(int i = 0; i < lenght; ++i)
{
if(i<2) continue;
if(is_prime(i)) printf("%d\n", i);
}
}Így a paraméterként kapott tömb negatív elemeire le sem fut a prímtesztelés, mert ugye nincs is értelme, lehet, hogy felkészítve sincs rá.
Teccikéteni?Hú, de nehezen ment c++ nélkül
[ Szerkesztve ]
Same rules apply!
-
dobragab
addikt
válasz EQMontoya #5667 üzenetére
Jaja, nehéz leszokni róla, gondolom, itt is hiányzott az std::vector, range based for, std::ostream
Na meg szerintem nem is ezt akartad írni
void print_primes(int * primes, int lenght)
{
for(int i = 0; i < lenght; ++i)
{
if(primes[i]<2) continue;
if(is_prime(primes[i])) printf("%d\n", primes[i]);
}
}[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
maestro87
őstag
válasz EQMontoya #5667 üzenetére
Én az ilyeneket mindig egy
++i
-vel oldottam meg. Amíg nem találok (csinálok) olyan példát, amiben tényleg hasznos lesz acontinue
(értsd. lerövidíti a kódot), addig csak olyan felvágós utasításként fogom kezelni. Felvágós, mert szerintem kevesebben értik vagy később tanulják meg a használatát (mint most én is) és sokszor feleslegesen használják, mint pl. most te is a++i
helyett.
Ráadásul a++i
szerintem kevesebb utasításból áll, mint acontinue
, mármint asm-re lefordítva.
Bár lehet mindjárt visszavonom az egészet, ahogy jobban nézegetem a kódodat.
Vissza is vontam, mertcontinue
nélkül meghívná a függvényt a negatív számokra is, azaz kimaradna a tesztelés.A C++-t is elkezdtem már tanulgatni, de még nem jöttem rá, hogy mitől jobb a C-nél, mit lehet C++-ban megoldani amit C-ben nem, vagy csak jóval bonyolultabban...
[ Szerkesztve ]
-
dobragab
addikt
válasz maestro87 #5671 üzenetére
++i
tök mást csinál.continue
igazából arra való, hogy ne legyen annyi egymásba ágyazás. A fenti kód így írható át:void print_primes(int * primes, int lenght)
{
for(int i = 0; i < lenght; ++i)
{
if(primes[i]>=2)
{
/* és egy rakás random utasítás */
if(is_prime(primes[i]))
printf("%d\n", primes[i]);
/* meg itt is sok utasítás */
}
}
}A bitb*szogatás nem az én területem, de tudomásom szerint a
continue
asm-ben 1 db jump lesz, ugyanúgy, ahogy azif
is.C++ C-hez képest nagyon sok mindent tud, amit neked első körben érdemes megnézned, az az objektumorientált tervezés.
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
ToMmY_hun
senior tag
válasz maestro87 #5671 üzenetére
Kereső algoritmusokban a keresett elem megtalálásakor hasznos lehet a
continue
. Olyankor is, amikor előfeltételként vizsgálod a ciklusmagban egy számításigényes művelet elvégzésének szükségességét. (Erre írt példát EQMontoya).A mikrokontrollerek programozásához pedig nagyon kevés, speciális esetben van szükség C++ használatra. Komplexebb problémák megoldása során találkozhatsz vele, úgy mint például orvostechnikai berendezések, robotika stb. A "mitől job" kifejezés pedig nem a legcélszerűbb megfogalmazási módja a kérdésnek, nem jobb és nem is rosszabb, szimplán más a létezésének célja.
C programmers never die, they are just cast into void.
-
EQMontoya
veterán
válasz maestro87 #5671 üzenetére
Van, amikor nincs ++i.
Pl, c++.ban:for(const auto& i : my_list) { ... }
A continue-ban azt szeretjük, hogy az minden nyelven ugyanúgy működik.
És hidd el, azt mindenki érti, ha pedig a ciklus közepén a ciklusváltozóhoz nyúlsz, az:
-Sokkal kevéssé érthető
-Jobb helyen arconvágnak érte, mert nagyon veszélyes.Pl.
for(int i = 0; i < valami ; ++i)
{
if(zöld(tömb[i]) && pöttyös(tömb[i])) continue;
if(sarga(tömb[i]) && !csikos(tömb[i])) continue;
//do something here...
}Sok sikert ++i-vel.
Same rules apply!
-
ToMmY_hun
senior tag
Viszont ha már szóba jött a
continue
akkor megkérdezem, hogy mit gondoltok areturn
kifejezés többszöri felhasználásáról egy függvényen belül? Sokan ezt is elítélik, de én előszeretettel térek vissza hibát jelző értékkel argumentum ellenőrzés után kivételkezelést nem támogató függvények esetén.A "no push friday" mozgalmat pedig támogatom Mennyivel nyugisabb lenne az utolsó munkanap.
maestro87 Így már
jobbanjól hangzik, hajrá-hajrá![ Szerkesztve ]
C programmers never die, they are just cast into void.
-
maestro87
őstag
válasz dobragab #5672 üzenetére
Igen, közben rájöttem, hogy két egymásba ágyazott
if
(vagy egyif
-ben két feltétel) többet ehet memóriában is.Ha struktúrákat használok az nem nevezhető már objektumorientált programozásnak? Nekem egyszer valaki azt mondta a forráskódomra, hogy olyan mintha C++-ban lenne, pedig akkor még nem is nagyon használtam struktúrákat sem.
(#5673) ToMmY_hun: C++-t Visual Studio-ban szeretném majd használni, azért tanulgatom, nem MCU-hoz.
(#5674) EQMontoya: Sok lúd disznót győz. Meggyőztetek.
(#5675) ToMmY_hun: Már azzal is baj van?
[ Szerkesztve ]
-
dobragab
addikt
válasz maestro87 #5676 üzenetére
C-ben is lehet OO kódot írni, csak nehezebb, öröklést csinálni pedig undorító. Az OOP elveket viszont explicite nem támogatja a C, azaz egy C-s "osztályt" bármikor lehet szarul használni, C++-ban többé-kevésbé a használójára rá lehet kényszeríteni a "jó" használatot. Legalábbis dióhéjban ennyi.
(#5675) ToMmY_hun
C++-ban szerintem gátlástalanul lehet
return
-ölni akárhonnan. C-ben vigyázni kell, mert lehet, hogy pl. hibajelzésre használt visszatérés előtt fel kéne szabadítani valami erőforrásokat, és nem történik meg automatikusan. Erre (C-s kivételkezelés) majd fogok szülni egy másik hsz-t, még agoto
kapcsán.Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
alapz@j
tag
-
EQMontoya
veterán
válasz dobragab #5679 üzenetére
Linus is csak a hírnevéből él, meg az odaszólogatós leveleiből, amúgy meg faszságot beszél régóta.
Konkrétan az egyik projekten újraírtunk pár C kódot C++-ban, és azon felül, hogy fele annyi kód lett, konkrétan gyorsabb lett, mert jobban tudta optimalizálni a fordító a több rendelkezésre álló információ miatt.
Szóval Torwalds a múltban él és a múltat nézi, így hát seggel megy a jövőbe.[ Szerkesztve ]
Same rules apply!
-
stepboy
csendes tag
válasz dobragab #5550 üzenetére
sziasztok,
Ezt a példát nem értem.
int temp = 1;
evil_api_function_call(fp, ptr, &temp);C99-ben tudod lokális változónak is képezni a "címét" egy trükkel. Pontosabban: tudsz compound literal segítségével temp tömböt létrehozni egy elemmel, ami viszont már konvertálódik pointerre.
Tehát azt akarod mondani, hogy lokális változó címét nem lehet paraméterként átadni függvényhíváskor?
-
dobragab
addikt
válasz maestro87 #5683 üzenetére
"Összetett literális".
Alaptípusokra, mint amilyen az
int
, azunsigned long
, adouble
, tudsz a programkódba beágyazott konstansokat írni. Pl:0
,25UL
,0x0badc0de
,4.6f
,0.001
. Speciális literal még a string literal, amit így ismersz:"Hello world!\n"
.Struktúrákra, union-okra, tömbökre C89-ben ilyet csak inicializálásnál tudsz:
struct Pont p = {5, 12};
int arr[] = {1, 2, 3, 5, 8, 13, 21};
p = {12; -5}; // <- ERROR
p.x = 12;
p.y = -5; // <- macerásC99 behoz ezzel kapcsolatban két feature-t, a compound literal és a designated initializer.
Compound literal
Arra való, hogy a programkódban ne csak ilyen alaptípusokat, hanem összetett típusokat is meg lehessen adni egyetlen kifejezésben. Ehhez ugyanaz a szintaxis, mint az inicializálásnál, konyhanyelven annyi különbséggel, hogy a kapcsos zárójel tartalmát az adott típusra kell "cast-olni".
p = (struct Pont){12; -5};
struct Pont Pont_tukroz(struct Pont p)
{
return (struct Pont){p.y, -p.x};
}
struct Pont q = Pont_tukroz((struct Pont){10, 13});printf("%p\n", (int[]){1});
double osszeg = double_osszeg((double[]){1.0, 2.718, M_PI}, 3);Ezek a "változók" temporális objektumok, nincs nevük, nem képezheted a címét, mint ahogy ez is értelmetlen:
printf("%p", &1);
Élettartamuk a blokk végéig tart (bezáró
}
), nem úgy, mint C++-ban, ahol a pontosvesszőig (jó, nem pont így van a szabványban, de megközelítőleg pontos).Designated initializer
C-ben a struktúrák adattagjait közvetlenül érjük el, szinte mindig név szerint.
void Pont_kiir(struct Pont p)
{
printf("(%d, %d)", p.x, p.y);
}Kivéve: inicializálásnál.
struct Pont p = {5, 12};
Ez egyértelműnek tűnik, az
x
koordináta 5 lesz, azy
pedig 12. De mi történik, ha valami bunkó így definiálta astruct Pont
-ot?struct Pont
{
int y;
int x;
}Ilyenkor minden működik tovább, kivéve az inicializálást, akkor pont fordítva történnek a dolgok, mint ahogy az ember elképzelte. Ezért vezették be, hogy a struktúrákat inicializálni is lehessen név szerint:
struct Pont p = {.x = 5, .y = 12};
Természetesen compound literal-lal együtt is használható.
p = {.x = 5, .y = 12};
És nem csak struktúrákra, tömbökre is.
int arr[] = {[0] = 8, [1] = 13, [2] = 21};
Sőt, vegyesen is.
haromszog_rajzol((struct Pont[])
{
[0] = {.x = 12, .y = 5},
[1] = {.x = -12, .y = 5},
[2] = {.x = 0, .y = 0}
});Jó eséllyel ezeket a te fordítód is támogatja, ha GCC vagy Clang, csak -std=c99 kell neki. MSVC a C99 cuccokat a 2015-ös verzió óta zömmel tudja...
EQMontoya: bocsi a magyar változónevek miatt
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
dobragab
addikt
válasz stepboy #5685 üzenetére
De, ezzel így semmi baj nincs. Csak ez azért ciki, mert a
temp
változó csakis azért létezik, hogy a függvénynek cím szerint oda tudd adni. Másra nem kell, ettől rondább lesz a kód.Így már szebb (szerintem):
evil_api_function_call(fp, ptr, (int[]){1});
Mert ugye ezt nem írhatod le.
evil_api_function_call(fp, ptr, &1);
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
nagyúr
válasz alapz@j #5690 üzenetére
Az egyik elv az, hogy csak akkor valtoztatnak meg szabalyokat/mintakat, amikor arra kifejezetten jo ok van. Tehat ha idaig jo volt az ANSI, es az ujabb feladatokat is meg lehet oldani igy, akkor nem tesznek a fejlesztokre extra mentalis terhet azzal, hogy varialnak.
A C++ (Scala, etc.) egyik fo problemaja, hogy nagyon sok modszerrel meg lehet csinalni ugyanazt. C++-ban irhatsz proceduralis, OO, funkcionalis, etc. programot, ami egyreszt meno+kenyelmes, masreszt sokkal nehezebb megakadalyozni, hogy egy nagyobb projektnel divergaljon a stilus/megkozelitest. A sokfele megkozelites meg azt eredmenyezi, hogy a projekt reszvevoinek 1) allandoan el kell donteni, hogy melyiket alkalmazzak 2) nehezebb ertelmezni a masik kodjat.
Pl. a Java ezert is olyan sikeres -- egy Java kodot _barki_ el tud olvasni. (Ott a komplexitast attoltak a frameworkok szintjere.)
while (!sleep) sheep++;
-
alapz@j
tag
Értem, de azért azt tegyük hozzá, hogy az általa említett Javában is gyakran van szintaktikai változás verziók között - ha jól emlékszem, pl. az 1.5-től jött be a
for (String s : stringArray)
forma a korábban használtfor (int i ...) stringArray.get(i)
kiváltására és nem okozott ez törést senki életében. -
dobragab
addikt
Napi mitírki. Nem nehéz, de azért van benne egy apró csavar. Kérdés: mi a függvény visszatérési értéke?
unsigned set(unsigned *a, unsigned *b) {
*a = 1;
*b = 2;
return *a;
}[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
Ú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!