Apua javaohjelmointiin

Viestiketju alueella 'Ohjelmointi' , aloittaja jubideemus, 07.01.2019.

NOSTOJA MUROPAKETIN SISÄLLÖSTÄ
  1. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Taas pitää pyytää neuvoja. Toisessa aliohjelmassa (annaEkaSana) joku tökkii, koska en saa tulostamaan sukunimeä, tulostaa koko nimen. Eka aliohjelma tulostaa etunimen ihan niin kuin pitääkin.

    package Nimi;
    import fi.jyu.mit.ohj2.Syotto;

    /**
    *
    * @author juhah
    * @version Mar 28, 2019
    */
    public class Nimi {

    /**
    * @param args ei käytössä
    */
    public static void main(String[] args) {

    String nimi = Syotto.kysy("Anna sukunimi etunimi");
    StringBuilder sb = new StringBuilder(nimi);
    poistaEkaSana(sb);
    System.out.println("Terve, etunimesi on siis " + sb);
    String sukunimi = annaEkaSana(nimi);
    System.out.println("ja sukunimesi on siis " + sukunimi);
    }

    /**
    * @param sukunimi
    * @return ghthsr
    *
    */
    public static String annaEkaSana(String sukunimi) {
    StringBuilder sn = new StringBuilder(sukunimi);
    int poisto2 = sn.indexOf(" ");
    int poisto3 = sn.length();
    StringBuilder annaEkaSana = sn.delete(poisto2, poisto3);
    return sukunimi;

    }

    /**
    * @param sb
    */
    public static void poistaEkaSana(StringBuilder sb) {
    int poisto = sb.indexOf(" ");
    StringBuilder poistaEkaSana = sb.delete(0, poisto);

    }

    }
     
  2. telcoM

    Rekisteröitynyt:
    27.08.2015
    Viestejä:
    679
    Kokeillaanpas näin: Miten selittäisit omin sanoin, rivi riviltä, mitä tässä aliohjelmassa tapahtuu?

    Koodi:
    public static String annaEkaSana(String sukunimi) {
    StringBuilder sn = new StringBuilder(sukunimi);
    int poisto2 = sn.indexOf(" ");
    int poisto3 = sn.length();
    StringBuilder annaEkaSana = sn.delete(poisto2, poisto3);
    return sukunimi;
    
    }
    
    Usein jonkin koodipätkän sisältämän virheen tajuaa helpommin kun on selittämässä sen toimintaa jollekin toiselle. Se toki toimii parhaiten jos selityksen vastaanottaja osaa tehdä fiksuja kysymyksiä, mutta koska pelkkä selityksen muotoileminen sanalliseen muotoon riittää usein ongelman hoksaamiseen, voi kokeilla koodin toiminnan selittämistä vaikka pehmolelulle tai mielikuvituskaverille.
     
  3. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Tällä koodilla alkoi toimia.

    public static String annaEkaSana(String kokonimi) {

    int index = kokonimi.indexOf(' ');
    String sukunimi = kokonimi.substring(0, index);

    return sukunimi;
    }
     
    Viimeksi muokattu: 03.04.2019
  4. telcoM

    Rekisteröitynyt:
    27.08.2015
    Viestejä:
    679
    Eli hoksasit että tuo ensimmäinen versio annaEkaSana-aliohjelmasta sai parametriksi merkkijonon jonka nimeksi on annettu "sukunimi", kopioi sen StringBuilderiin nimeltä "sn", muokkasi "sn":ää mutta ei koskaan tullut lähettäneeksi sen sisältöä takaisin pääohjelmalle, vaan sen sijaan palautti alkuperäisen muokkaamattoman "sukunimi"-merkkijonon joka siis sisälsi koko nimen?

    Kenties harhautit itseäsi antamalla tuon merkkijonoparametrin nimeksi "sukunimi", vaikka se ei oikeasti ollut sitä: sitten syvennyit miettimään miten etunimen saa poistetuksi, teit sen StringBuilderilla, ja ensimmäinen yritys tuloksen palautuksesta pääohjelmalle ei onnistunut. Sitten keskityit ratkaisemaan sitä osaongelmaa, ja hupsis! palautitkin väärän merkkijonon. Sellaista sattuu.

    Olisi sen saanut toimimaan StringBuilderiakin käyttäen, olisi vaan pitänyt pitää huoli siitä että StringBuilderin sisältö palautetaan oikeassa muodossa: koska aliohjelman tyyppi on "public static String" eikä "jotain StringBuilder", silloin aliohjelman pitää palauttaa nimen omaan String eikä StringBuilder-oliota.

    Vaikka näin:
    Koodi:
    ...
    int poisto3 = sn.length();
    StringBuilder annaEkaSana = sn.delete(poisto2,poisto3); //annaEkaSana on tässä huono nimivalinta
    return annaEkaSana.toString();
    
    tai turhia välivaiheita välttäen:
    Koodi:
    ...
    int poisto3 = sn.length();
    return sn.delete(poisto2, poisto3).toString();
    
     
    Viimeksi muokattu: 04.04.2019
  5. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Joo. Kyllä sitä tuli tahkottua pitkään, mutta lopulta se ratkesi. Projekti jatkuu muiden tehtävien kanssa, eli lisää kysymyksiä on luvassa....Kiitos tähän astisesta avusta molemmille!
     
  6. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Pieniä haasteita on alla olevassa koodissa. Onnistun saamaan piirtämään suurimalle arvolle punaisen pallon asteikolle, mutta pienimmälle en saa vihreää. Tai sitten toisin päin. Jotenkin ei nyt taas aukea, miksi saa jomman kumman, mutta ei molempia. Veikkaan, että niissä pienimmän ja suurimman arvon lauseissa on jotain pielessä. Mutta mitä niin se ei nyt aukea.

    package luvutGraafisesti;

    import java.awt.Color;

    import fi.jyu.mit.graphics.Axis;
    import fi.jyu.mit.graphics.Marker;
    import fi.jyu.mit.graphics.Window;


    public class LuvutGraafisesti {
    //#STATICIMPORT

    /**


    public static double suurin(double[] luvut) {
    if ( luvut.length == 0 ) return 0.0;
    double max = luvut[0];
    for (int i=1; i<luvut.length; i++)
    if ( max < luvut ) max = luvut;
    return max;
    }
    /**
    * @param luvut2
    * @return palauttaa pienimmän luvun
    */
    public static double pienin(double[] luvut2) {
    if ( luvut2.length == 0 ) return 0.0;
    double min = luvut2[0];
    for (int j=1; j<luvut2.length; j++)
    if ( luvut2[j] < min ) min = luvut2[j];
    return min;
    }
    /**
    * Aliohjelmalla piirretään ikkunaan kuva, jossa taulukon
    * jokainen alkio on kuvattuna ympyrällä. Muut mustalla, paitsi
    * taulukon suurinta arvoa edustavat punaisella.
    * @param ikkuna johon piirretään
    * @param luvut taulukon alkiot
    */
    public static void piirraKuva(Window ikkuna, double[] luvut) {
    double max = suurin(luvut);
    double r = 0.25;

    for (int i=0; i<luvut.length; i++) {
    Marker ympyra = new Marker(i,luvut,r);
    if ( luvut == max ) // harvinaista kyllä, == toimii reaaliluvuille tässä!
    ympyra.setColor(Color.RED);
    ikkuna.add(ympyra);
    }
    }
    /**
    * @param ikkuna
    * @param luvut
    */
    public static void piirraKuva2(Window ikkuna, double[] luvut) {
    double min = pienin(luvut);
    double r = 0.25;

    for (int j=0; j<luvut.length; j++) {
    Marker ympyra = new Marker(j,luvut[j],r);
    if ( luvut[j] == min ) // harvinaista kyllä, == toimii reaaliluvuille tässä!
    ympyra.setColor(Color.GREEN);
    ikkuna.add(ympyra);
    }
    }

    /**
    * Piirretään kuvaaja luvuista. Suurimmat arvot piirretään punaisella.
    * @param args ei käytössä
    */
    public static void main(String[] args) {
    //double luvut2[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    // 0 1 2 3 ...
    double luvut[] = {3, 5, 3, 9, 21, 30, 6, 4};
    Window ikkuna = new Window(600,400);
    double max = suurin(luvut);
    double min = pienin(luvut);
    ikkuna.scale(0,-1,luvut.length,max+1);
    ikkuna.add(new Axis(100,max*2,0));
    piirraKuva(ikkuna,luvut);
    piirraKuva2(ikkuna,luvut);
    ikkuna.showWindow();

    }

    }
     
  7. telcoM

    Rekisteröitynyt:
    27.08.2015
    Viestejä:
    679
    Teepäs tuohon pääohjelmaan piirraKuva() ja piirraKuva2()-aliohjelmakutsujen väliin ensin ikkuna.showWindow() ja sitten jotakin joka pitää pienen tauon tai vaikka odottaa näppäimenpainallusta (kysy vaikka käyttäjältä jotakin) ennen kuin jatkaa eteenpäin. Aja ohjelma ja katso tarkkaan. Mitä näet?
     
    Viimeksi muokattu: 08.04.2019
  8. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Ok. Kun saa aikaan pienen viiveen näkyy punaisena se suurimman arvon pallo. Sitten se muuttuu mustaksi. Miksi? Nyt ei ymmärrä miksi näin käy.
     
  9. telcoM

    Rekisteröitynyt:
    27.08.2015
    Viestejä:
    679
    Pidä se viive toistaiseksi paikallaan, ja lisää tuohon jälkimmäiseen eli piirraKuva2()-aliohjelmaan värin valitsevaan if-lauseeseen else-osuus siten että se piirtää edelleen pienimmän luvun vihreällä ja sitten muuten käyttää vaikka sinistä väriä. Aja, ja katso mitä tapahtuu. Joko nyt hoksaat?

    Tai mieti näin: mitä piirräKuva() tekee silloin kun käsiteltävä luku ei ole suurin? Entä mitä piirräKuva2() tekee silloin kun käsiteltävä luku ei ole pienin? Mitä tapahtuu kun näiden kahden aliohjelman piirtämät kuvat pannaan päällekkäin niin että piirräKuva2():n tuotos on päällimmäisenä?
     
    Viimeksi muokattu: 10.04.2019
  10. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Jes! Nyt alkoi sujua. Kiitos! Tässä lopullinen koodi. Pääsin eroon toisesta aliohjelmasta kun vähän mietin uudelleen vinkkisi perusteella. Toinen aliohjelma ikäänkuin jyräsi ensimmäisen yli kuvassa.

    Koodi:
    package luvutGraafisesti;
    
    import java.awt.Color;
    
    import fi.jyu.mit.graphics.Axis;
    import fi.jyu.mit.graphics.Marker;
    import fi.jyu.mit.graphics.Window;
    
    /**
     * Ohjelmalla piirretään kuvaaja luvuista
     
     */
    public class LuvutGraafisesti {
    
      
        /**
         * [USER=11477]@param[/USER] luvut
         * @return
         */
        public static double suurin(double[] luvut) {
            if ( luvut.length == 0 ) return 0.0;
            double max = luvut[0];
            for (int i=1; i<luvut.length; i++)
                if ( max < luvut ) max = luvut;
            return max;
        }
        /**
         * [USER=11477]@param[/USER] luvut2
         * @return palauttaa pienimmän luvun
         */
        public static double pienin(double[] luvut2) {
            if ( luvut2.length == 0 ) return 0.0;
            double min = luvut2[0];
            for (int j=1; j<luvut2.length; j++)
                if ( luvut2[j] < min ) min = luvut2[j];
            return min;
        }
        /**
         * Aliohjelmalla piirretään ikkunaan kuva, jossa taulukon
         * jokainen alkio on kuvattuna ympyrällä.  Muut mustalla, paitsi
         * taulukon suurinta arvoa edustavat punaisella.
         * [USER=11477]@param[/USER] ikkuna johon piirretään
         * [USER=11477]@param[/USER] luvut taulukon alkiot
         */
        public static void piirraKuva(Window ikkuna, double[] luvut) {
            double max = suurin(luvut);
            double min =pienin(luvut);
            double r = 0.25;
          
            for (int i=0; i<luvut.length; i++) {
                Marker ympyra = new Marker(i,luvut,r);
                if ( luvut == max )  // harvinaista kyllä, == toimii reaaliluvuille tässä!  
                    ympyra.setColor(Color.RED);
                else if ( luvut == min )  // harvinaista kyllä, == toimii reaaliluvuille tässä!  
                    ympyra.setColor(Color.GREEN);
                else ympyra.setColor(Color.BLUE);
               ikkuna.add(ympyra);
            }
        }
          
        /**
         * Piirretään kuvaaja luvuista.  Suurimmat arvot piirretään punaisella.
         * [USER=11477]@param[/USER] args ei käytössä
         */
        public static void main(String[] args) {
            //double luvut2[] = {31,28,31,30,31,30,31,31,30,31,30,31};
            //                0  1  2  3 ...
            double luvut[] = {3, 5, 3, 9, 21, 30, 6, 4};
            Window ikkuna = new Window(600,400);
            double max = suurin(luvut);
            double min = pienin(luvut);
            ikkuna.scale(0,-1,luvut.length,max+1); 
            ikkuna.add(new Axis(100,max*2,0));
            piirraKuva(ikkuna,luvut);
            ikkuna.showWindow();      
            piirraKuva(ikkuna,luvut);
            ikkuna.showWindow();
    
        }
    
    }
    
     
    Viimeksi muokattu: 14.04.2019 klo 14:24
  11. telcoM

    Rekisteröitynyt:
    27.08.2015
    Viestejä:
    679
    Hyvä, hoksasit että aina ei ole tarpeen tehdä omaa aliohjelmaa vaan asioita voi yhdistellä jos se on tarkoituksenmukaista.

    Mutta taitaapa olla että tuonne on jäänyt pari juttua jotka vaatisivat vähän huomiota.
    Ensinnäkin, kun siivosit tuon piirraKuva2()-aliohjelman pois, ajatus ei tainnut mennä ihan loppuun asti.

    Koodi:
    piirraKuva(ikkuna, luvut);
    ikkuna.showWindow();
    piirraKuva(ikkuna, luvut);
    ikkuna.showWindow();
    
    Kutsut piirraKuva()-aliohjelmaa kahdesti, samalla syötteellä kummallakin kerralla. Tekeekö toinen kerta mitään mitä ensimmäinen kerta ei olisi jo tehnyt?

    Ja sitten sellainen pieni asia, että kun kopioit ohjelmakoodia tänne, kannattaa kehystää se [code]...[/code] - tageilla, niin rivit kuten
    Koodi:
    if ( max < luvut[i] ) max = luvut[i];
    
    näkyvät oikein eikä rivin loppu ja koodi siitä eteenpäin muutu kursiiviksi. [i] on nimittäin myös foorumin käyttämä BBCode kursiivi-muotoilukoodi.
     
  12. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Ok. Taisin olla turhan innoissani onnistumisesta, että jäi tuo toinen kutsu turhaan roikkumaan. Ok pitää muistaa tuo kehystys jatkossa. Kiitos avusta taas kerran!!
     
  13. jubideemus

    Rekisteröitynyt:
    04.01.2019
    Viestejä:
    19
    Hei taas! Nyt on ongelmana kertotaulun muokkaaminen. Pitäisi saada aikaiseksi while-silmukka, jossa annetaan kerrottava luku ja toinen luku, joka määrää montako kertaa luku kerrotaan.
    Tehtävä:
    Tee vielä tulostaKertotauluWhile(n,m), joka tulostaa n:än kertotaulusta m-riviä. Toteutus while-silmukalla. Esimerkiksi tulostaKertotauluWhile(3,5) tulostaisi:
    1 * 3 = 3
    2 * 3 = 6
    3 * 3 = 9
    4 * 3 = 12
    5 * 3 = 15

    Oma yritykseni on tässä:

    Koodi:
     
    package Kertotaulu;
    
    import java.util.Scanner;
    /**
     *
     * @author juhah
     * @version Apr 11, 2019
     */
    public class Kertotaulu2 {
      /**
     *
     */
    public void aja() {
          Scanner syote = new Scanner(System.in);
          int luku;
         
          System.out.print("Syota luku: ");
          luku = syote.nextInt();
          //tulostaKertotaulu(luku);
    
          Scanner syote2 = new Scanner(System.in);
          int kertoja;
         
          System.out.print("Syota kertoja: ");
          kertoja = syote.nextInt();
          tulostaKertotauluWhile(luku, kertoja);
      }
    
      /**
     * @param luku
     * @param kertoja
     */
    /*public void tulostaKertotaulu(int luku) {
          for(int i = 1; i <= 10; i++){
              System.out.println(i + " * " + luku + " = " + luku * i);
          }
          System.out.println(luku + ":n kertotaulu");
      }
      */
    /**
     * @param luku
     * @param kertoja
     */
    public void tulostaKertotauluWhile(int luku, int kertoja) {
            int i = 1;
            while(i <= kertoja){
              System.out.println(i + " * " + kertoja + " = " + luku * kertoja);
              i++;
          }
           
          System.out.print(luku + ":n kertotaulu");
      }
      /**
     * @param args
     */
    public static void main(String[] args) {
          Kertotaulu olio = new Kertotaulu();
          olio.aja();
      }
    }
     
  14. telcoM

    Rekisteröitynyt:
    27.08.2015
    Viestejä:
    679
    Ja mikä oli ongelma? Oliko virheilmoitus jotakin tällaista?

    Koodi:
    Kertotaulu2.java:59: error: cannot find symbol
          Kertotaulu olio = new Kertotaulu();
          ^
      symbol:   class Kertotaulu
      location: class Kertotaulu2
    Kertotaulu2.java:59: error: cannot find symbol
          Kertotaulu olio = new Kertotaulu();
                                ^
      symbol:   class Kertotaulu
      location: class Kertotaulu2
    2 errors
    
    Virheilmoituksiin kannattaa kiinnittää huomiota, koska niiden tarkoitus on avustaa ohjelmoijaa.
    Tässä tapauksessa ollaan luokassa Kertotaulu2, mutta rivillä 59 tarvitaan luokkaa nimeltä Kertotaulu (ilman kakkosta). Käviköhän taas niin että lähdit muuttamaan aikaisempaa versiota luokasta eri nimelle, mutta et sitten muuttanut kaikkia viittauksia siihen uudelle nimelle?

    Aina kun muutat jonkin ohjelmassa käytössä olevan nimen joksikin muuksi, muutos pitää yleensä tehdä vähintään kahteen paikkaan:
    * sinne missä nimi määritellään
    * sinne missä sitä käytetään (näitä paikkoja voi olla monta)

    Editorin tai IDE:n "etsi ja korvaa"-toiminto on tässä suureksi avuksi.

    Vai oliko tuo vain tänne postattuun koodiin jäänyt typo, ja varsinainen ongelma oli se että tulostaKertotauluWhile() tulostaa väärin? Näyttäisi vähän siltä että silmukan System.out.println()-rivillä on ajatus katkennut ja muuttujat menneet vähän sekaisin.

    Katsopa tuota riviä uudestaan, ja mieti mikä muuttuu jokaisella silmukan kierroksella ja mikä pysyy vakiona. tulostaKertotauluWhile()-aliohjelman kakkosparametri kertoo kuinka monta riviä halutaan tulostaa, mutta itse laskutoimitukseen kullakin rivillä sillä ei pidä olla mitään vaikutusta.
     
Tagit:

Jaa tämä sivu

Alibi
Anna
Deko
Dome
Erä
Hymy
Kaksplus
Kippari
Kotilääkäri
Kotiliesi
Koululainen
Ruoka.fi
Parnasso
Seura
Suomen Kuvalehti
TM Rakennusmaailma
Tekniikan Maailma
Vauhdin Maailma
Golfpiste
Vene
Nettiauto
Ampparit
Plaza
Muropaketti