Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: Palindromitarkistus - Java

Sivun loppuun

Tommittaja [25.02.2009 21:11:09]

#

olen tehnyt tällaisen ohjelman, johon haluaisin lisätä tarkistusmetodin, onko sana palindromi vai ei, koodi on tässä:

public class Reverse {
	public static void kaanna(String rivi) {
		char taulu[] = rivi.toCharArray();
		for (int i = taulu.length-1; i>-1; --i) {
			System.out.print(taulu[i]);
		}
		System.out.println();
	}
}

mutta sitten, kun yritin tehdä tällaista metodia:

public static void palindromiTark(String rivi) {
        if (rivi.equalsIgnoreCase(kaanna(rivi)))
                System.out.println("On palindromi");
        else
                System.out.println("Ei ole palindromi");
}

mutta sitten kääntäjä herjaa, että void on väärä tyyppi, ja sitten laitan sen kaanna-metodin tämmöiseksi:

public static String kaanna(String rivi) {
	char taulu[] = rivi.toCharArray();
	for (int i = taulu.length-1; i>-1; --i) {
		System.out.print(taulu[i]);
	}
	System.out.println();
}
public static void kaanna(String rivi) {
	char taulu[] = rivi.toCharArray();
	for (int i = taulu.length-1; i>-1; --i) {
		System.out.print(taulu[i]);
	}
	System.out.println();
	return rivi;
}

mutta sen jälkeen se kyllä kääntyy, mutta kun laitan return rivi, niin se palindromiTark ei toimi oikein, enkä keksi, miten tuo tehdään(mieluiten kutsumalla tuota kaanna-metodia).

Jaska [25.02.2009 21:18:25]

#

Tuo kaanna ei palauta merkkijonoa kummassakaan tapauksessa. Sinun pitää metodissa kaanna tallentaa merkit yksi kerrallaan merkkijonoon ja lopulta palauttaa se, jos haluat, että kaanna palauttaa merkkijonon. Yksi tapa on myös tehdä metodi, joka palauttaa boolean-arvon: http://leepoint.net/notes-java/data/strings/96string_examples/example_isPalindrome.html

public static boolean isPalindrome(String word) {
    int left  = 0;                 // index of leftmost unchecked char
    int right = word.length() -1;  // index of the rightmost

    while (left < right) {         // continue until they reach center
        if (word.charAt(left) != word.charAt(right)) {
            return false;          // if chars are different, finished
        }
        left++;                    // move left index toward the center
        right--;                   // move right index toward the center
    }

    return true;                   // if finished, all chars were same
}

Päärynämies [25.02.2009 21:21:19]

#

Minun koodisilmääni tuo esittelemäsi käännä metodi ei tee muuta kuin tulostaa tuon annetun merkkijonon ilmeisestikin nurinkurisessa järjestyksessä. Sitten vielä tulostaa rivinvaihdoin.

Ja tottakai se kääntäjä herjaa tuosta void tyypistä, kun koitat tuon kaanna-metodin palautusarvoa verrata merkkijonoon. Kaanna-metodihan ei palauta mitään.

Tommittaja [25.02.2009 21:21:27]

#

tiedän, mutta hmm ajattelin, että se olisi jotenkin toiminut, mutta ei...
miten tuo sitten pitäisi tehdä, jos ei noin? mieluiten ilman mitään StringBufferia

Teuro [25.02.2009 21:23:27]

#

Alla oleva koodinpätkähän on aivan puuta heinää. Miksi käyt taulun läpi, vaikka et edes tee noilla taulukon indekseillä mitään?

Tommittaja kirjoitti:

public class Reverse {
	public static void kaanna(String rivi) {
		char taulu[] = rivi.toCharArray();
/*
		for (int i = taulu.length-1; i>-1; --i) {
			System.out.print(taulu[i]);
		}
		System.out.println();*/
	}
}

Returnin käyttö ei sitten ole vieläkään ilmeisesti ihan kirkkaana mielessä vai? return palauttaa siis jonkun erikseen annetun tyypin mukaisen arvon. Void ei ole mitään, joten se ei voi palauttaa mitään.

Tommittaja kirjoitti:

mutta sitten, kun yritin tehdä tällaista metodia:

public static void palindromiTark(String rivi) {
        if (rivi.equalsIgnoreCase(kaanna(rivi))) /* void tyyppinen kaanna metodi! */
                System.out.println("On palindromi");
        else
                System.out.println("Ei ole palindromi");
}

mutta sitten kääntäjä herjaa, että void on väärä tyyppi, ja sitten laitan sen kaanna-metodin tämmöiseksi:

Alla olevassa on sama juttu miksi suotta tulostella taulun indeksejä?

Tommittaja kirjoitti:

public static String kaanna(String rivi) {
	char taulu[] = rivi.toCharArray();
	for (int i = taulu.length-1; i>-1; --i) {
		System.out.print(taulu[i]);
	}
	System.out.println();
}

Tämä metodi on aiavn turha, koska syötät sille rivin ja palautat saman rivin metodin lopussa täysin koskematta koko riviin.

Tommittaja kirjoitti:

public static void kaanna(String rivi) {
	char taulu[] = rivi.toCharArray();
	for (int i = taulu.length-1; i>-1; --i) {
		System.out.print(taulu[i]);
	}
	System.out.println();
	return rivi;
}

mutta sen jälkeen se kyllä kääntyy, mutta kun laitan return rivi, niin se palindromiTark ei toimi oikein, enkä keksi, miten tuo tehdään(mieluiten kutsumalla tuota kaanna-metodia).

Päärynämies [25.02.2009 21:23:28]

#

Jaska kirjoitti:

Sinun pitää metodissa kaanna tallentaa merkit yksi kerrallaan merkkijonoon ja lopulta palauttaa se, jos haluat, että kaanna palauttaa merkkijonon.

Tuossahan se jo luki, että miten sen voi toteuttaa.

eq [25.02.2009 21:28:31]

#

Spoiler palindromeille (edit: toivottavasti ymmärrettävissä nyt):

Tarkista totuusarvo lauseelle merkkijono.at(i) == merkkijono.at(merkkijonon_pituus-i-1) arvoille i = 0...merkkijonon_pituus/2.

Näin ei toki pääse hienoja String-vertailuja compare():lla tekemään.

Tommittaja [25.02.2009 21:28:47]

#

miten niin "en tee noilla taulukkoindekseillä mitään"? mähän tulostan ne ja tarvitsen niitä siihen rivin "kääntämiseen", vai mitä tarkoitit?

PS: kiitos, Jaska, tuo esimerkkisi oli aika hyvä voisi kokeilla noin...

Edit: kävi itsellänikin mielessä vertailla alkioita, että onko samat, kiitos. :)

Teuro [25.02.2009 21:29:53]

#

Tommittaja kirjoitti:

miten niin "en tee noilla taulukkoindekseillä mitään"? mähän tulostan ne ja tarvitsen niitä siihen rivin "kääntämiseen", vai mitä tarkoitit?

PS: kiitos, Jaska, tuo esimerkkisi oli aika hyvä voisi kokeilla noin...

Siten niin, että ohjelmasi toimisi tehtävän kannalta aivan identtisesti ilman tuon taulun läpikäymistäkin.

Jaska [25.02.2009 21:30:37]

#

Kokeile koodia osoitteessa http://www.roseindia.net/java/beginners/StringReverseUsingStringUtils.shtml . Itselläni ei ole javaa koneessani, joten en tiedä toimiiko.

Tommittaja [25.02.2009 21:38:33]

#

Jaska, kokeilin tuota antamasi koodin linkkiä, ja minusta tuntuu, että tuo package on jonkun itse tekemä, tai ei ainakaan standardi, koska kääntäjä herjasi että: package <joku> doesn't exist...

Päärynämies [25.02.2009 21:53:55]

#

Jos valmista reverse-metodia kaipaa, niin sellanenhan löytyy jo StringBuffer-luokasta. Vai oliko aloittajalla joku erityinen syy välttää StringBufferia?

Tommittaja [25.02.2009 22:01:26]

#

halusin vain oppia toisin kun osasin jo Bufferia käyttää jotenkin

Grez [25.02.2009 22:16:37]

#

En kyllä ymmärrä miksi haluat opetella huonon tavan tehdä jokin asia. Tai ainakin mielestäni on huono tapa kirjoittaa itse huonompi versio ohjelmointikieleen sisäänrakennetusta toiminnosta.

Blaze [25.02.2009 22:28:26]

#

Kyllähän se pyörän uudelleenkeksiminen on ihan fiksua opiskelumielessä. Oikeissa jutuissa kannattaa tietenki käyttää sitä standardikirjastoa.

Grez [25.02.2009 22:41:36]

#

No joo, tässä tapauksessahan ongelma ei edes varsinaisesti ole tuo että miten se kääntäminen tehdään vaan se, että ihan perusasiat kuten funktio ja sen paluuarvo on hukassa.

Antti Laaksonen [25.02.2009 22:55:49]

#

Hauska tapa kääntää merkkijono on siirtää merkkijonon ensimmäinen merkki viimeiseksi ja kääntää sen loppuosa. Tällöin funktio voi kutsua itseään eikä aputaulukoita, silmukoita tms. tarvita.

static String kaanna(String mjono) {
    // jos merkkijono on tyhjä, kääntäminen ei vaikuta mitenkään
    if (mjono.length() == 0) return mjono;
    // käännetään loppuosa ja siirretään ensimmäinen merkki loppuun
    return kaanna(mjono.substring(1)) + mjono.charAt(0);
}

Esimerkiksi jos funktio kääntää merkkijonon "PUTKA", se kysyy ensin itseltään, mikä merkkijonon loppuosa "UTKA" on käännettynä, ja lisää tähän merkkijonon ensimmäisen merkin "P". Tulos on "AKTU" + "P" = "AKTUP".

Päärynämies [26.02.2009 00:00:43]

#

Itse tässä nyt huvikseni tein vastaavan kääntämismetodin pinon avulla, en tiedä miksi. Kuitenkin siinä tungetaan jokainen kirjan pinoon (tai tässä tapauksessa käytin merkkijonoja) ja muodostetaan uusi merkkijono laittamalla tuolta pinosta kaikki pinon alkiot peräkkäin, päällimmäinen luonnollisesti tulee ensimmäiseksi. Javana:

import java.util.Stack;

public class Reverse {

    public static String reverse(String merkkijono){
        Stack<String> pino = new Stack<String>();
        for(int i = 0; i < merkkijono.length(); i++){
            pino.push(merkkijono.substring(i,i+1));
        }
        String kaannos = "";
        while(!pino.empty())
            kaannos += pino.pop();
        return kaannos;
    }
}

Niin ja reverse(null) heittää virhettä.

Hieman turha koodinpätkä kieltämättä.

Ja kyllähän se pyörän uudelleen keksiminen voi hyödyllistä olla oppimistarkoituksessa (parempia pyöriä tuskin syntyy paljoa). Ja hyvä on myös oppia käyttämään valmiita kirjastoja.

Tommittaja [26.02.2009 21:46:08]

#

tein nyt näin:

public class Reverse {
	public static void kaanna(String rivi) {
		char taulu[] = rivi.toCharArray();
		for (int i = taulu.length-1; i>-1; --i) {
			System.out.print(taulu[i]);
		}
		System.out.println();
	}
	public static void onkoPalindromi(String rivi) {
		char taulu[] = rivi.toCharArray();
		int alku = taulu[0];
		int loppu = taulu.length;
		while (alku <= loppu) {
			++alku;
			--loppu;
			if (alku == loppu)
				System.out.println("On palindromi");
			else
				System.out.println("Ei ole palindromi");
		}
	}
	public static void main(String[] args) {
		kaanna("innostunutsonni");
		kaanna("tommi teki Tämän ohjelman Javalla!!");
		kaanna("123456789");
		onkoPalindromi("innostunutsonni");
		onkoPalindromi("Innostunutsonni");
		onkoPalindromi("Olen tehnyt taman Javalla");
	}
}

mutta jostain syystä tämä ei tulosta mitään... siis tuo onkoPalindromi-metodi.. mikä mättää?

Metabolix [26.02.2009 21:51:39]

#

Sovella taas (tai edes tämän kerran) niitä jo annettuja neuvoja, että luet funktiosi itse ja mietit, mitä se tekee. Virheesi on niin ilmiselvä ja järjetön, että kehotan vain kerrankin ajattelemaan omilla aivoillasi, mitä alku ja loppu sisältävät silmukkasi alussa ja aikana. >_>

Edit: Tässäpä vielä suomennos koodistasi: Sijoitetaan yhteen muuttujaan ensimmäisen merkin ASCII-arvo ja toiseen merkkien määrä. Kun jälkimmäisen muuttujan arvo on suurempi tai yhtäsuuri kuin ensimmäisen, katsotaan, ovatko arvot samat, ja muutetaan niitä sitten vastakkaisiin suuntiin.

Tehtävä: Montako merkkiä tämä algoritmi vertailee syötteellä "1234321"?

Grez [26.02.2009 21:55:37]

#

Komppaan tässä Metabolixia, joka ehti kirjoittaa lyhyemmin sillä aikaa kun kirjoittelin viestiäni.

No ei kai se nyt ole kovin vaikeaa pohtia hetken mitä tuossa tapahtuu:

public static void onkoPalindromi(String rivi) {
    //kutsuttu merkkijonolla innostunutsonni
    char taulu[] = rivi.toCharArray();
    int alku = taulu[0];
    //alku on merkin "i" arvo eli 105
    int loppu = taulu.length;
    //loppu on taulun pituus eli 15
    while (alku <= loppu) {
        //tämä suoritetaan niin kauan kun alku on pienempi tai yhtä suuri kuin loppu
        //eli koska 105 on suurempi kun 15, niin ei suoriteta ollenkaan
        ++alku;
        --loppu;
        if (alku == loppu)
            System.out.println("On palindromi");
        else
            System.out.println("Ei ole palindromi");
    }
}

Ja vaikka sijoittaisit tuohon alku kohtaan 0, niin siltikään se ei toimisi oikein, koska
1) se ei tarkistaisi ensimmäistä merkkiä
2) jos palindromin pituus olisi muu kuin 2 merkkiä, ilmoittaisi "Ei ole palindromi"

Tuohon samaan tyyliin, kuin tuossa havainnollistin, vaan mietit rivi kerrallaan mitä tapahtuu eri tilanteissa. Näin virheiden korjaus pitäisi olla erittäin helppoa.

Ohjelmista virheiden etsiminen on oikeasti helppoa. Ei muuta kuin otat lusikan kauniiseen käteen ja opettelet sen. Se on ihan perustaito ohjelmoinnissa. Et kuitenkaan voi jokaista kirjoittamaasi koodia tunkea foorumille ja toivoa että muut etsivät virheet.

Teuro [27.02.2009 07:08:39]

#

Tommittaja kirjoitti:

tein nyt näin:

public class Reverse {
	public static void kaanna(String rivi) {
		char taulu[] = rivi.toCharArray();
		for (int i = taulu.length-1; i>-1; --i) {
			System.out.print(taulu[i]);
		}
		System.out.println();
	}

mutta jostain syystä tämä ei tulosta mitään... siis tuo onkoPalindromi-metodi.. mikä mättää?

Tästä vielä sen verran, että tästä ei ole mitään hyötyä, koska metodi ei tee mitään seuraavan metodin (onkoPalindromi) eteen. Aivan yhtä hyvin voisit kutsua metdia onkoPalindromi suoraan. Vastaus olisi täsmälleen samanlainen.

Voisit vaikka päässä miettiä, että miten palindromi tarkastetaan. reunaehdoiksi asetetaan tietysti, että voit katsoa ainoastaan kahta merkkiä kerrallaan. Tiedossasi on siis vain merkkijonon pituus ja muuttujat kahden merkin tallentamiseen.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta