problema

 ( matthew | 2006. március 7., kedd - 21:21 )

Hello! Adott egy problema, miszerint string1-bol ki kell szedni a string2-ben talalhato osszes karaktert. A progi, amit irtam igy nez ki:

#include

void
squeeze (char alap[], char torlendok[])
{
int i, j, x = 0;

for (i = 0; alap[i] != '\0'; i++)
for (j = 0; torlendok[j] != alap[i]; j++)
alap[x++] = alap[i]; /* Itt lehet a gond, de nem 100% */

alap[x] = '\0';
}

int
main (void)
{
char string1[] = "karakterlanc";
char string2[] = "acl";
squeeze (string1, string2);
printf ("%s\n", string1);
return 0;
}

Segmentation faultot kapok, es ketsegbe vagyok esve, mert nem tudom mit rontottam el. Regota gondolkozom rajta. Konyorgom, aki tud segitsen.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Ez a megoldas mukodik, bar nem a legoptimalisabb.
A te kododdal a problema valahol itt volt:
"for (j = 0; torlendok[j] != alap[i]; j++)
alap[x++] = alap[i];"

A for j ciklus tulindexelheti a torlendok tombot, ez okozta a seg.faultot.

Mate

void squeeze (char alap[], char torlendok[])
{
int i, j, x = 0, bFound;

for (i = 0; alap[i]; i++)
{
bFound = 0;
for (j = 0; torlendok[j]; j++)
{
if(torlendok[j] == alap[i])
{
bFound = 1;
break;
}
}
if(!bFound)
{
alap[x++] = alap[i];
}
}
alap[x] = '\0';
}

Egy egyszerűbb megoldási lehetőség:

for (i = 0; alap[i] != '\0'; i++)
for (j = 0; torlendok[j] != alap[i]; j++)
if (torlendok[j]=='\0') alap[x++] = alap[i];

Remelem nem gondoltad komolyan... Hogyan oldja ez meg a segfaultot? Ugyanis ha az alap karakter nincs benne a torlendo listaban, akkor bizony segfault lesz elobb-utobb.

Inkabb:

x = 0;
for (i = 0; alap[i]; i++) {
    for (j = 0; torlendok[j] && torlendok[j] != alap[i]; j++);
    if (!torlendok[j])
        alap[x++] = alap[i];
}
alap[x] = 0;

A "for(j..." ciklus minden egyes lépésével felülírod az alap sztringet az első karakterrel:
karakterlanc, kkrakterlanc, kkkakterlanc, kkkkkterlanc
majd a második karakterrel, ami már rég az első:
kkkkkkerlanc, kkkkkkkrlanc, kkkkkkkklanc, kkkkkkkkkanc
és így tovább addig, amíg a az alap[x] sf-ra nem futtatja a programodat.

Mivel a "for (j..." ciklusban az i nem valtozik, es a 'k', ami az elso karaktere az alap tombnek, nincs benne a tolendo listaban (ergo nem all le a ciklus), soha nem jut el az alap tomb masodik karakterehez. Hulyesegeket ne beszeljunk...

Zarojel: bizonyos esetekben, ha a memoriaban kap egy 'k'-t mielott segfaultolna, akkor leall... Viszont ez nem valtoztat az algoritmus viselkedesen, ami ugyebar nem szabad fuggjon csak azoktol az adatoktol, amik erdeklik...

Ezt alaposan elnéztem: azt feltételeztem, hogy a "for(j..." leáll a torlendok végén.

matthew!
bar nem ez volt a problemad, de ha mar mukodik a
program, javitgathatod is pl. probald meg a
belso ciklust (a keresest) kiiktatni.
udv, ncs

Én ezt így írnám meg: (csak szegmensfault aspektusából elemeztem
a dolgot, hogy mi értelme az egésznek és hogy azt csinélja-e
amit akarsz, azt nem vizsgáltam.):

void
squeeze (char *alap, char *torlendok)
{
int i, j, x;

x = 0;i=0;while(alap[i])
{j=0;while(torlendok[j]!=alap[i])
{alap[x]=alap[i];x++;
j++;}i++;}alap[x] = '\0';

}

/*
jobban járnál, ha az új stringet nem az alap[]-ban gyűjtenéd,
hanem egy pufferben, és a folyamat végén visszapakolnád az
alap[]-ba. Így elsőre nem látom a garanciát arra, hogy ne
fusson túl a ciklus!
*/

int
main (void)
{
char string1[] = "karakterlanc\0";
char string2[] = "acl\0";
squeeze (string1, string2);
printf ("%s\n", string1);
return 0;
}

> Sol omnibus lucet.

Atyauristen! Szerinted attol, hogy a for ciklusokat atirtad ekvivalens while ciklusokra, megszabadulsz a segfaulttol? Vagy esetleg attol, hogy az x++ kulon utasitas lett? Erdekes...

A megjegyzesed aztan igazi gyongyszem:

jobban járnál, ha az új stringet nem az alap[]-ban gyűjtenéd,
hanem egy pufferben, és a folyamat végén visszapakolnád az
alap[]-ba. Így elsőre nem látom a garanciát arra, hogy ne
fusson túl a ciklus!

Mivel torlesrol van szo, ezert biztos, hogy bele kell ferjen az eredetibe... Szegeny kerdezo azt hiszi: huha en tul egyszeruen kepzeltem el, de ide kell kulon pufferezes meg minden... Sot, a for ciklus sem a regi...

Nem ertem az ilyesmit... Mar volt kicsit fennebb is hasonlo iranyu gondolatom, csak nem fejtettem ki:
Mielott valakinek segiteni probalnal, elemezd es ertsd meg a problemat, ne irj ossze-vissza, mert csak meg jobban osszekavarod a dolgokat.

Azt tettem közzé, hogy ÉN, hogyan írnám meg. Futtasd le az eredetit,
meg az enyémet azt nézd meg, hogy melyik dob segfaultot. Egy külön
utasításba tett x++ néha csodákat művel.

> Sol omnibus lucet.

A tied is segfaultol, eppen ugy mint az eredeti, mivel UGYANAZ a kod!
A ket kod ekvivalens, ha nem hiszed, nezd meg gcc --save-temps segitsegevel:

Az eredeti:

squeeze:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $12, %esp
        movl    $0, -12(%ebp)
        movl    $0, -4(%ebp)
.L2:
        movl    -4(%ebp), %eax
        addl    8(%ebp), %eax
        cmpb    $0, (%eax)
        jne     .L5
        jmp     .L3
.L5:
        movl    $0, -8(%ebp)
.L6:
        movl    -8(%ebp), %eax
        movl    12(%ebp), %ecx
        addl    %eax, %ecx
        movl    -4(%ebp), %eax
        movl    8(%ebp), %edx
        addl    %eax, %edx
        movb    (%ecx), %al
        cmpb    (%edx), %al
        jne     .L9
        jmp     .L4
.L9:
        movl    -12(%ebp), %eax
        movl    %eax, %edx
        addl    8(%ebp), %edx
        movl    -4(%ebp), %eax
        addl    8(%ebp), %eax
        movb    (%eax), %al
        movb    %al, (%edx)
        leal    -12(%ebp), %eax
        incl    (%eax)
        leal    -8(%ebp), %eax
        incl    (%eax)
        jmp     .L6
.L4:
        leal    -4(%ebp), %eax
        incl    (%eax)
        jmp     .L2
.L3:
        movl    -12(%ebp), %eax
        addl    8(%ebp), %eax
        movb    $0, (%eax)
        leave
        ret

A tied:

squeeze:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $12, %esp
        movl    $0, -12(%ebp)
        movl    $0, -4(%ebp)
.L2:
        movl    -4(%ebp), %eax
        addl    8(%ebp), %eax
        cmpb    $0, (%eax)
        jne     .L4
        jmp     .L3
.L4:
        movl    $0, -8(%ebp)
.L5:
        movl    -8(%ebp), %eax
        movl    12(%ebp), %ecx
        addl    %eax, %ecx
        movl    -4(%ebp), %eax
        movl    8(%ebp), %edx
        addl    %eax, %edx
        movb    (%ecx), %al
        cmpb    (%edx), %al
        jne     .L7
        jmp     .L6
.L7:
        movl    -12(%ebp), %eax
        movl    8(%ebp), %edx
        addl    %eax, %edx
        movl    -4(%ebp), %eax
        addl    8(%ebp), %eax
        movb    (%eax), %al
        movb    %al, (%edx)
        leal    -12(%ebp), %eax
        incl    (%eax)
        leal    -8(%ebp), %eax
        incl    (%eax)
        jmp     .L5
.L6:
        leal    -4(%ebp), %eax
        incl    (%eax)
        jmp     .L2
.L3:
        movl    -12(%ebp), %eax
        addl    8(%ebp), %eax
        movb    $0, (%eax)
        leave
        ret

Hasonlitsd ossze a kettot... Meghogy csodakat muvel! ROFL

Meg egyszer kerlek: hulyesegeket ne terjessz...

1. Nem állítottam, hogy csodákat művel.
2. Emellett mintha elszaladtál volna:

/*
jobban járnál, ha az új stringet nem az alap[]-ban gyűjtenéd,
hanem egy pufferben, és a folyamat végén visszapakolnád az
alap[]-ba. Így elsőre nem látom a garanciát arra, hogy ne
fusson túl a ciklus!
*/

Figyelmedbe ajánlom az utolsó (felkiáltójellel
hangsúlyozott)mondatot.

3. Vigyázz arra, hogy Te ne hibázz sose.

> Sol omnibus lucet.

1. "Egy külön utasításba tett x++ néha csodákat művel."
Ezt biztos en irtam, ha nem te...

2. Nem szaladtam el mellette, az elozo hozzaszolasomban gyongyszemkent emlitettem azt is. Erdemes elolvasni.

3. Vigyazok amennyire tudok, de ha tevedek, elismerem.

1. Itt egy példa, hogy egy külön szedett x++ csodákat
tesz. Az ebbéli példa szerintem kimeríti a "néha" fogalmát.
Tanuljunk meg mondatot elemezni.
http://hup.hu/node/19669

2. Próbáljuk meg közösen értelmezni ezt a mondatot:

"Így elsőre nem látom a garanciát arra, hogy ne
fusson túl a ciklus!" Az én olvasatomban ez egyrészt jelenti azt, hogy
(1) érzésem szerint meg kéne vizsgálni a ciklus leállási
feltételét.
(2) bizonytalanságot fejez ki atekintetben, hogy az
általam adott kód hibátlan.

Ezek után egy olyan eszelős támadás, ami részedről
történt - szerintem - indokolatlan.

Részemről az ügy lezárva, mert kezd személyes síkra
terelődni a beszélgetés. Üdv: meditor

> Sol omnibus lucet.

Egyre jobban asod ala magad, de azert meg valaszolok...

1.
Akkor kell kulonszedni az x++ -t, ha ugyanabban az utasitasban meg van vonatkozas az x-re. Az itteni peldaban nem volt ilyesmi. Akkor mit segithetne? Ez olyan mintha azt mondtad volna, hogy neha ha vizbe lepsz, megvizul a labad... Persze, igaz, de nem relevans...
Egyebkent emlekszek arra a thread-re, ott is felrebeszeltel (static meg lapozodas). Es most latom, ott kijelentetted, hogy te "SOHA" nem hasznalsz for ciklust. Miert is? Kivancsi lennek az elonyeire. Sot arra is, hogy egy continue-t hogyan oldasz meg elegansan.

2. Kiveszed a kontextusbol azt a mondatot. Ha az elotte levoket is elolvasod, akkor az jon ki az egeszbol, hogy a puffer merete miatt nem latsz garanciat a tulfutasra...

Eszelos tamadas? Elnezest, hogy ki mertelek javitani es eszerveket hozni fel, hogy meggyozzelek. Ami ugy nez ki meg mindig nem sikerult...

Az idegesit az egeszben, hogy valaki kerdez valamit, jon valaki es odavag valami dumat valaszkent, ami nemhogy nem segit, hanem ront. Es meg be sem tudod ismerni a tevedeseidet.

En csak arra szeretnelek kerni, hogy vigyazz a segitesre, mert az ilyen segites rosszabb, mint a nem segites. Egy eleg "respected" tagja vagy a hup kozossegenek, es ezert figyelnek rad az emberek. Ez felelosseggel is jar!

ok
> Sol omnibus lucet.

matthew errol beszeltem:

void torold ( char * ebbol , char * ezeket )
{
   char
      marad [ 128 ] ,      
      * tmp ;
      
   memset ( marad , 1 , 128 ) ;

   tmp = ezeket ;
   while ( ( * tmp ) != '\0' )
      marad [ * ( tmp ++ ) ] = 0 ;
   
   tmp = ebbol ;
   while ( ( * tmp ) != '\0' )
   {
      if ( marad [ * tmp ] )
         ( * ( ebbol ++ ) ) = ( * ( tmp ++ ) ) ;
      else
         tmp ++ ;
   }   
   ( * ebbol ) = '\0' ;
}

udv, ncs

ps.: ja es szerintem a 'delete' kifejezobb
nev - van 'squeeze' csak az mast kene csinaljon (man tr).
pps.: a fenti fuggveny nem mukodik, sz@r, semmi kozom hozza,
fogalmam sincs hogy kerult ide stb. :)

nagyon koszonom mindenkinek a segitseget :)
viszont most akadt egy ujabb gond, bar ez nem olyan mint az elozo...
konyvemben irnak a bitenkenti logikai operatorokrol, de fogalmam sincs mik ezek, mert nem ertek semmit ebbol a reszbol... :/ ha valaki, tudja esetleg megosztana velem?

Van "és", "vagy", "kizáró vagy", meg negáció.

"Vagy":
1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0

Pl. 53 | 89 = 125
kettes számrendszerben leírva alkalmazod a fentieket az azonos
helyiértéken álló bitekre:

0110101 (53)
1011001 (89)
--------
1111101 (125)

"És":

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0

"Kizáró vagy":

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

A negációban minden bit átfordul az ellenkezőjére, azt már nem írom le.
Tudós kollegáktól elnézést kérek, ha pongyola voltam ...

ajaj, ezeket a bites dolgokat nem ertem :S
azt sem ertem hogy a 1011001 hogy lesz 89... :(
meg egyaltalan 0kat es 1eket miert kell osszehasonlitani.

meg egyaltalan 0kat es 1eket miert kell osszehasonlitani

hatékonysági okokból.
pl. van 8 változód, de mindegyiket csak logikai kifejezésekben használod. ilyenkor logikus, hogy a 8 byte helyett 1 byte-ban is tárolhatod a 8 logikai értéket. írsz 8 makrót, amik így néznek ki:
#define FLAG_1 0x01
#define FLAG_2 0x02
#define FLAG_3 0x04
...
#define FLAG_8 0x80

az egyetlen definialt valtozod legyen a 'flags' nevu, unsigned char tipusu valtozo. a 8 logikai értéket így állítod be:
ha igazra akarod állítani a FLAG_3-at:
flags|=FLAG_3

ha hamisra:
flags&=~FLAG_3

ha az ellenkezőjére:
flags^=FLAG_3

ha pedig használni akarod, pl. így tudod:
if (flags | FLAG_3) ...

remelem soha nem lesz szuksegem erre az izere. mivel sajnos nem ertem

Szerintem akkor hagyd a C-t... Ha nem vagy kepes felfogni a kettes szamrendszert... Remelem nem vagy meg 15 eves...

Lehetne egy kicsit bovebb cimet adni a topicnak?

Koszonom. :)

---------------------
Ригидус а бетегадьбол

pl. "pls help me!!!" :)

vagy "nagy problema segitsetek"

--
Az élet harc. Délelőtt az éhséggel, délután az álmossággal.

"Segmentation faultot kapok"

velemeny? :)

---------------------
Ригидус а бетегадьбол