Close
Duke shfaqur rezultatin -9 deri 0 prej 9
  1. #1
    i/e regjistruar
    Anëtarësuar
    15-07-2004
    Vendndodhja
    Rome
    Postime
    62

    C - Kod që kthen një varg mbrapsh

    Kam nje problem ne C dhe do te kerkoja ndihmen tuaj per te kuptuar zgjidhjen.
    Eshte nje funksion i thjeshte i cili shtyp ne monitor ne invers nje fjale apo shprehje dhe kthen si rezultat numrin e germave te shtypura dhe eshte ndertuar ne kete menyre:


    Kodi:
    int shtyp_invers(char  *fjala) {
        int shtypja_pjesore;
    
          if (*fjala == '\0')    return 0;
        
        shtypja_pjesore = shtyp_invers(fjala+1);
    
        printf("%c", *fjala);
    
        return 1+shtypja_pjesore;
    }
    Ajo qe nuk marr vesh eshte futja e ketij numrit "shtypja_pjesore" mbas komandes "if.."sepse per te gjetur nr e germave te shtypura mund te shkruanim ne fund thjesht return 1+shtyp_invers; Tani i bie qe detyra e kesaj shtypjes_pjesore eshte te beje spostimin e treguesit ne germen pasardhese po se si e ben me kete komanden " shtypja_pjesore = shtyp_invers(fjala+1)"nje zot e di.pse mos shkruanim psh *(fjala++) per te kaluar ne germen pasardhese?kur e bej kete veprimin e fundit me dev c++ me ndodh qe nuk kalon ne germa pasardhese por ne pasardhesja e kesaj dmth kercen me 2 germa.

    Shpresoj te mos ju kem ofenduar inteligjencen me te tilla probleme po te me falni se jam ne hapat e para.flm
    Ndryshuar për herë të fundit nga edspace : 04-07-2007 më 09:14

  2. #2
    i/e regjistruar Maska e Borix
    Anëtarësuar
    17-01-2003
    Postime
    2,316
    pse mos shkruanim psh *(fjala++) per te kaluar ne germen pasardhese?
    "C" konsiderohet si gjuha e "pointerave". Meqenese emri i nje vektori, 'fjala' ne rastin tone, eshte thjesht nje pointer ne adresen ne memorie, atehere eshte me e shpejte dhe me praktike t'i referencohesh adreses pasardhese duke perdorur aritmetiken e pointerave: fjala+1, etj. Po ta jepje *(fjala++), atehere funksioni do te merrte si parameter karakterin pasardhes qe referencon pointeri fjala dhe do te nxirrte nje "warning" te tipit "different types for actual paramter 1". Per me thjesht, funksioni yt mund te konvertohet ne nje procedure void si me poshte:

    Kodi:
    void shtyp_invers(char  *fjala) {
    
        if (*fjala == '\0') return; // nese karakteri qe ndodhet ne memorien qe po referencon fjala eshet NULL, dil nga procedura
        
        shtyp_invers(fjala+1);  // kalo si parameter karakterin ne adresen pasardhese te memories dhe therrit funksionin me kete.
    
        printf("%c", *fjala); // kur mbaron rekursioni, pra therritet "return" i pare, kjo afishon karakterin qe doli nga thirrja me fundit.
                                   // pas kesaj, del cdo karakter i meparshem i ruajtur ne stakun e sistemit: nga me i fundit tek me i pari.
        return;
    }
    Funkioni rekursiv i dhene eshte mjaft i qarte. Mos harro qe cdo karakter ruhet si nje numer (char). Per sa kohe qe nuk kemi arritur tek karakteri NULL, pra tek fundi i stringut ose vektorit me karaktere 'fjala', atehere therrit vetveten me karakterin pasardhes. Kur te arrihet karakteri "NULL", ekzekutimi i funksionit vazhdon tek rreshti pasardhes, duke afishuar ne ekran te gjithe karakteret: nga me i fundi tek me i pari i vektorit fjala.

    Per shembull, e zeme se fjala = "borix\0". Ekzekutimi i funksionit vazhdon si me poshte:
    Variabli 'fjala' eshte fillimisht nje pointer tek karakteri "b" i stringut "borix". E zeme se adresa e "b" eshte 100. Ekzekutohet kodi shtyp_invers(fjala+1), ose shtyp_invers(101). Tani fjala ka vleren 101, ku ne memorien me adrese 101 eshte germa "o".
    Therritet serish kodi shtyp_invers(fjala+1); deri sa fjala te jete e barabarte me adresen e karakterit '\0'. Ne ate pike, funksioni del me rreshtin e kodit if (*fjala == '\0') return 0; . Paskesaj, fillojne te nxirren nga staku i sistemit te gjithe pjeset e kodit qe duhej te ekzekutoheshin pas rreshtit ku behet thirrja rekursive. Ne rastin tone do te printohet germa me e fundit printf("%c", *fjala); dhe do te dilet me nje vlere numerike:
    return 1+shtypja_pjesore; Pra, afishimi ne ekran do te jete: xirob.
    Ndryshuar për herë të fundit nga edspace : 04-07-2007 më 09:14
    "The rule is perfect: in all matters of opinion our adversaries are insane." (M. Twain)

  3. #3
    mos e luaj; I DEBUAR! Maska e qoska
    Anëtarësuar
    17-05-2004
    Vendndodhja
    tirane
    Postime
    837
    Shume e rende me duket per nje stack(rradhe) ajo qe ke bere aty ne ate funksion me e thjeshte do te ishte

    Kodi:
    int shtyp_invers(char  *fjala) {
        int shtypja_pjesore, gjatesia;
    
         if  (!fjala) return (EINVAL);
    
         gjatesia = strlen(fjala); //XXX: problem sigurie nese nuk kemi '\0' ne fund(duhet te kontrollojme?!
    
       for(int i = 0; i <= gjatesia/2; i++) {
                shtypja_pjesore = fjala[i];
                fjala[i] = fjala[gjatesia - i - 1];
                fjala[gjatesia - i - 1] = shtypja_pjesore;
       }
       printf("%s", *fjala);
    
        return (0);
    }
    Pak a shume se nuk eshte e testuar e shkruajta direkte ne forum .

    Sa per ++ nje mundesi eshte dhe precedenca(se kam kontrolluar) por mund te jete qe thirrja e nje funksioni ka me shume precedence sesa operatori ++.

    Gjithsesi ajo qe te ka shpjeguar Borix eshte shume e skate.
    Ndryshuar për herë të fundit nga qoska : 03-07-2007 më 12:32

  4. #4
    i/e regjistruar
    Anëtarësuar
    15-07-2004
    Vendndodhja
    Rome
    Postime
    62
    Borix procedura qe shkruajte eshte shume e qarte dhe jam shume dakort te zgjidhet ne ate menyre dhe flm per infot e sscanf megjithese ate shenjen e cuditshme nuk e gjeta dot aty.Edhe shpjegimi ishte i qarte pervecse ne fund ku thua "dhe do te dilet me nje vlere numerike:
    return 1+shtypja_pjesore; Pra, afishimi ne ekran do te jete: xirob." ,,mos doje te thoje gje "return 1+shtyp_invers(fjala+1);" apo po shpjegoje funksionin e shkruar nga mua?

    qoska nuk e di pse po edhe mua sa here qe kam te bej me manipulim fjalesh prirem ti hedh njere germat ne nje array dhe pastaj te punoj me array se jane me te kuptueshme.tek funksioni tend gjithcka shkon mire po nuk kuptova vetem ate pjesen ku thua shtypja_pjesore = fjala[i]; ku shtypja_pjesore eshte integer kurse fjala[i] i bie te jete germe ,po qe ky dev c++ nuk ma kapka si gabim.mgjth flm.

  5. #5
    mos e luaj; I DEBUAR! Maska e qoska
    Anëtarësuar
    17-05-2004
    Vendndodhja
    tirane
    Postime
    837
    Ja edhe jo ne forme array.
    Te keshilloj te perdoresh rekursivitet vetem per te thjeshtesuar zgjidhje qe shemtojne kodin si psh qe e bejne kodin te duket: if...else if .... else pastaj prape if ...else if...else .... goto etj etj per te zgjidhur/kontrolluar te njejtin parameter ose kur nuk ke probleme me madhesine e stack gje qe eshte e limituar ne nivel kerneli, pasijet 'embedded'(qe perdoren shume kohet e sotme; celulare, makine llogaritese, etj...), etj...


    Kodi:
    int shtyp_invers(char  *fjala) {
        int shtypja_pjesore, gjatesia;
    
         if  (!fjala) return (EINVAL);
    
         gjatesia = strlen(fjala); //XXX: problem sigurie nese nuk kemi '\0' ne fund(duhet te kontrollojme?!
    
       for(int i = 0; i < gjatesia/2; i++) {
                shtypja_pjesore = *(fjala+i);
                *(fjala+i) = *(fjala + (gjatesia - i - 1));
                *(fjala + (gjatesia - i - 1)) = shtypja_pjesore;
       }
       printf("%s", fjala);
    
        return (0);
    }
    Sa per ate punen e int <<->> char eshte nje nga shembujt me te mire dhe mjaft elegante per te treguar se cfare lirshmerie te ofron C .

    Ne kete rast kemi dy konvertime(cast) pa asnje warning nga compiler cfaredolloj celesi te aktivizojme sepse C ne vetvete i ruan karateret ASCII ne formen e integer por garanton qe ne nuk humbim informacion kur kthejme nga integer ne char pasi supozohet(panvaresisht se kjo eshte ne dore te perdoruesit/programuesit si shume gjera te tjera ne C) qe nuk do te kemi nje numer me te madh se (0x7F), shifra qe mund te ruhet ne nje byte.
    Po te lexosh ose perdoresh C ne kohe do te gjesh kod te tille:
    Kodi:
    .....
    ....
    int a, b;
    .....
    .....
    b = a - '0'; //Kthen a nga nje karakter ne integer; man ascii ne unix/linux
    ...
    ...
    i cili perdoret shume per gjate leximit te karaktereve numerike ose kontrollimit nese nje germe eshte brenda bashkesise ASCII.
    Ndryshuar për herë të fundit nga qoska : 04-07-2007 më 15:11

  6. #6
    i/e regjistruar Maska e Borix
    Anëtarësuar
    17-01-2003
    Postime
    2,316
    Terminator,

    Ate shpjegimin per vleren 1+shtypja_pjesore e kisha per funksionin qe ke dhene ti. Le te shqyrtojme se cila eshte vlera qe kthen funksioni yt.

    Ti deklaron nje integer me emrin shtypja_pjesore, pa i dhene nje vlere fillestare. Pra, nuk duhet supozuar se ajo fillimisht ka vleren zero. E zeme se funksionit i kemi dhene stringun "borix".

    Atehere, kur mbaron rekursioni (pra kur arrihet base case: if (*fjala == '\0') return 0;, atehere funksioni fillon te ekzekutoje te gjitha rreshtat e kodit poshte thirrjes rekursive: rreshtin printf("%c", *fjala); dhe rreshtin return 1+shtypja_pjesore;.

    Por me siper thame se variabli shtypja_pjesore nuk ka vlere fillestare dhe rreshti i fundit duhet te nxjerre ndonje warning ose gabim. Faktikisht, nuk eshte keshtu. Kur arrihet base case i rekursionit, funksioni kthen zero, prandaj, variabli shtypja_pjesore merr vleren zero ne rreshtin shtypja_pjesore = shtyp_invers(fjala+1);. Kjo do te thote se ne rreshtin return shtypja_pjesore + 1, do te kthehet vlera 1. Kjo vlere i shtohet serish variablit shtypja_pjesore ne rreshtin e thirrjes rekursive, dhe vlera behet 2. Kjo e fundit i shtohet serish ... e keshtu me rradhe deri sa arrihet karakteri i pare i stringut te dhene.

    Sic e kupton vete, vlera 1+shtypja_pjesore kthen gjatesine e stringut te dhene. Pra, ne rastin e stringut "borix", kur printohet karakteri 'x', shtypja_pjesore ka vleren 0 dhe shprehja 1 + shtypja_pjesore do te kete vleren 1, kur printohet 'i', ajo ka vleren 1 dhe shprehja vleren 2, ... , kur printohet 'b' ajo merr vleren 4 dhe shprehja merr vleren 5 dhe funksioni perfundon.
    Ndryshuar për herë të fundit nga Borix : 04-07-2007 më 16:53
    "The rule is perfect: in all matters of opinion our adversaries are insane." (M. Twain)

  7. #7
    Programues Softueresh Maska e edspace
    Anëtarësuar
    04-04-2002
    Vendndodhja
    Filadelfia, SHBA
    Postime
    2,565
    Për t'u sqaruar rreth operatorit ++, duhet të dish ndryshimin midis ++i dhe i++. Në të dyja rastet vlera e i rritet me 1, por ajo që ndryshon është koha kur ndodh rritja.

    Kur ++ përdoret si parashtesë (++i), në fillim rritet vlera e variablës, pastaj ekzekutohet shprehja që përmban variablën. Për shembull, kodi:

    Kodi:
    int i = 1; 
    printf("%d", ++i);              /* printon 2 */
    është njësoj sikur të kishim shkruar:

    Kodi:
    int i = 1; 
    i = i + 1;
    printf("%d", i);               /* printon 2 */

    Kur ++ përdoret si prapashtesë (i++), në fillim ekzekutohet shprehja që përmban variablën, pastaj rritet vlera me një. Për shembull, kodi:

    Kodi:
    int i = 1; 
    printf("%d", i++);              /* printon 1 */
    printf("%d", i);                /* printon 2 */
    është njësoj sikur të kishim shkruar:

    Kodi:
    int i = 1; 
    printf("%d", i);               /* printon 1 */
    i = i + 1;
    printf("%d", i);               /* printon 2 */

    Në kodin që kishe hedhur ti, shprehja:
    shtypja_pjesore = shtyp_invers(fjala+1);
    nuk ndryshon vlerën e fjala, por argumentit të funksionit. Kompjuteri krijon një variabël të re për argumentin, bën mbledhjen, dhe pastaj thërret funksionin shtyp_invers().

    Nëse kodi do ishte ndryshuar si
    shtypja_pjesore = shtyp_invers(fjala++);
    kompjuteri do thërrasë funksionin me vlerën e variablës fjala, pastaj e rrit vlerën e fjala-s. Pra, në këtë rast, kompjuteri do thërriste shtyp_invers gjithnjë me të njëjtën variabël deri sa të mbushet stack-u dhe të nxjerrë gabim.
    Edi

  8. #8
    i/e regjistruar Maska e Borix
    Anëtarësuar
    17-01-2003
    Postime
    2,316
    Shkurtimisht, deklarojme variablat e meposhtem:

    Kodi:
     int x, i=10;
    Veprojme si me poshte:

    Kodi:
    x = i;  // x merr vleren e i, aktualisht 10.
    
    x = i++;  // x merr vleren e i, aktualisht 10, dhe pastaj "i" rritet me 1, pra behet 11.
    
    x = ++i; // variabli i rrtet me 1, pra behet 12, ne rastin tone, pastaj kjo vlere i kalohet variablit x. Pra x = 12.
    Ndihmesa: Kur dy pluset jane perpara nje variabli, atehere FILLIMISHT, rritet vlera e variablit me 1. Nese dy pluset jane pas nje variabli, atehere vlera e atij variabli rritet ne FUND te veprimeve te tjera.
    "The rule is perfect: in all matters of opinion our adversaries are insane." (M. Twain)

  9. #9
    i/e regjistruar
    Anëtarësuar
    15-07-2004
    Vendndodhja
    Rome
    Postime
    62
    Eshte shume e kuptueshme gjithcka.Edhe kete punen e ++ e dija po nuk i kisha kushtuar rendesi te madhe.Tani cdo gje u sqarua ne detaj dhe ju falenderoj.

Tema të Ngjashme

  1. Disa krijime nga Kosovari
    Nga Kosovari_78_Ca në forumin Letërsia shqiptare
    Përgjigje: 5
    Postimi i Fundit: 04-05-2006, 14:43
  2. Te Genjej O shpirti Im.....
    Nga LoveLyBruneTT në forumin Letërsia shqiptare
    Përgjigje: 11
    Postimi i Fundit: 04-03-2006, 18:53

Regullat e Postimit

  • Ju nuk mund të hapni tema të reja.
  • Ju nuk mund të postoni në tema.
  • Ju nuk mund të bashkëngjitni skedarë.
  • Ju nuk mund të ndryshoni postimet tuaja.
  •