(Mod. siirsi rekursio-oppaan kommenteista.)
Törmäsin opettavaisen tuntuiseen esimerkkiin.
#include <iostream> using namespace std; void reverse(char *a); int main(int argc, char *argv[]) { char str[] = "This is a test"; reverse(str); } void reverse(char *a){ if (*a) reverse(a+1); else return; cout<< *a; }
Sitten kokeilin tehdä saman Javalla. Siitä tuli vähän monimutkaisempi, mutta lyhyt.
public class Ohjelma { public static void main(String[] args) { String str = "hello"; System.out.println(reverse(str, 0)); } public static String reverse (String instring, int indeksi){ if (indeksi < instring.length()){ return reverse(instring, indeksi+1)+instring.charAt(indeksi); } else return ""; } }
Saisko tämän Javalla jotenkin ytimekkäämmäksi? Onko toi kakkosparametri pakko olla?
Koitin hahmotella itselleni pinon toimintaa.
kutsu arvo pinon purkautuessa pinoon mennessä 6. kutsu palauttaa-> "" "" 5. kutsu palauttaa-> 6. kutsu + o ""o 4. kutsu palauttaa-> 5. kutsu + l ""ol 3. kutsu palauttaa-> 4. kutsu + l ""oll 2. kutsu palauttaa-> 3. kutsu + e ""olle 1. kutsu palauttaa-> 2. kutsu + h ""olleh "" tarkoittaa, että mitään ei mene merkkijonoon. str="hello"; str.length() == reverse(hello, 0).length()
lrp kirjoitti:
Saisko tämän Javalla jotenkin ytimekkäämmäksi? Onko toi kakkosparametri pakko olla?
No ton java-ohjelman saa suoraan käännettyä C++:sta näin:
public static void reverse (String a){ if (!a.isEmpty()){ reverse(a.substring(1)); } else return; System.out.print(a.charAt(0)); }
Ja niin että se palauttaa merkkijonon:
public static String reverse (String a){ if (!a.isEmpty()){ return reverse(a.substring(1))+a.charAt(0); } else return ""; }
Tyylivalitusta seuraa. Tuo alkuperäinen koodi on kyllä taas hieno esimerkki if-else-rakenteen epäselvästä käytöstä. Koodissa rekursiivinen kutsu ja merkin tulostus kuuluvat kiinteästi yhteen, joten ne olisi viisainta laittaa joko yhdessä if-lauseen sisään tai yhdessä sen ulkopuolelle. Molemmissa tapauksissa else-lohko jää tarpeettomaksi, koska funktiossa halutaan suorittaa joko molemmat olennaiset rivit tai ei kumpaakaan riviä.
Tässä molemmat rivit ovat if-lauseessa eikä else-lohkoa tarvita:
if (*a) { reverse(a + 1); std::cout << *a; }
Tässä kumpikaan rivi ei ole if-lauseessa mutta else-lohkoa ei silti tarvita, koska if-lauseen sisällä on return-lause.
if (!*a) { return; } reverse(a + 1); std::cout << *a;
Tässä ovat vastaavat koodit Javalla silloin, kun funktio palauttaa merkkijonon:
if (!a.isEmpty()) { return reverse(a.substring(1)) + a.charAt(0); } return "";
if (a.isEmpty()) { return ""; } return reverse(a.substring(1)) + a.charAt(0);
Tässä on vielä pakollinen yhden rivin versio, ettei kenenkään muun tarvitse sen takia lähettää viestiä:
return a.isEmpty() ? "" : (reverse(a.substring(1)) + a.charAt(0));
Aihe on jo aika vanha, joten et voi enää vastata siihen.