Idézet a K&R könyvből:
2.3 Gyakorlat. Írjunk meg a sqeeze(s1,s2) egy másik változatát, amely s1-ből minden olyan kerektert töröl, amely megegyezik bármelyik s2 karakterláncbeli karakterrel!
Én a lenti megoldást írtam.
Lehetne ezt a feladatot frappánsabban megoldani a goto használata nélkül?
squeeze (s1,s2)
char *s1,*s2;
{
int i,n,x=0;
for(i=0;s1[i]!=0;i++)
{
for(n=0;s2[n]!=0;n++)
if (s1[i]==s2[n])
goto abort;
s1[x]=s1[i];
x++;
abort:
;
}
s1[x]=0;
}
- 2446 megtekintés
Hozzászólások
vhogy continue; -vel szvsz meglehet. mindjárt megnézem pontosabban. :)
szerk: na mi van ha így néz ki a kérdéses rész:
for(n=0;s2[n]!=0;n++)
if (s1[i]==s2[n]) break;
if ( s2[n] == 0 ) {
s1[x]=s1[i];
x++;
}
?
Nem próbáltam ki de szvsz műxik így.
kl223
- A hozzászóláshoz be kell jelentkezni
squeeze (s1,s2)
char *s1,*s2;
{
int i,n,x=0;
for(i=0;s1[i]!=0;i++)
{
for (n = 0; s2[n]; n++)
if (s1[i] == s2[n])
break;
if (!s2[n]) {
s1[x]=s1[i];
x++;
}
}
s1[x]=0;
}
- A hozzászóláshoz be kell jelentkezni
Köszönöm a gyors hozzászólásokat! :-)
A kérdésem az lenne, hogy egy ilyen esetben szerintetek kerülendő-e a goto használata?
Mivel ezekben a megoldásoban egy plusz feltételvizsgálat is szerepel, ezért méréseim szerint 6%-al lassabbak az eredeti változatnál.
- A hozzászóláshoz be kell jelentkezni
Szerintem siman hasznalhato itt a goto, mas kerdes, hogy lehet, hogy a tanarnak nem fog tetszeni. Ez a "tilos a goto" egy nagyon kemeny dogma, amit meg talan Wirth vagy Dijkstra kezdett el hangoztatni a strukturalt programozas szuletesekor. Teny, hogy keves esetben van szukseg ra, de nem veletlen, hogy meg a Pascalban is szerepel ez a kulcsszo!
- A hozzászóláshoz be kell jelentkezni
Azért ciklusból így kiugráni mégse kellene vele, nem?
- A hozzászóláshoz be kell jelentkezni
Egyébként mi lenne, ha az if-ben szereplő feltételt negálnád, és a többit hagynád úgy ahogy van? Így amikor végre kell hajtani a törlést, végrehajtja, egyébként meg nem.
- A hozzászóláshoz be kell jelentkezni
IMHO először tanulj meg goto nélkül programozni, aztán ha már fél éve így kódolsz, akkor tudni fogod hogy hol/mire szabad goto-t használni (a fentire szerintem igen, leginkább hibakezelésre szokták (goto out, aztán a rutin végén van az out címke ami takarít).
- A hozzászóláshoz be kell jelentkezni
A goto nem szep, a strukturalt programozasban nem illik hasznalni(csak ha nagyon kell)
Viszont ha gyors kodot akarsz irni, akkor szukseg lehet ra :)
- A hozzászóláshoz be kell jelentkezni
A goto valójában csak arra alkalmas, hogy előbb-utóbb karbantarthatatlan, átláthatatlan kódot írjál.
Én is azt tudom javasolni, hogy ne használj goto-t, tanulj meg nélküle programozni. A goto nem halálos, de használata sok veszélyt rejt magában.
A fenti kódban valóban megoldás, ha a második (belső) ciklus belsejében levő feltételes elágazás feltételét beemeljük az őt befoglaló ciklus ciklusfeltételébe negálva. Ekkor a belső feltétel vizsgálat elhagyható.
Ezért nem árt, ha némi elméleti programozást is tanul az ember, az ilyen technikákat ott meg lehet tanulni és tetszőleges programnyelvben alkalmazni.
- A hozzászóláshoz be kell jelentkezni
Ja, ha mar itt tartunk, a "break" utasitas sem eppen a strukturalt programozas gyongyszeme, de arra nem szoktak raugrani a tanarok :)
- A hozzászóláshoz be kell jelentkezni
HaHó!
Talán azért nincs a ,,break'' utasítással gond, mert nem mindenütt lehet használni.
A break utasítást főképpen a ciklusokból való kilépéshez, valamint a ,,switch'' utasítás ,,case'' ágainak lezárására használják, az utasítás hatására a vezérlés a ciklus/switch utasítás utáni első utasításra kerül.
A ,,goto'' utasítással elvben egy adott blokkon belül bárhova lehet ugrani, s talán ezért nem szeretik látni a tanárok a goto-t, s nem szólnak a break miatt...
- A hozzászóláshoz be kell jelentkezni
Kipróbáltam emlékszem-e még a C-re :-)
unsigned char *sqeeze( unsigned char *szoveg, unsigned char *torlendo ){
int i, honnan, hova;
unsigned char megorzendo[256];
memset( megorzendo, 1, 256 );
for( i=0; torlendo[i]; i++ )
megorzendo[torlendo[i]] = 0;
for( honnan=0, hova=0; szoveg[honnan]; honnan++ )
if( megorzendo[ szoveg[honnan] ] )
szoveg[hova++] = szoveg[honnan];
return szoveg;
}
- A hozzászóláshoz be kell jelentkezni
void squeeze(char *s1, const char *s2)
{
char* pdest = s1;
while( *s1 )
{
const char *pcomp = s2;
while( *pcomp )
{
if( *s1 != *pcomp )
++pcomp;
else
break;
}
if( *pcomp==0 )
*pdest++ = *s1++;
else
++s1;
}
*pdest = 0;
}
Megjegyzések:
1. unsafe code: s1, s2-nel NUL terminátorra számítani durva biztonsági rés. Át kellene adni plusz paraméterben a string hosszot is. Ekkor már NUL karakter is törölhetõ (az eredeti megoldásban nem).
2. const használat: s2 szükségtelenül módosítható, ez csökkenti a felhasználhatóságot. Legyen a paraméter const char* s2
3. bemenõ paraméter vizsgálat kellene (s1!=NULL && s2!=NULL).
4. visszaadott érték hasznos lenne.
- A hozzászóláshoz be kell jelentkezni
hi
ez most nagyon tetszett ;))
meg lehetne egy picit egyszerusiteni
void squeeze(char *s1, const char *s2)
{
char* pdest = s1;
const char *pcomp;
while( *s1 )
{
for(pcomp=s2;*pcomp && *s1!=*pcomp;pcomp++);
if( !*pcomp )
*pdest++ = *s1;
s1++
}
*pdest = 0;
}
--- nem probaltam ki ;)
- A hozzászóláshoz be kell jelentkezni
1. lol
2. lol
3. lol
4. lol
- A hozzászóláshoz be kell jelentkezni
kedves micsa, tudjuk, hogy te tudod hogy mi nem tudjuk, de megnyilatkoznál nekünk halandóknak is, ó Mester, hogy mi a mulatságos?
köszönjük az egyszerű nép nevében.
- A hozzászóláshoz be kell jelentkezni
1. unsafe code: s1, s2-nel NUL terminátorra számítani durva biztonsági rés. Át kellene adni plusz paraméterben a string hosszot is. Ekkor már NUL karakter is törölhetõ (az eredeti megoldásban nem). ??? Miert, az atadott hossz, az miert biztosabb, mint a NUL terminator? Amugy ez a kijelentes igy kb. nulla tartalommal bir. Ha ez a fuggveny egy kulso dll-ben leledzik, akkor lehet valami ertelme (marmint a problemanak, de nem a "megoldasnak"), de ha egy program resze, akkor minden attol fugg, hogy "ki" hivja...
2. const használat: s2 szükségtelenül módosítható, ez csökkenti a felhasználhatóságot. Legyen a paraméter const char* s2 A felhasznalhatosag mit jelent szerinted??? Nem teljesen ertem a mondatod elso felet. Amugy a const legfoljebb annyit jelent, hogy warningol veszettul a fordito (mar ha elfelejtesz cast-olni ;-))
3. bemenõ paraméter vizsgálat kellene (s1!=NULL && s2!=NULL).Ez megint attol fugg, "ki" hivja ezt a rutint. ld. 1. pont
4. visszaadott érték hasznos lenne. Mar miert?? Van olyan eset amikor igen, van amikor ki nem sz@rja le??? ld. 1. pont
Zsiraf
- A hozzászóláshoz be kell jelentkezni
> Amugy a const legfoljebb annyit jelent, hogy warningol veszettul a fordito (mar ha elfelejtesz cast-olni ;-))
Ez nem igaz, nem csak warningot jelent. Vegyük az alábbi kódot:
void foo (char *s)
{ ... }
majd valahol máshol:
foo("asdf");
foo("asdf");
Ekkor az "asdf" sztring két példányban fog szerepelni a memóriában, hiszen ha a foo az elsőt átírja, akkor is a második hívásnál az "asdf" sztringet kell megkapnia.
Ha viszont a foo argumentuma "const char *", akkor a fordító joggal optimalizálhat arra, hogy az "asdf" sztringet csak egyszer tárolja le, és a két esetben ugyanazt a pointert kapja a foo. Ha az első a const ellenére átírja a sztring tartalmát, a második már nem az "asdf" sztringet kapja meg, hanem az előző hívás által módosított értéket, ergó hibásan fog működni. Na erre a hibás működésre figyelmeztet a warning, ami tehát nem pusztán egy warning, hanem sokkal több.
- A hozzászóláshoz be kell jelentkezni
Ekkor az "asdf" sztring két példányban fog szerepelni a memóriában, hiszen ha a foo az elsőt átírja, akkor is a második hívásnál az "asdf" sztringet kell megkapnia.
Bocs, de baromsagokat miert kell irni? Az, hogy a sztring konstansokat hogyan kezelje a fordito, nincs szabalyozva. Van olyan, amely read-only area-ba pakolja (hiszen definicioszeruen ezek konstansok), pl. gcc, es van olyan ami nem pl VisualAge C++. Tehat pl. gcc eseten (ha nem adunk meg -fwritable-strings-et) foo("asdf") nem ir at semmit, mert segfaultol mivel a string constans az valoban konstans... es persze nem szerepel 2x a "memoriaban"...
De, csak hogy peldat is mutassak:
(gdb) r
Starting program: /tmp/a.out
Program received signal SIGSEGV, Segmentation fault.
0x0804832a in atir (a=0x8048498 "alma") at test.c:5
5 *a = 'y';
(gdb) bt
#0 0x0804832a in atir (a=0x8048498 "alma") at test.c:5
#1 0x0804834c in main () at test.c:10
(gdb)
A forras igy nez ki:
void atir(char *a)
{
*a = 'y';
}
main()
{
atir("alma");
}
Zsiraf
p.s.: szoval string constant-t atirni elegge csunya dolog... :-o Hogy szabadjon megjegyeznem, nem a goto-t kene irtani, hanem az ilyen f@szsagokat... ma bocs... :-(
- A hozzászóláshoz be kell jelentkezni
egmont egy másik fordítási opcióra utalt, és igaza van:
a string merge-re, amikor a fordító észleli a két azonos const stringet és egybeolvasztja őket - vagy éppen ezt letiltod és tényleg két másolat létezik belőle a memóriában.
- A hozzászóláshoz be kell jelentkezni
ld. elozo hozzaszolasom :-)
Zsiraf
- A hozzászóláshoz be kell jelentkezni
Bocs, de baromsagokat miert kell irni?
Picit vegyél vissza a stílusból légy szíves. Lehet hogy nem voltam 100%-ig pontos, lehet hogy Te jobban értesz mindehhez, de az első baromságot Te írtad, amikor azt mondtad, hogy a const csak egy warningot eredményez. Valószínűleg pontatlanul ugyan, de tökéletesen rávilágítottam arra, hogy ebben nem volt igazad. Tehát elsőként Te írtál baromságot kettőnk közül. No problem, csak akkor talán nem kéne ilyen stílusban számonkérni rajtam, hogy ha én is azt írok.
- A hozzászóláshoz be kell jelentkezni
Valószínűleg pontatlanul ugyan, de tökéletesen rávilágítottam arra, hogy ebben nem volt igazad. Na most ezt telleg teljesen nem ertem... Szerinted egy fuggveny parameter deklaraciojanak -- nevezetesen pl. void foo(char *a); -- hatasa van arra, hogy kesobb a hivaskor megadott string literal (konstans?) tarolasa read-only, vagy read-write teruletre tortenik??? Erdekes lenne...
De hogy ne csak pofazzak:
cat test.c
void foo(char *a)
{
*a = 'y';
}
main()
{
foo("alma");
foo("alma");
}
gcc-3.3 test.c
strings a.out
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
QVhO
alma
gcc-3.3 -fwritable-strings test.c
strings a.out
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
QVhO
alma
alma
Ezek szerint, nem attol fugg, hogy ket string-et keszit, vagy egyet de ket hivatkozassal, hogy milyen a fuggveny deklaracioja (a maradek ket probat rad bizom...)
Nem erzem a tokeletes bizonyitast, hogy milyen hatasa van a const char* argumentum deklaracionak... Csak azt latom, hogy a fordito -fwritable-strings opciojanak milyen hatasa van, meg hogy a forditonak milyen hatasa van... Tehat mar ne haragudj, de baromsagot irtal...
Zsiraf
p.s.: amugy a 4.xx gcc: GCC no longer accepts the -fwritable-strings option. Use named character arrays when you need a writable string.... tehat ennel a forditonal mar kivulrol se tudod rakenyszeriteni, hogy duplazza a string literal-okat..
p.s.: lehet, hogy neha elviselhetetlen a stilusom, de en azert utanna szoktam nezni annak amirol szolok, s probalok nem urban legend-eket letrehozni/terjeszteni...
- A hozzászóláshoz be kell jelentkezni
"amugy a 4.xx gcc: GCC no longer accepts the -fwritable-strings option. Use named character arrays when you need a writable string.... tehat ennel a forditonal mar kivulrol se tudod rakenyszeriteni, hogy duplazza a string literal-okat.."
nem így van, mert a string merge-lést a "merge-constants" vezérli, nem a "writeable-strings" opció.
de a lényeg nem ez.
nem is az, hogy egy adott platformon, egy adott fordítóval hogyan viselkedik.
a lényeg az, hogy a const elhagyása tervezési hiba, mert futási időben fog kiderülni a hiba /megbukni az optimalizáció/, nem pedig fordítási időben.
- A hozzászóláshoz be kell jelentkezni
nem így van, mert a string merge-lést a "merge-constants" vezérli, nem a "writeable-strings" opció. Hmm.. elozo peldaprogram es
gcc -fno-merge-constants test.c
strings a.out
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
QVhO
alma
gcc-3.3 -fmerge-constants -fwritable-strings test.c
strings a.out
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
QVhO
alma
alma
.
No, akkor most mi van?
Mar ne haragudj, de en azt vettem ki lenyegnek egmont hozzaszolasabol, hogy ha a deklaracio nem const char *, akkor string literal fgv-hivasra nemcsak warningot kapok, hanem ket ugyanolyan string-et is a memoriaban... Kiprobaltam, de nem ez tortent...
azt alitod: de a lenyeg ... nem is az, hogy egy adott platformon, egy adott fordítóval hogyan viselkedik. igy van, de egy biztos, hogy ugy, ahogy egmont irta egyik platformon es egyik forditoval sem mukodik! Megegyszer: nem attol fugg, hogy a fordito a string literal-okat merge-eli, hogy const, vagy nem const argumentum deklaracioju fuggveny hivasakor szerepel az adott literal, hanem attol, hogy a fordito, milyen modon tarolja. Erre lehet hatassal az, hogy irhato/olvashato vagy csak olvashato teruletre rakja, meg esetleg, hogy tiltjuk-e neki a merge-et... de mas NEM.
Zsiraf
p.s.: meg mindig nem ertem, ha elhagyom az argumentum deklaraciojaban a const qualifier-t, akkor min bukik meg futas idoben?
- A hozzászóláshoz be kell jelentkezni
"meg mindig nem ertem, ha elhagyom az argumentum deklaraciojaban a const qualifier-t, akkor min bukik meg futas idoben?"
1. elhagyjuk
2. jon a programozo 4 het mulva, nem tud arrol a ceges szabalyrol, hogy "ebbol a fuggvenybol elhagytuk a const-ot, de az valojaban ott van, ne hivd meg csak const argumentummal".
3. beleir 5 sort a fuggvenybe, ami megpiszkalja s2-t.
4. a hiba nem derul ki feluletes tesztelesnel, mert nem fut ra olyan agra a program, ahol const char* s2-t valaki atcastol char* s2 -re (brrr nagykalapacsos C tipuskenyszerites)
5. kiszallitjak az uj verziot
6. 2 het mulva az atomreaktor elszall timbuktuban.
-----
"Erre lehet hatassal az, hogy irhato/olvashato vagy csak olvashato teruletre rakja, meg esetleg, hogy tiltjuk-e neki a merge-et... de mas NEM"
nos, az optimalizacio csodakra kepes. nem regi vacak C forditokra kell gondolni, hanem valami ugyesebb c++ -ra, pl globalis optimalizacioval, ami a projektben az osszes elofordulast is meg tudja vizsgalni.
- A hozzászóláshoz be kell jelentkezni
3. beleir 5 sort a fuggvenybe, ami megpiszkalja s2-t. es nem nezte at az osszes hivasi helyet? pedig latta, hogy eddig a fgv. nem piszkalta az s2-ot? Erdekes... Ha en belepiszkalok egy fgv-be, akkor altalaban vegignezem az osszes hivasi helyet, hogy jo, vagy nem... De lehet, hogy tul slendrian vagyok...
Zsiraf
p.s.: amugy meg mindig nem ertem mi koze ennek a goto elhagyasahoz... ;-)
p.s.: nem regi vacak C forditokra kell gondolni,???? Miert, te a C programjaidat C++-al szoktad forditani, persze lehet hogy en elmaradott vagyok mert nem a Visual C++-t hasznalom... Persze, lehet hogy a gcc regi szar vacak.... Ja, kiprobalhatod a merge-elest a gcc-4xx C++ forditojaval is... (jo, jo tudom az is szar regi vacak...)
- A hozzászóláshoz be kell jelentkezni
természetesen egy jó fordító szemantikailag nézi végig az összes helyet. ha megállapítja, hogy valami const, vagy kevésszer van használva, akkor akkor akár inline-olhatja is. tehát dönthet összevonásról de akár egy közös konstans duplikálásáról is.
/de részemről itt vége, a személyeskedő vagdalkozásból köszönöm ennyi elég volt/
- A hozzászóláshoz be kell jelentkezni
Hmmmm... valóban. Megadom magam :) És persze elnézést az előző beszólásomért, tényleg nem volt jogos.
- A hozzászóláshoz be kell jelentkezni
de yó... megválaszoltatott helyettem :)
1. most cseréljük le a strcpy függvényt? mert hogy "unsafe"?
2. így van, a const csak max 1 warningot jelent (C++ lehet hogy jobban nyipákol), de hát erre van ugye a cast.
3. miért, mivel biztonságosabb, ha a függvényt egy (char*)1 -gyel hívom és nem NULL-lal?
4. ez a függvény spéci nem "számol ki" semmit... eléggé nem látom a visszatérési érték értelmét...
- A hozzászóláshoz be kell jelentkezni
1. természetesen a strcpy függvényt le kell cserélni, mert unsafe.
ébresztő, nem 1970 van, hanem 2006.
lásd még: google: strcpy unsafe standard
2. ???
nem gondolod, hogy a warning az csak tünet? végig nem gondolt kódra utal. /Ha valami bemenő paraméter nem const, pedig nem is módosítjuk, akkor a függvényt nem lehet const char* argumentummal hívni. Ezzel csökkentettük a felhasználhatóságot, és potenciális hibalehetőséget vittünk be./
3. rossz érv. A NULL speciális érték, ami sok nagyságrenddel gyakrabban fordul elő, mint a (char*)1 A bemenő paraméter vizsgálata tehát jelentősen biztonságosabbá teszi a kódot, mint az volt vizsgálat nélkül.
4. Például hasznos lehet a replacement-ek száma. Példa: illegális fájlnév karaktereket helyettesítettünk fájlba mentés előtt. A programnak illene warning-ot adni, ha szükség volt helyettesítésre. Ha nincs visszatérési érték, akkor ez időtrabló és kényelmetlen.
- A hozzászóláshoz be kell jelentkezni
Hmm, biztonságosság meg az strcpy lecserélése. Alapvetően két hozzáállás van, évszámtól függetlenül:
a., A programozó azért programozó, mert tudja, hogy mit csinál, úgy írja meg a kódot, hogy null-ra nem hív strcpy-t, így nem kell a kezét fogni, ellenőrizni mindent, amit leírt, hogy jaj véletlenül bajt ne okozzon, és ezzel akár többet is foglalkozni, mint maga a feladat. Ha elront valamit, majd kijavítja.
b., A programozó csak egy luser, akinek valaki elárulta a fordító nevét, megbízni benne nem lehet, mert kettejük közül a fordító az okosabb, inkább ne tudjon hatékony programot írni, de nem szabad odaengedni a kódhoz, mert tuti csak elrontaná.
A C az a., csoportba tartozik, a b.-be pedig pl. a java. Ott garantáltan nincs null-dereferenciálás meg memóriafolyás, helyette van a görcsölés, hogy ha már egyszer tudom, hogy mit akarok, akkor azt hogy nyomjam le a nyelv torkán.
De hogy ne rohanjunk előre annyira: a C++-os stl-ben van string osztály, ugye. Na persze, csak egyszer érdemes megnézni, hogy egy átlag szövegfeldolgozási feladatnál a minimálisan szükségeshez képest hány átmeneti példány jön létre a hívások során, foglalással, inicializálással, stb. együtt.
Valamit valamiért, a hatékonyság és a bolondbiztosság egymással szemben áll, a C pedig anno a hatékonyság mellett tette le a voksot, és ahogy látom, ez a mai napig így is maradt, azaz én nem cserélném le a jó öreg strcpy-t: akinek nem elég biztonságos, az használjon pl. java-t.
(char*)1: Tényleg ritka, bár azért van hasonló, lásd pl. az mmap-ot, ami hiba esetén (void *)-1 -et ad vissza :).
De ha már libc-hibáknál/hiányosságoknál tartunk, nekem ezek csípik a szememet:
- konstans puffert használó dolgok, pl. strtok, localtime, és társai
- poén-függvények, pl. strfry, memfrob
- errno: van jópár függvény (sqrt, log, stb.), ami _csak_ az errno-val jelzi, ha hiba történt, az errno meg nem thread-safe ugye...
- specifikálatlan esetek, pl. mit ad vissza az snprintf(NULL, 0, "izehoze")? Elvileg 8-at kéne, gyakorlatilag meg implementáció-függően 8-at, 0-t, vagy segfault-ot...
- const-'lazulások', pl. char* strchr(const char*, int), azaz az strchr(p, p[0]) a const char* p-t szó nélkül castolja char*-ra...
- egész-méretek: ívesen nem érdekel, hogy mekkora az a szám, amivel a proci még egy művelettel számolni tud (int), nekem mindig akkora változó kell, amiben a feladat megkövetelte tartomány elfér. van ilyen, nevezeteset az stdint.h-beli [u]int(8|16|32|64)_t, csak éppen ezeket senki sem használja, plusz még a glib is inkább definiál sajátot (bár ez már egy másik mese)...
- signal-safe-ség. a hivatalosan sighandler-ből hívható függvények (man 2 signal) jók, de a library-k (libc, libm) signal-safe-ségével mi a helyzet? Merhetek olyat csinálni sighandlerben, hogy 'syslog(LOG_CRIT, "Ekkora a string: %d", strlen(s))'? Van ebben minden, mint a búcsúban: vasprintf, localtime, strlen...
- A hozzászóláshoz be kell jelentkezni
> - konstans puffert használó dolgok, pl. strtok, localtime, és társai
Ezek történelmi okokból vannak csak, és általában létezik _r párjuk.
> - az errno meg nem thread-safe ugye...
De, az (az újabb rendszereken, pl. asszem glibc-2.3.x-től). Lásd "man errno".
- const-'lazulások'
Itt engem konkrétan az iconv() inbuf paramétere zavar, hogy az vajh miért nem const.
- A hozzászóláshoz be kell jelentkezni
1., hogy az strcpy-t le kell-e cserelni vagy nem, azt gsimon eleg jol elmagyarazta... :-)
2., akkor a függvényt nem lehet const char* argumentummal hívni. Hmm.. a warning warning, az error error. Tehat hivni lehet, csak forditaskor osszevonja a szemoldoket a fordito... amugy meg ele kell szurni egy (char *)-ot, oszt az a cast (gondolom talalkoztal mar vele ;-) )!
3., Hogy, biztonsagos-e, az nem attol fugg, mit vizsgal, hanem hogy aki hivta, az mit adott at neki... Lehet abban !NULL, oszt megis...
4., A programnak illene warning-ot adni, ha szükség volt helyettesítésre. oszt, ki mondta, hogy arra hasznaltuk... ;-) No de ferre a trefat, epp ezt probaltam megertetni az elejen, hogy ezek a borzaszto hianyossagok mind attol fuggnek, hogy hol hasznaljuk a kodot... A jelen esetben asszem arrol volt szo, hogy lehet-e hatekonyan goto nelkul megoldani... Mintha ennek semmi koze nem lenne a NULL/NUL, meg "sechole"-khoz... de mindegy...
Zsiraf
p.s.: a warning meg, hogy mire utal?? Mar ne haragudj, de miert a "vegig nem gondolt" kodra utal?? Ezt mi alapjan allitod. pl. az if (a && b || c) ha warningol, akkor az azt jelenti, hogy nem gondoltam at? Vagy meg megadod az eselyt, hogy ismerem a precedenciajat a logikai muveleteknek?
- A hozzászóláshoz be kell jelentkezni
1. strcpy
a cél library függvény volt.
Itt a kötelező hozzáállás a hülyebiztosság.
Igen, így a megvalósítás több mint 50%-a hibaellenőrzés lesz.
Jutalma a megbízhatóbb rendszer.
Uff. erről ennyit.
2. cast
mi itt a lényeg? Az, hogy ha nem const char* -ot használunk itt, akkor ez egy rosszul tervezett függvény lesz. Ezt nem lehet elviccelni, kedves szaszg és mások, akiknek a cast a megoldás.
A cast itt is ordítóan utal arra, hogy bizony nem volt átgondolva az, hogy char* -ot adtunk át, pedig string konstanst vártunk.
Kérlek, ebbe gondolj bele, mert ez életveszélyes programozási stílushoz vezet!
1 perc gondolkodás 100 perc debuggolástól és 10000 dühös júzertől menthet meg.
3. A NULL ellenőrzéssel biztonságosabbá tettük, tehát célunkat elértük.
4. Értsd meg, a könyvtári függvénynek akkor is működnie kell, ha atomot robbantanak mellette. Nem támaszkodhat a külvilágból szármzaó adatok helyességére például, mert ebből így sz.r rendszer lesz.
- A hozzászóláshoz be kell jelentkezni
"Értsd meg, a könyvtári függvénynek akkor is működnie kell, ha atomot robbantanak mellette. Nem támaszkodhat a külvilágból szármzaó adatok helyességére például, mert ebből így sz.r rendszer lesz."
Próbáltál NULL-ot adni a strcpy függvénynek? :P Pedig ha robbantanak mellette, akkor is jól működik. Az olyan. :)
- A hozzászóláshoz be kell jelentkezni
2. cast
mi itt a lényeg? Az, hogy ha nem const char* -ot használunk itt, akkor ez egy rosszul tervezett függvény lesz. Ezt nem lehet elviccelni, kedves szaszg és mások, akiknek a cast a megoldás.
A cast itt is ordítóan utal arra, hogy bizony nem volt átgondolva az, hogy char* -ot adtunk át, pedig string konstanst vártunk.
Kérlek, ebbe gondolj bele, mert ez életveszélyes programozási stílushoz vezet! Na most en ezt teljesen nem ertem. A fuggveny nem valtoztatja meg az adott string-et, tehat akar const a string akar nem, semmi nem tortenik... Akkor mi itt az eletveszely?? Az, hogy nyog egyet a fordito, hogy bameg, const-t attal at nem const-ra? Es??? Hagy kiabaljon. Az a dolga... Valos problema lenne, ha valtoztatnal a stringen, de a fuggvenyfejben const-ra deklaraltad... Persze ilyenkor error-t kop minden epelmeju fordito ;-)
3., 4., csak azt tudom mondani, amit az elobb is, mintha az eredeti kerdes nem konyvtari fuggveny irasarol szolt volna: Lehetne ezt a feladatot frappánsabban megoldani a goto használata nélkül? vagy nem???
Zsiraf
p.s.: foleg a 10000 duhos user tetszett ;-) jo, jo, nem viccelek 1 mar biztos van szemelyedben...
- A hozzászóláshoz be kell jelentkezni
az életveszély abban jelentkezik, hogy karbantarthatatlan kódot írsz.
ma még lefordul, és működik, de egy időzített bombát helyeztél el a kódodban.
ha valaki meglátja, azonnal gondolkozni kezd: "ez itt most miért nem const char*"? valami trükk van a dologban?
2 hét múlva senki nem fog rá emlékezni, hogy a második paraméter const kellet volna hogy legyen.
4 hét múlva valaki beír 5 új sort a függvénybe, vagy készít egy másik függvényt ebből másolással - de a szándék nincs a kódban, csak a nem egészen korrekt megvalósítás.
1 hónap múlva előjön az első rejtélyes hiba.
1 év múlva kirúgnak, mert pár havonta rejtélyes elszállás lesz a timbuktui telephelyen, ahonnan senki nem küld neked vissza pár megás coredumpot /velünk ez hetente megtörténik/.
3/4: nem tudom máshogy mondani: ne adj ki sz.r munkát a kezedből még egy 5 soros függvény esetén sem. ez fog megkülönböztetni a harcos amatőröktől ("bedobunk egy cast-ot oszt jóvan", és "lassú az adatbázis? ráhúzunk egy indexet, és kész").
- A hozzászóláshoz be kell jelentkezni
Oke, akkor utoljara vissza az eredeti problemara... Baratunk megkerdezte, lehet-e ezt a rutint goto nelkul megirni... Erre azt valaszoltatok, hogy ez a rutin tele van sechole-al, mert nem const char *, meg nem nezi a NULL-t, meg miert nem adja at a string hosszat md5sum-jat, inverzet, crc-jet, es kulonben is az strcpy tokeletesen obsolate... Majd, mindenfele legendak a string literal-okrol meg iconv-rol, meg ilyenek??? Minek? En ezt nem ertem teljesen...
Amugy azt miert nem kifogasolod, hogy nem kommentezte soronkent a kodjat, s igy karbantarthatatlan 5 soros rutint irt?
Vagy hogy miert nem objektum orientaltan irta meg, mert most az a trendi?? (a sechole-ok mellett)
Zsiraf
p.s. De azt meg legyszives vilagositsd meg szamomra (habar nagyon off), hogy ha 2 hét múlva senki nem fog rá emlékezni, hogy a második paraméter const kellet volna hogy legyen.. miert eletveszelyes? Veletlenul valaki nem const-ot ad at? Vagy const-ot??? Es akkor mi lesz??? Mi lesz az a rejtelyes hiba, ami miatt timbuktuban elszall az iskolai mintafeladattol a mittomemmi?
- A hozzászóláshoz be kell jelentkezni
mert többen tartják karban a függvényt.
- A hozzászóláshoz be kell jelentkezni
Es??? Ha ezren tartjak karban, akkor attol mar segfaultol, hogy const/nem const argumentumot adtunk egy nem const-nak deklaralt helyre, es ennek ellenere nem probalta meg atirni??? vagy mi a rak?
Zsiraf
p.s.: ha meg valaki az 1000 karbantarto kozul, ugy valtoztat a fgv-en, hogy mostmar belepiszkit a stringbe, akkor mar ne haragudj de kutya kotelessege az osszes hivasi helyet atnezni, akar const char *, akar char * volt a deklaracio, vagy nem???
- A hozzászóláshoz be kell jelentkezni
1. egy könyvtári jellegű függvénynek nem nézhető végig az összes felhasználási helye, mert az nem ismert a készítés pillanatában.
2. ha hiányzik a const, akkor Demoklész kardja lebeg a függvény fölött: bármikor bárki felhasználhatja rosszul, akár 1 nappal a lelkiismeretes ellenőrzés után. a bugok márpedig mindig a legrosszabkor bújnak elő. Nem lenne egyszerűbb végiggondolt, tisztességes kódot készíteni, egyszer?
/itt a vége/
- A hozzászóláshoz be kell jelentkezni
2. Ha hianyzik a const es vki const-ot ad akkor ne pofazzon. Ha nem vallaltam, h nem nyulok hozza, akkor ne szamitson ra, h nem fogok hozzanyulni.
- A hozzászóláshoz be kell jelentkezni
Nagyon felkaptad a vizet, de nem megfontoltak az érveid.
1. aki nem tud dolgozni a libc-vel, az programozzon visual basicben. Csak gondolkozz el azon is, ha keresel egy bugot, sokkal nagyobb segítség lehet, ha kicrashsel a program, mint debug messagekkel vadászni...
2. ha nem találkoztál még idegesítő warninggal, amiről te tudod hogy rendben van, akkor még lehet gyakorolni. Példának meggreppelheted a linux kernel source-ot "happy" keyworddal.
3. user space-ben úgysem tudod lecsekkolni, hogy valid-e az a memóriarész. Ha a függvény úgy van specifikálva hogy valid pointert kér, akkor valid pointert kér, nem pedig NULL-ot. Ezen kívül úgysem tudsz csinálni semmit: ha elszállt egy pointered, elszállt. Amúgy a (char*)1-et nem szó szerint értettem, tőlem (char*)0x53762341 is lehet, ha nincs oda mappelve memória.
Ha még mindig nem tiszta: ez nem a linux kernel, itt nincs rw_verify_area :P
Tehát a programozó felelőssége vigyázni a pointerekre.
4. így van, ez hasznos lehet, bár nem kéri a specifikáció.
- A hozzászóláshoz be kell jelentkezni
1. "ha keresel egy bugot, sokkal nagyobb segítség lehet, ha kicrashsel a
program, mint debug messagekkel vadászni"
uuuhhhh... tehát egy űrhajót vezérlő rendszert is inkább rántson el a string replace-elő függvényecske, és jöjjön inkább az önmegsemmisítés... jajj.
a többi pont érdektelen / nem a felvetésekre reagál.
/semmi víz felkapás nincsen/
- A hozzászóláshoz be kell jelentkezni
megértettem: nincs akivel tárgyalni, türelmemnek is vége...
A legnehezebb vitatkozni az olyan emberekkel, akiknek határozott meggyőződésük van olyan dolgokról, amiket nem ismernek. S még ráadásul ego érzékenyek is...
te nem halottál ugye még core file-ról? Jah, visual basicben nincs? :D
részemről befejezve az "eszmefuttatás". LOL
- A hozzászóláshoz be kell jelentkezni
kedves micsa, személyeskedéssel nem jutsz messzire. nagyon mellé lőttél barátom.
- A hozzászóláshoz be kell jelentkezni
ebben az esetben (lásd fent) igenis számít hogy const char* vagy char*. Csak nem erről volt ugye eredetileg szó... Hanem arról a 4 "javaslatról"...
"a többi pont érdektelen / nem a felvetésekre reagál."
ettől függetlenül nem látom hogy koherens módon megindokoltad volna az érvelésedet.
tiszteletem "barátom" :P
- A hozzászóláshoz be kell jelentkezni
(Nem szóltam, a lényegi részt zamboriz kolléga leírta :)...)
De ha már sikerült hozzászólnom, akkor a rejtett goto általam eddig talált legszebb/legrondább esetére tennék ide egy linket:
Duff's device
- A hozzászóláshoz be kell jelentkezni
Hát ez tényleg nem kispályás :)
- A hozzászóláshoz be kell jelentkezni
Hát persze
/* goto abort; */
Így néz ki goto nélkül.
Frappáns megoldás.
Azt nem írtad ,hogy jól működjön is :-)
- A hozzászóláshoz be kell jelentkezni