Ayuda con ejercicio escolar sobre arrays

Hola,
Primero que nada quiero darme unas lineas para felicitar este foro y la pagina en general, siento que tendre mucho uso de ella ya que estoy estudiando Java y varias cosas que no encuentro en los libros y apuntes que recomiendan en la Universidad.

A proposito de lo mismo me he complicado de manera increible con el ultimo ejercicio de la primera parte del curso de Java. El ejercicio consiste en leer un archivo de texto y crear arrays a partir de él para finalmente mostrarlos ordenados alfabeticamente.

El archivo de texto esta creado de la siguiente manera:


Elvis_Presley Jailhouse_Rock Rock RCA 1991 17 72,23
Massive_Attack Protection
Massive_Attack Blue_Lines
Test_Iscicles Circle_Square_Triangle Ska NoLabel 1995 2 9,12

Cada linea de este archivo representara un array (o un CD) y cada pieza de infromacion de cada linea es un elemento del array, asi por ejemplo si tomo la segunda linea del archivo (el segundo array) el array seria:

array2[0] = Massive_Attack
array2[1] = Protection

Para leer este array he creado una clase llamada Labb4 que se ve como sigue:

  1. import java.io.*;
  2. import java.util.Scanner;
  3.  
  4. public class Labb4 {
  5.  
  6.     public static void main(String args[]) {
  7.         String array[] = new String[10];
  8.  
  9.         try {
  10.             BufferedReader lineReader = new BufferedReader(new FileReader("skivor.txt"));
  11.  
  12.             String textLines;
  13.             while ((textLines = lineReader.readLine()) != null) {
  14.                 Scanner textFile = new Scanner(lineReader);
  15.                 String artist = textFile.next();
  16.                 String album = textFile.next();
  17.                 String genre = textFile.next();
  18.                 String label = textFile.next();
  19.  
  20.  
  21.                }
  22.  
  23.  
  24.             lineReader.close();
  25.         } catch (IOException ioe) {
  26.             System.out.println("Error de lectura del archivo");
  27.         }
  28.     }
  29. }

En esta clase estoy inicializando un array con 10 posiciones tan solo para probar. Luego leo el documento de texto, separo cada pieza de informacion y les asigno un nombre de variable. En este punto debo crear un objeto de la clase CD con los datos leidos en el while y luego agregar este objeto en un array.
Para ordenar alfabeticamente los arrays se debe utilizar un metodo llamado "sort" que se encuentra en una clase llamada CD, esta es una clase que fue utilizada en un ejercicio anterior y se debe volver a utilizar. Esta clase se ve de la siguiente manera:

  1. /*
  2.  * To change this template, choose Tools | Templates
  3.  * and open the template in the editor.
  4.  */
  5.  
  6. /**
  7.  *
  8.  * @author Americo Perez
  9.  * @date 16-11-2010
  10.  * @kurs Java I (dt006g)
  11.  * @Labb Laboration 2
  12.  *
  13.  */
  14. public class CD {
  15.     private String artist, title, genre, recordLabel, nothing;
  16.     private double playTime;
  17.     private int releaseYear, numberSongs;
  18.  
  19.     public CD() {
  20.  
  21.     }
  22.  
  23.  
  24.     //Constructor for the cd with brief information
  25.     public CD (String artist, String title, int releaseYear) {
  26.         this.artist = artist;
  27.         this.title = title;
  28.         this.releaseYear = releaseYear;
  29.     }
  30.  
  31.  
  32.     //Constructor for the cd with full information
  33.     public CD (String artist, String title, String genre, String skivbolag, int releaseYear, int numberSongs, double playTime) {
  34.         this(artist, title, releaseYear);
  35.         this.genre = genre;
  36.         this.recordLabel = skivbolag;
  37.         this.releaseYear = releaseYear;
  38.         this.numberSongs = numberSongs;
  39.         this.playTime = playTime;
  40.     }
  41.  
  42.  
  43.     //Array Sortering
  44.     public sort(CD[] skivor) {
  45.  
  46.         // Aqui tengo que ordenar el array alfabeticamente
  47.  
  48.     }
  49.  
  50.  
  51.  
  52.  
  53.     //Setting and getting the information from Labb2.java class
  54.  
  55.     public void setEmpty(String empty) {
  56.         nothing = empty;
  57.     }
  58.  
  59.     public String getEmpty() {
  60.         return nothing;
  61.     }
  62.  
  63.     public void setArtist(String name) {
  64.         artist = name;
  65.     }
  66.  
  67.     public String getArtist() {
  68.         return artist;
  69.     }
  70.  
  71.     public void setTitle(String titleName) {
  72.         title = titleName;
  73.     }
  74.  
  75.     public String getTitle() {
  76.         return title;
  77.     }
  78.  
  79.     public void setGenre(String genreName) {
  80.         genre = genreName;
  81.     }
  82.  
  83.     public String getGenre() {
  84.         return genre;
  85.     }
  86.  
  87.     public void setSkivbolag(String recordLabelName) {
  88.         recordLabel = recordLabelName;
  89.     }
  90.  
  91.     public String getSkivbolag() {
  92.         return recordLabel;
  93.     }
  94.  
  95.     public void setReleaseYear(int releaseDate) {
  96.         releaseYear = releaseDate;
  97.     }
  98.  
  99.     public int getReleaseYear() {
  100.         return releaseYear;
  101.     }
  102.  
  103.     public void setNumberSongs(int songsNumber) {
  104.         numberSongs = songsNumber;
  105.     }
  106.  
  107.     public int getNumberSongs() {
  108.         return numberSongs;
  109.     }
  110.  
  111.     public void setPlayTime(double cdPlayTime) {
  112.         playTime = cdPlayTime;
  113.     }
  114.  
  115.     public double getPlayTime() {
  116.         return playTime;
  117.     }
  118.  
  119.  
  120.     //Create the printBrief metod which will print some information.
  121.     public void printBrief() {
  122.         System.out.println("Artist      : " + getArtist() + "\nAlbums namn : " + getTitle() + "\nUtgivningsår: " + getReleaseYear());
  123.     }
  124.  
  125.     //Create the printFull metod which will print all the information.
  126.     public void printFull() {
  127.         System.out.println("Artist      : " + getArtist() + "\nAlbums namn : " + getTitle() + "\nGenre       : " + getGenre() + "\nSkivbolag   : " + getSkivbolag() + "\nUtgivningsår: " +
  128.                 getReleaseYear() + "\nAntal låtar : " + getNumberSongs() + "\nSpeltid     : " + getPlayTime() + " minuter.");
  129.     }
  130. }

Mi problema es como crear el CD objeto en la clase Labb4 y agregarlo al array y despues como lo ordeno en el metodo "sort".
Otra exigencia del ejercicio es que los arrays ordenados alfabeticamente deben ser escritos a un nuevo archivo de texto. Pero quiero pensar en este ultimo paso una vez que haya solucionado lo anterior.
Dos restricciones son que no se puede utilizar Arrays.sort o Collections.sort

Cualquier idea, ejemplo, lo que sea se los agradecere. Realmente no encuentro como resolver este ejercicio.

Antemano muchas gracias
//Americo

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Para agregar elementos a un arreglo.

Si te fijas en la linea 33 de la clase CD tienes un constructor que recibe todos los datos necesarios para crear el objeto, y en la línea 18 de Labb4 ya tienes todos los datos.

Entonces, basta con que lo invoques:

...
CD cd = new CD( artist, title genre ...etc. ec
...

Si no tienes toda la información puedes dejar algunos datos en nulo.

...
CD cd = new CD( artist, null, genre, null ,  ...etc. ec
...

Otra opción es crear el objeto y "settear" los valores que si tengas:

CD cd = new CD();
cd.setArtist( textFile.next());
cd.setAlbum(textFile.next());
cd.setGenre(textFile.next());
cd.setLabel(textFile.next());

Luego ( o antes ) tendrías que cambiar el tipo de tu arreglo, por que ahora mismo es de strings y tu necesitas que sea de CD's

En la linea 7

    CD[] array = new CD[ 10 ];
...

Y agregarlo:

CD cd = new CD();
...
array[ i ] = cd; // coloca el nuevo objeto cd en la posición "i"

Obvio tienes que crear e incrementar la variable i, ahi te queda de ejercicio esa parte.

Para el ordenamiento:

En la línea 44 de CD ya está definido la firma del método de ordenamiento:

public sort(CD[] skivor) {

( en mi opinión debería de ser un método de clase : public static sort( CD[] skivor ) )

Luego lo que tienes que hacer es implementar algún algoritmo de ordenamiento. El más sencillo es "bubble sort" o de burbuja.

En la Wikipedia viene un ejemplo en Java utilizando números. Lo que lo hace más interesante es que tu tienes que ordenar CD's, bajo algún criterio y no números. Para entender como funcionaría y como podrías hacer este ordenamiento con algún elemento no numérico ( que puede ser comparado con el operador > ) revisa mi explicación en una pregunta similar.

Haz un intento, y postea de nuevo con lo que tengas y donde te estas otorando.

Me he quedado atorado

Gracias por tu tiempo, en realidad necesito una ayuda con esto,

En realidad un poco atorado. He aplicado los consejos que me has dado pero hay algo que no quiere funcionar.
Mi clase Lab4 se ve de esta manera ahora:

import java.io.*;
import java.util.Scanner;

public class Labb4 {
   
    public static void main(String args[]) {
        CD[] myArray = new CD[10];
        try {
            BufferedReader lineReader = new BufferedReader(new FileReader("skivor.txt"));

            String textLines;
            while ((textLines = lineReader.readLine()) != null) {
               
               
                for (int index = 0; index < myArray.length; index++) {

                    Scanner textFile = new Scanner(lineReader);
                   
                    CD cd = new CD();
                    cd.setArtist(textFile.next());
                    cd.setTitle(textFile.next());
                    cd.setGenre(textFile.next());
                    cd.setSkivbolag(textFile.next());
                   
                    cd.printArray();
                   
                    myArray[index] = cd;

                } // end for

            } // end while

            lineReader.close();

        } catch (IOException ioe) {

            System.out.println("Error de lectura del archivo");

        }

    } // end Main
}

para probarla he creado un objeto llamado "printArray" en la clase CD que solamente imprime los "get", sin mensajes de textos o similares.
Pero el resultado esta lejos de ser lo esperado. Al probar la clase la primera linea del archivo de texto no se imprime, la segunda y tercera linea se imprimen como si fuera una sola y la cuarta tampoco se imprime.

Esto es lo que me entrega la consola:

Exception in thread "main" java.util.NoSuchElementException
Massive_AttackProtectionMassive_AttackBlue_Lines

        at java.util.Scanner.throwFor(Scanner.java:838)
        at java.util.Scanner.next(Scanner.java:1347)
        at Labb4.main(Labb4.java:29)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

Cual es el problema??

Estoy leyendo tu post sobre el argoritmo de ordenamiento, tan pronto solucione este problema pondre en practica lo que escribes en el post.
/Americo

El problema no estuvo en la

El problema no estuvo en la impresión, sino en que quisiste leer un elemento que no existe , quizá tu archivo no tiene todos los datos. Al menos eso es lo que dice tu stacktrace

Exception in thread "main" java.util.NoSuchElementException
Massive_AttackProtectionMassive_AttackBlue_Lines
        at java.util.Scanner.throwFor(Scanner.java:838)
        at java.util.Scanner.next(Scanner.java:1347)
        at Labb4.main(Labb4.java:29) <------------------------------------------- AQUI

Dice que en la linea 29 invocaset el métod next de Scanner y que no había el elemento que buscabas.

En fin, como alternativa puedes sobrescribir el método "toString()" de la clase CD y temporalmente usar el método toString de la clase Arrays

class CD {
...
   public String toString() {
        return "CD[ titile:"+title+", artist:"+artist+"]"; // etc. etc
    }
...

Y luego :

System.out.println( Arrays.toString( unArreglo ) );

Itera todo el arreglo e imprime sus valores

Mmmmm......

No se si estoy cansado o ya se me esta acabando la capacidad de comprension.
No tengo ningun metodo toString en la clase CD y lo otro es que en el archivo de texto no todas las lineas (o cd) contienen la misma informacion. En lagunos casos tiene nombre, titulo, tiempo de reproduccion y en otras solamente nombre y titulo.

Elvis_Presley Jailhouse_Rock Rock RCA 1991 17 72,23
Massive_Attack Protection
Massive_Attack Blue_Lines
Test_Iscicles Circle_Square_Triangle Ska NoLabel 1995 2 9,12

Por lo que la clase lab4 deberia ser capaz de diferenciar que informacionn imprimira por cada array.

/Americo

Precisamente, la sugerencia

Precisamente, la sugerencia es que lo tuvieras. En fin, el problema está en que en cada CD ( en cada linea ) tu esperas encontrar exactamente el mismo número de campos.

edit Un momento, me parece que está batiendo todo. En la linea 13 de Labb4, estas creando un Scanner con todo el archivo y en la linea 12 estas iterando todo el archivo.

Debes de crear un Scanner con la linea actual solamente.

Aún así, si tienes un número disparejo de elementos por línea el scanner fallará, mira:

import java.util.Scanner;
class ScannerDemo {
        public static void main( String [] args ) {
                // la linea tiene 2 elementos y se intentarán leer 3
                Scanner s = new Scanner("a b");
                s.next();
                s.next();
                s.next();
        }
}

Al correrlo:

C:\>java ScannerDemo
Exception in thread "main" java.util.NoSuchElementException
        at java.util.Scanner.throwFor(Unknown Source)
        at java.util.Scanner.next(Unknown Source)
        at ScannerDemo.main(ScannerDemo.java:7)

Te parece conocido?

OK, no hope

Voy a comenzar todo de nuevo desde cero, Estoy muy confundido y creo que es mejor partir desde cero nuevamente.

A medida que vaya creando algo nuevo ire posteandolo para conocer tus comentarios.

/Americo

Aqui esta el codigo reescrito

He reescrito la clase Lab4 y me he encontrado con el primer problema.

import java.io.*;
import java.util.Scanner;

public class Labb4 {

    public static void main(String args[]) {
        CD[] myArray = new CD[4];
        File file = new File("skivor.txt");
        try {

            Scanner lineReader = new Scanner(file);

            while (lineReader.hasNextLine()) {

                String textLine = lineReader.nextLine();

                for (int row = 0; row < myArray.length; row++) {

                    Scanner line = new Scanner(textLine); // el problema es aqui!!!

                    CD cd = new CD();
                    cd.setArtist(line.next());
                    cd.setTitle(line.next());

                    cd.printArray();

                }
            }

            lineReader.close();

        } catch (IOException ioe) {

            System.out.println("Error de lectura del archivo");

        }

    } // end Main
}

Con este codigo obtengo los arreglos pero mal iterizados.

run:
Elvis_PresleyJailhouse_Rock

Elvis_PresleyJailhouse_Rock

Elvis_PresleyJailhouse_Rock

Elvis_PresleyJailhouse_Rock

Massive_AttackProtection

Massive_AttackProtection

Massive_AttackProtection

Massive_AttackProtection

Massive_AttackBlue_Lines

Massive_AttackBlue_Lines

Massive_AttackBlue_Lines

Massive_AttackBlue_Lines

Test_IsciclesCircle_Square_Triangle

Test_IsciclesCircle_Square_Triangle

Test_IsciclesCircle_Square_Triangle

Test_IsciclesCircle_Square_Triangle

BUILD SUCCESSFUL (total time: 0 seconds)

El problema esta en la linea:

Scanner line = new Scanner(textLine);

Si no me equivoco el parametro del Scanner deberia ser "row" ya que es row quien tiene la linea actual, pero al intentar usar "row" Netbeans me reclama diciendo que no puede encontrar el constructos Scanner(int).

Por que y como puedo solucionar este problema?
A proposito, he simplificado el archivo de texto y ahora tiene solamente nombre de artista y album. Todas las lineas tienen la misma cantidad de informacion
mas adelante agregare mas informacion en el archivo y vere como se comporta la clase.

/Americo

Imagen de neko069

Por lo que entiendo, dentro

Por lo que entiendo, dentro de tu arreglo, deberías descomponer la línea por "tokens"
lo puedes hacer con StringTokenizer o textLine.split( ), con eso sacarías un arreglo de Strings, donde cada token
representaría una propiedad de tu CD ...

while (lineReader.hasNextLine()) {

                String textLine = lineReader.nextLine();
                String [ ]  cdTags = textLine.split( /*aquí va el separador que usas, underscore, o espacio en blanco*/ );

                    CD cd = new CD();
                    cd.setArtist( cdTags[ 0 ] );
                    cd.setTitle( cdTags[ 1 ] );

                    cd.printArray();
            }

Digo, es a primera instancia lo que se me ocurre, aunque si crecen las propiedades de tu CD, pues sería poco práctico hacerlo así...

Si no me equivoco el

Si no me equivoco el parámetro del Scanner debería ser "row" No, fíjate en el tipo de dato de row int row = 0 es un int. Es decir, es el índice de la linea y no la linea misma, por eso no te funciona el Scanner, no hay un constructor que reciba un int. Entonces por ahi no esta el problema.

Que notas de raro en la salida? Están cuatro veces todas las entradas no? Lo que no se vé en el código que pusiste, es, como estas agregando el CD al arreglo, ni como haces la impresión.

Se me hace que estas agregando siempre a la misma parte.

Aprovechando que limpiaste tu

Aprovechando que limpiaste tu código lo suficiente como para poder correrlo yo mismo, corrí y ya entendí por que te está saliendo esto.

Son dos problemas, bueno uno es un problema y otro es una vision :P

El primer problema es que estás leyendo cada linea, lo cual esta bien, pero luego estas queriendo llenar esa linea en las 4 posiciones del arreglo.

Entonces lo que ahorita estas haciendo ( mal ) es:

1.- Lees la linea: Elvis_Presley Jailhouse_Rock
2.- Iteras todo el arreglo ( ahí es donde esta realmente el horror )
2.0.- Para la posición 0 imprimes Elvis_PresleyJailhouse_Rock
2.1.- Para la posición 1 imprimes Elvis_PresleyJailhouse_Rock
2.2.- Para la posición 2 imprimes Elvis_PresleyJailhouse_Rock
2.3.- Para la posición 3 imprimes Elvis_PresleyJailhouse_Rock
Repites el paso 1 ahora con Massive_AttackProtection

Por eso te salen cada uno cuatro veces.

El segundo problema es que imprimes cada vez que estas llenando el elemento, pero jamás lo pones en el arreglo, lo que tienes que hacer es imprimir despues y agregarlo al arreglo.

Modifiqué tu código y lo siguiente ya funciona bien. Te puse comentarios esperando que entiendas cuales fueron las diferencias.

Saludos!!!

  1. import java.io.*;
  2. import java.util.Scanner;
  3. class Labb4 {
  4.     public static void main(String args[]) {
  5.         CD[] myArray = new CD[4];
  6.         File file = new File("skivor.txt");
  7.                         Scanner lineReader = null;
  8.         try {
  9.             lineReader = new Scanner(file);
  10.             int row = 0; // cada linea es un renglon del arreglo, by OscarRyz
  11.             while (lineReader.hasNextLine()) {
  12.                 String textLine = lineReader.nextLine();
  13.  
  14.                 //Nope, no vamos a iterar por cada elemento del arreglo. OscarRyz
  15.                 //for (int row = 0; row < myArray.length; row++) {  
  16.                     Scanner line = new Scanner(textLine); // el problema es aqui!!! // je je no , es arriba OscarRyz
  17.                     CD cd = new CD();
  18.                     cd.setArtist(line.next());
  19.                     cd.setTitle(line.next());
  20.                                                                        
  21.                     // agregarlo al arreglo e incrementar row en uno  by OscarRyz
  22.                     myArray[ row++ ] = cd;             
  23.                                                                        
  24.                     //cd.printArray();// esto te hace ver visiones by OscarRyz
  25.                 //}
  26.             }
  27.             // lineReader.close();                      //moved to finally by OscarRyz
  28.         } catch (IOException ioe) {
  29.             System.out.println("Error de lectura del archivo");
  30.         } finally {
  31.             lineReader.close();
  32.         }
  33.         // Una vez lleno el arreglo lo imprimimos: //by OscarRyz
  34.         for( CD cd : myArray ) {                                //by OscarRyz
  35.            cd.printArray(); //<-- sería mejor llamarlo printCD no?//by OscarRyz
  36.         }//by OscarRyz
  37.  
  38.     } // end Main
  39. }
  40.  
  41. class CD {
  42.   private String artist;
  43.   private String title;
  44.  
  45.   void setArtist( String artist ) {
  46.         this.artist = artist;
  47.   }
  48.   void setTitle( String title ) {
  49.         this.title = title;
  50.   }
  51.  
  52.   public void printArray(){
  53.         System.out.println("CD[ artists: "+artist+", title: "+title+"]");
  54.         // o mejor aún:
  55.         //System.out.println(String.format("CD[ artists: %s, title: %s", artist, title );
  56.   }
  57. }

Entonces si te fijas, ya estabas bastante cerca. Comenté todos los cambios para que te pudieras dar cuenta de las diferencias, borralos cuando los hayas ( y hasta ) que los hayas entendido. Finalmente, no le moví mucho a tu código así que no cuenta como que te hice la tarea y aún te falta bastaaaante camino por recorrer.

Espero que te sirva.

Suerte!

Ahora estoy mas cerca

Gracias por el tip.

He insertado el textLine.split y he eliminado el for. Ahora obtengo los arreglos como deberia ser.
Aqui esta el codigo actualizado:

import java.io.*;
import java.util.Scanner;

public class Labb4 {

    public static void main(String args[]) {
       
        File file = new File("skivor.txt");
        try {

            Scanner lineReader = new Scanner(file);
            int arrayNumber = 0;
            while (lineReader.hasNextLine()) {

                // Crea un array de tipo CD. arrayNumber determina el tamano del array
                CD[] myArray = new CD[arrayNumber];
               
                String textLine = lineReader.nextLine();
               
                Scanner row = new Scanner(textLine);

                String[] cdTags = textLine.split(" ");
               

                // Crear el objeto CD por cada arreglo (cada linea en el archivo de texto)
                CD cd = new CD();
                cd.setArtist(row.next());
                cd.setTitle(row.next());
               

                // Llama al metodo printArray para mostrar los arrays
                cd.printArray();

                arrayNumber++;
            }

            //Cierra el archivo de texto
            lineReader.close();

        } catch (IOException ioe) {
            System.out.println("Fel inläsning");
        }

    } // end Main
}

Ahora lo que necesito hacer es ordenarlos alfabeticamente y para eso debo utilizar el metodo "sort" de la clase CD que es de la siguiente manera:

 public void sort(CD[] skivor) {
        /*
            sorting goes here
         */

    }

Necesitaria un empujencito para saber como "traspaso" los arreglos a este metodo para aplicar el algoritmo de ordenamiento que OscarRyz me recomendo estudiar.

OscarRyz: Ahora me esta entregando de forma correcta los arreglos en la consola:

run:
Front_Line_Assembly Mindphaser

Elvis_Presley Jailhouse_Rock

Massive_Attack Protection

Massive_Attack Blue_Lines

Test_Iscicles Circle_Square_Triangle

BUILD SUCCESSFUL (total time: 0 seconds)

Para tener mas informacion: el metodo printArray es asi:

public void printArray() {
        System.out.println(getArtist() + " " + getTitle() + "\n");
    }

/Americo

No uses split y Scanner al mismo tiempo

Solo estás revolviendo las cosas. Split es bueno, pero el scanner hace precisamente eso. Si te fijas en tu código no usaste para nada el resultado del split, asi que mejor quitalo.

Para pasarlo solo necesitas antes de que termine el main:

CD.sort( myArray );

Pero claro, necesitas que sort sea un método de clase  public static sort( CD [] arreglo ) ( no tiene sentido que sea de instancia a menos claro que lo que quieras sea ordenar los elementos internos , en fin )

Ya casi lo haces. Revisa java.lang.String.compareTo() para saber como hacer una comparacion alfanumerica de strings. Ejemplo:

"hola".compareTo( "adios");  //regresa 7  o sea que "hola" es mayor que  "adios"

Gracias por el aviso!!

lo que necesito hacer con sort es ordenar los arreglos y guardarlos en un archivo de texto.
/Americo

Ahh pues ahi si ya aplica lo

Ahh pues ahi si ya aplica lo del bubble sort :)

  • Revisa el link de la wikipedia.
  • Copia y pega ( en otro programa ) el ejemplo con los ints,
  • ENTIENDELO!!
  • y luego intenta aplicarlo con tu arreglo de CD's