Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Kabuto

Páginas: 1 ... 44 45 46 47 48 [49] 50
961
Hola,
estoy verde, verdísimo, en HTML y más en JavaScript.

Pero creo que uno de los problemas es que las celdas TD tienen el mismo ID("documento").

El ID ha de ser único para cada elemento, es como el DNI de las personas, no puede haber varias personas con el mismo DNI.
Entonces, para esto que quieres hacer, seleccionar elementos por su ID no parece ser el camino.

En la funcion existeArchivo, en lugar de hacer un getDocument por ID, tal vez podrías usar la palabra  "this" como parametro de la funcion y cambiarle la clase.

Es decir,, en el HTML:

Código: [Seleccionar]
<tr>
<th>Juan</th>
<td onload="existeArchivo(this,D:\Prueba\docs1\fabri1\blabla1.txt)"></td>
<td onload="existeArchivo(this,archivo)"></td>
<td onload="existeArchivo(this,archivo)"></td>
</tr>

Así, con el this, estás pasandole a la función el elemento concreto (la celda en este caso) que está llamando a la función.

Este this lo recoges fácilmente al declarar la funcion, pro ejemplo puedes llamarlo celda:
Código: [Seleccionar]
function existeArchivo(celda,archivo)
{
.....
}

De ese modo, "celda" representa la celda a la que ha llamado la funcion, y ya solo tienes que aplicarle una clase u otra según si se encuentra el archivo o no.
Código: [Seleccionar]
if(fileBool){celda.className= "entregado";}
else{celda.className= "noEntregado";}
}

Con esto más o menos, a falta de que alguien que sepa más que yo (repito que estoy verde verdísimo... xD ) lo confirme y corrija, deberías poder cambiar la clase de cada celda.

962
Suele ser muy útil, hacer "una traza" manual del programa que hemos escrito. Es decir, con papel y lápiz mismamente, listar las variables que estamos usando y apuntamos su valor actual.

Luego ejecutamos mentalmente las líneas del programa una por una y vamos apuntando en el papel los cambios de valor de las variables y que resultado obtendríamos en pantalla.
Es entonces cuando vemos los errores "de lógica" que estamos cometiendo.
Remarco lo "de lógica" porque estos errores no nos los pueden detectar los compiladores (aunque de alguno nos pueden avisar alguna vez), son errores que solo podemos detectar nosotros.

Por ejemplo, centrémonos en este código:
Código: [Seleccionar]
public void setNombre (String valorNombre){
        nombre = valorNombre;
        System.out.println ("Ha cambiado el nombre del médico " + nombre + " a: " + nombre);
        nombre = nombre;
    }

No hay ningún error "sintáctico", cualquier compilador dará por válido ese código. Sin embargo, sí hay erróres "de lógica"..
Hagamos la traza, supongamos que llamamos a este método pasando como argumento el String "Luis".

Código: [Seleccionar]
medico.setNombre("Luis");
Bien, este método utiliza dos variables, uno es "nombre" que es atributo de la clase y el otro es "valorNombre" que es el parámetro del própio método.
Estos serían sus valores iniciales:
  • nombre = ""
  • valorNombre = "Luis"

El atributo "nombre" está con cadena vacía porque es como se iniciaría según el contructor de la clase.

Bien, ejecutemos mentalmente la primera línea:
Código: [Seleccionar]
nombre = valorNombre;
El atributo "nombre" ha cambiado su valor, anotemoslo. En rojo guardamos el valor que tenía previamente, para recordarlo, aunque realmente ya se ha perdido.
  • nombre = "", "Luis"
  • valorNombre = "Luis"
Y ahora ejecutemos la siguiente línea:
Código: [Seleccionar]
System.out.println ("Ha cambiado el nombre del médico " + nombre + " a: " + nombre);
Veamos el resultado en pantalla, según los valores actuales de las variables:
Citar
Ha cambiado el nombre del médico Luis a: Luis

Humm, no obtenemos el resultado deseado. Habría que revisar la lógica del código y buscar otra fórmula para obtener el resultado que deseamos.
Está claro que usar en una sentencia dos veces la misma variable ("nombre" en este caso), esperando que por pantalla dicha variable muestre dos valores distintos, es un error de lógica. Es imposible.
Y es precisamente resolviendo estos errores que parecen tan tontos, cuando de verdad se aprende a programar.
Porque saber programar no es conocer la sintaxis y los comandos de un lenguaje. Saber programar es conseguir dar ordenes lógicas al ordenador.

Así que por ahora es mejor para tí que intentes solucionarlo tú, porque si te lo soluciona otra persona pierdes la oportunidad de aprender.
Hay varias formas de solucionarlo, unas más eficientes que otras, a ver cuál puedes encontrar tú.

Aún nos queda una línea de programa por ejecutar:
Código: [Seleccionar]
nombre = nombre;
Ha habido un cambio de valor en la variable "nombre", aunque bueno, en realidad no ha cambiado nada... :P
  • nombre = "", "Luis", "Luis"
  • valorNombre = "Luis"


Como ves, esto de apuntar a mano en un papel las variables que estamos usando, apuntar como cambia su valor tras cada línea de código ejecutada y simular qué resultado tendríamos en pantalla... es muy útil para ver si las órdenes que hemos dado, siguen o no la lógica que creíamos haber programado.

De hecho, esto mismo es lo que hacen los depuradores (debuggers) de los compiladores de programación.
Solo que cuando se trata de código sencillo, como este que son tres líneas y dos variables, es mucho más rápido e intuitivo hacerlo uno manualmente en papel (además agiliza la mente) que no ponerse a configurar y aprender a usar un debugger.
Que no es nada difícil tampoco, pero sí un poco engorroso y tiene más sentido usarlo en códigos más complejos.

Sigue publicando aquí tus dudas y no dejes de intentar resolver los errores de lógica de tu programa ya que, repito de nuevo, es aquí cuando realmente aprendes y cuando realmente desarrollas el ingenio para dar soluciones eficientes y no solo eficaces (eficiencia y eficacia no es lo mismo...)

963
Hola compañero,

veo un poco de confusión en tu código.
Los bucle for no hacen nada porque estan vacíos. Además no son necesarios para esos métodos, donde tan solo se nos pide comprobar que el dato recibido es mayor que 0 y menor que 30 antes de pasárselo al atributo, lo cuál ha de hacerse con un if.

Y el método drawn para dibujar, se hace y se entiende más fácil usando bucles for.

Abajo posteo un código que he escrito ahora para este ejercicio, que creo que te ayudará a entender mejor como conseguir lo que se pide.
Disculpa que no haya respetado los nombres en inglés del ejercicio, pero a veces la mente se concentra mejor al escribir el código usando nombres en nuestro idioma materno y no en uno extranjero, por mucho dominio de ese idioma que podamos tener.

Te explico un poco lo que hace, aunque el código ya tiene varios comentarios y casi se explica por si solo.

- Defino la clase Rectángulo, con sus dos atributos.

- Escribo dos constructores:
Uno que no recibe parametros y creará el objeto rectángulo con su tamaño mínimo (1x1).
Otro, que si recibe parámetros, y permite indicar las dimensiones cuando vayamos a crear (instanciar) el objeto en el main().

- Getters de los atributos, ningún misterio.

- Setters de los atributos. Aquí se nos pide que comprobemos que los valores que recibamos, sean mayor que cero y menor que 30.
Esto lo hacemos preguntando con un if.
Si se cumple la condición, pasamos esos valores a los atributos.
Si no se cumple, no hacemos nada, los atributos no se cambian con los nuevos valores. Si se quiere, se puede lanzar un mensaje indicando que los valores no son válidos por no cumplir las condiciones >0 y <30

- Método que calcula el area del rectángulo, sin misterios.
Basta con devolver el resultado de multiplicar el ancho x alto.

- Método que calcula el perímetro, sin misterios.
Basta con devolver la suma de los cuatro lados, o lo que es más rápido: sumar el ancho y el alto y multiplicarlo por  2.

- Método para dibujar el rectángulo con asteriscos. Esto si tiene un poquito de misterio, aunque no mucho.
Se puede hacer de dos formas: un rectángulo todo relleno de asteriscos o bien un rectángulo hueco, que solo tenga asteriscos en los bordes.
Esta segunda forma es un poco más liosa porque hay que usar algunos if para preguntar si estamos dibujando un borde (primera y última linea todas con *) o estamos dibujando las lineas intermedias (solo * al princpio y al final, en medio solo espacios en blanco)

Ahora no vale la pena liarse con eso y he optado por el método fácil, todo relleno de asteriscos.
Si miras el código de este método, verás que es sencillo.
Primero un par de mensajes en pantalla informando de lo que se va a dibujar.
Luego un bucle for que recorre el alto, es decir, las filas (o lineas, como quieras llamarlas).
Anidado tenemos otros bucle for que recorre el ancho, es decir, las columnas.
Antes del segundo bucle anidado, el que dibuja los asteriscos, hago una tabulación para que el rectángulo salga separado del borde de la pantalla. Es algo puramente estético, no es necesario realmente.
Después de este segundo bucle, si es necesario hacer un salto de línea, tal y como hacías en tu propio código.

Por último:
- La clase Rectángulo ya está definida.
Ahora creo un metodo main para poder instanciar un objeto Rectángulo, al que ya le paso unas dimensiones y directamente llamo a su método que lo dibujará en pantalla.

Y eso es todo.
Pregunta cualquier cosa que no entiendas. A lo mejor ves alguna cosa rara como que en los métodos, en los return devuelvo el resultado de operaciones sin antes haberlos guardado en una variable.
Esto es perfectamente válido y es de hecho lo habitual en estos casos.
Por ejemplo en tu código vemos este método con un fallo gordo:

Citar
public void getArea(){
   int superfice;
   superfice = heigth*width;

}

Primero, dices que es void, esto significa que no va a devolver nada (void = vacio, nada..).
Entonces, este método es inútil, queremos que devuelva el resultado de calcular el Area, en este caso, ha de devolver un valor entero (int).
Por lo tanto, además ha de tener una sentencia return

Citar
public int getArea(){
   int superfice;
   superfice = heigth*width;
        return superficie;
}

Ahora, ya funcionaría perfectamente y sería un código totalmente válido. Pero hay un detalle, estamos usando una variable llamada superficie para almacenar el resultado y luego devolverlo.
Esto es innecesario, de hecho, una vez se ejecuta la sentencia return, la variable superficie "se muere", desaparece, deja de existir.
Puesto que la variable tiene una vida tan efímera, apenas un par de ciclos de computación, no es necesaria crearla y podemos devolver directamente el resultado de la expresión "heigth*width" sin necesidad de almacenarla previamente.
Citar
public int getArea(){
   return heigth*width;
}

Se supone que quien quiera llamar a este método en la parte del main(), ya se encargará él de guardar el computo en una variable o de sacarla por pantalla, o lo que sea...
Nuestro método simplemente ha de devolver un valor, y para ello basta con devolver el resultado de la multiplicación sin guardarlo en ningún sitio.


En fin, ya no me enrollo más. Aquí tienes mi código, cualquier duda, a preguntar por aquí.
Un saludo.

Código: [Seleccionar]
public class Rectangulo {

    private int alto;
    private int ancho;
   
    /**
     * Constructor sin parametros
     */
    public Rectangulo()
    {
        alto = 1; //1 es el valor mínimo aceptable de los atributos
        ancho = 1; //no puede ser 0 porque entonces no existe el rectángulo
    }
    /**
     * Constructor que recibe parametros para definir ancho y alto
     * @param alto Altura del rectangulo
     * @param ancho Base o anchura del rectangulo
     */
    public Rectangulo(int alto, int ancho)
    {
        this.alto = alto;
        this.ancho = ancho;
    }
   
    public int getAncho() {return ancho;}
    public int getAlto() {return alto;}
   
    /*
    Para establecer (setear) el ancho y el alto, hemos de comprobar que
    los valores recibidos son mayor que 0 y menor que 30
    */
    public void setAncho(int ancho)
    {
        if (ancho > 0 && ancho < 30)
            this.ancho = ancho;
    }
    public void setAlto(int alto)
    {
        if (alto > 0 && alto < 30)
        this.alto = alto;
    }
   
    /**
     * Calcula el area del rectangulo (base x altura)
     * @return Area del rectangulo.
     */
    public int getArea()
    {
        return ancho*alto;
    }
   
    /**
     * Calcula el perimetro del rectangulo (suma de sus 4 lados)
     * @return Perimetro del rectangulo
     */
    public int getPerimetro()
    {
        return 2 * (ancho + alto);
    }
   
    /**
     * Dibuja en pantalla mediante asteriscos el objeto rectangulo
     * segun los valores de sus atributos ancho y alto.
     */
    public void dibujar()
    {
        System.out.println("\n\nRepresentación del rectángulo con los valores:");
        System.out.println("Base: " + ancho + "\t" + "Altura: " + alto);
        System.out.println("Area: " + getArea() + "\t" + "Perimetro: " + getPerimetro() + "\n");
        for (int i = 1; i <= alto; i++)
        {
            System.out.print("\t");//Tabulamos un poquito para no dibujar justo en el borde de la pantalla.
            for (int j = 1; j <= ancho; j++)
                System.out.print("*");
            System.out.println();//Ya se ha dibujado el ancho, hacemos un salto de línea para dibujar la siguiente fila.
        }
    }
   
    public static void main(String args[])
    {
        Rectangulo miRectangulo = new Rectangulo(5,15);
        miRectangulo.dibujar();
    }
}

964
Es porque repites la palabra "double".
Esta solo has de ponerla una vez, la primera vez que declaras la variable para especificar su tipo de dato.
Luego ya no es necesario, y de hecho no puedes como estás comprobando, volver a especificar su tipo de dato.

Las siguientes veces que quieras poner su valor a cero, basta con un simple:

Código: [Seleccionar]
x = 0;
Sin especificar de nuevo que es double

965
BlueJ es genial para empezar a aprender, por cosas como poder ejecutar clases sin necesidad de llamarlas desde un main y tal, o por como representa gráficamente las conexiones y jerarquías de las clases. Es una gozada.

Pero tarde o temprano querrás saltar a entornos más profesionales como Eclipse, NetBeans, IntelliJ...  hay muchos.

Sobre crear ejecutables, seguro que alguien te lo podrá explicar mejor que yo (¡¡yo también estoy aprendiendo!!), pero en Java, por su filosfia de lenguaje "medio compilado, medio interpretado", no hay exactamente ejecutables como tal.

Se pueden crear archivos con extension .jar (que es poco más que un archivo comprimido con todas las clases que pueda necesitar nuestro programa).
Si el programa tiene interfaz gráfica se podría abrir haciendole doble click, similar a como si fuera un exe.
Si es un programa pensado para la consola de texto, como todos los que hacemos para aprender, habría que llamarlo desde la consola de comandos invocando el comando java.
Si buscar por Google poniendo "ejecutable Java" verás multitud de explicaciones sobre esto.

Tampoco le des muchas vueltas ahora a esto, entiendo que cuando empezamos a programar nos ilusiona poder hacer nuestros exe y compartirlos con otras personas. Y Java en este aspecto al principio desilusiona porque nos "tiene atados" al editor y parece que solo mediante este pueden ejecutarse, aunque obviamene no es asi.
Pero lo importante ahora es aprender a programar.
Cuando tengas más conocimientos, puedes atreverte a ir aprendiendo también C++ de manera simultánea (es muy similar a Java, casi calcado, de hecho, Java es un derivado de C++).
C++ si es un lenguaje compilado y te permitirá crear ejecutables para saciar la sed de crear archivos .exe, aunque sea de programitas tontunos de comparar palabras je je..

Por úlitmo, quizás me expresa mal con lo del objeto Scanner.

Scanner es una clase, y para poder utilizarla, tenemos que crear un objeto de esta clase.
En tu programa lo llamas entradaEscanner, yo lo llamo teclado, da igual como se llama, todos son objetos de la clase Scanner.

Es decir, las clases son como una definicion abstracta de como es una "cosa" (atributos) y qué comportamientos puede tener (Métodos). Pero la concreción de esa "cosa", la "materialización", es lo que llamaremos Objeto.

Podemos decir, que tu eres el objeto Dimiste, y yo soy el objeto Kabuto. Somos objetos diferentes, pero ambos pertenecemos a la clase Persona.

Esta clase dice que tenemos unos atributos: ojos, nariz, boca, extremidades, pelo, nº de DNI, etc.. pero la clase no especifica como han de ser, no tiene unos valores concretos.
Estos atributos se especifican, reciben unos valores concretos, cuando se crea un objeto.

Yo tengo ojos "verdes", tu quizás los tienes "marrones", yo tengo la nariz "larga", quizás la tuya sea "chata",
Mi color de pelo es "marrón", el tuyo puede ser "rubio", el de otra persona si es calva, pues será "null" je je...

Nuestra clase Persona además nos otorga unos "Métodos" unos procedimientos/funciones para realizar tareas.
Las personas respiramos, así que la clase Persona tendrá un método llamado respirar().
Así que si yo ejecuto mi metodo respirar y le paso un parametro aceptable para este metodo:
kabuto.respirar(aire);

Pues dara un resultado, en este caso, me dará unos cuantos segundos más de vida.
Si el parametro es diferente:
kabuto.respirar(veneno);

Pues el método .respirar() devolverá un resultado distinto, en este caso, mis segundos de vida se reducirán notablemente.  :P


Esto es básicamente la programacion orientada a objetos. Definir unas clases otorgándoles unos atributos y unos métodos, y a partir de ellas crearemos objetos, cada uno con los mismos atributos, pero con distintos valores según cada objeto.

966
Hola dimiste. Gracias por tus comentarios.

Los objetos Scanner, y varios más que irás descubriendo con el tiempo, son  recomendables "cerrarlos" cuando ya no se vayan a usar más.

En programas sencillos como estos que se hacen para aprender y todo sucede dentro del metodo main, no tiene apenas importancia.

En programas mas completos puede suponer un problema a la hora de recoger datos.
Es decir, un programa más completo, tendrá una clase con el metodo main, y seguramente durante la ejecución del programa se llamaran a otras clases escritas por el programador en archivos separados, con sus correspondientes métodos, o sea, que el código estará repartido en varios sitios.

Bien, si uno de estos métodos al terminar se deja un Scanner sin cerrar, puede ocurrir que otro método con su propio Scanner tenga problemas de acceso al System.in porque el anterior Scanner no liberó los recursos que ocupaba.

Como digo, en programas así sencillos no tiene relevancia, pero conviene cerrarlos igualmente para ir tomando buenas costumbres.

Además, yo escribo el código con el editor Eclipse, y si no cierro los Scanner, me marca el código con un signo de admiración, un warning,y claro, no queda bonito que te estén llamando la atención je je.
Me deja ejecutar el programa sin problemas pero me avisa de que, ojo, hay cierto riesgo.

Sobre .subString() y .toChar(), como bien dices, cada uno devuelve un tipo de dato distinto.
Aunque a subString() le pidamos un único carácter, ese carácter será de tipo String.
Por ejemplo,  --> "c"
.toChar nos devolvería ese caracter en tipo char.
Por ejemplo  --> 'c'

Fijate que para el char he usado "comillas simples". No es lo mismo "c" que 'c'.
Para Java (y otros lenguajes como C++) distingue entre estos dos tipos de comillas.
Lo que esté entre "comillas dobles", se considera un String.
Lo que esté entre "comillas simples", se considera un char.

Esto simplemente hay que tenerlo en cuenta porque, aunque con ambos tipos de dato podremos hacer las mismas cosas (como formar palabras, recoger opciones de un menu en pantalla,...), estas cosas habrá que hacerlas de distintas maneras y con distintos métodos según el tipo con el que estemos trabajando.

Pero en fin, todo esto se va aprendiendo sobre la marcha. No hay que preocuparse mucho ahora de estos "detalles".

Un saludo ;)

967
Es ciertamente un planteamiento interesante. Me encanta encontrarme cosas así porque demuestra lo variada que puede ser la programacion según cada persona. Hasta para tareas sencillas (comparar letras) nos encontramos distintas maneras, ni mejores ni peores, que llevan a lo mismo.

Os dejo la solución a la que yo he llegado, para compartir ideas.
En realidad os dejo dos, la última es exactamente igual, pero usando el método .charAt() en lugar de .subString().
Esto ya no cumple el enunciado propuesto en el ejercicio, pero lo pongo para que se vea como funciona y ver que puede ser más cómodo para cuando queramos operar con los caracteres individuales de un String.
Tan solo hay que tener en cuenta que .subString() nos devuelve una letra de tipo String y .toChar() nos devuelve también una letra, pero tipo char.
Por eso con esta última podemos usar el comparador de igualdad == y con la primera hay que recurrir al método .contains().
En según cada caso, nos interesará más usar una manera u otra.

Un saludo a todos.

Código: [Seleccionar]
import java.util.Scanner;

public class ComparaCaracteres {

public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);

        System.out.print("Primera palabra: ");
        String pal1 = teclado.nextLine();
        System.out.print("Segunda palabra: ");
        String pal2 = teclado.nextLine();
        teclado.close();

        //¿Cual es mayor?
        if (pal1.length() > pal2.length())
        {
            int mayor = pal1.length();
            int menor = pal2.length();
            int i;//Indice nos sirve para los dos bucles
            for (i = 0; i < menor; i++)
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println(pal1.substring(i, i+1).equals(pal2.substring(i, i+1)));
            }
            for (;i < mayor; i++)//"i" conserva el valor del bucle anterior
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println("La segunda palabra no tiene la letra " + (i+1));
            }
        }
        else//Segunda palabra es mayor, pero tambien nos vale en el caso de que midieran igual
        {
            int mayor = pal2.length();
            int menor = pal1.length();
            int i;
            for (i = 0; i < menor; i++)
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println(pal1.substring(i, i+1).equals(pal2.substring(i, i+1)));
            }
            /*Siguiente bucle no se ejecutara si las palabras midieran igual
             * ya que entonces "i" no sera menor que "mayor" y por lo tanto
             * no se cumplirá la condicion del bucle
             */
            for (;i < mayor; i++)
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println("La primera palabra no tiene la letra " + (i+1));
            }
        }
}
}



Código: [Seleccionar]
import java.util.Scanner;

public class ComparaCaracteres {

public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);

        System.out.print("Primera palabra: ");
        String pal1 = teclado.nextLine();
        System.out.print("Segunda palabra: ");
        String pal2 = teclado.nextLine();
        teclado.close();

        //¿Cual es mayor?
        if (pal1.length() > pal2.length())
        {
            int mayor = pal1.length();
            int menor = pal2.length();
            int i;//Indice nos sirve para los dos bucles
            for (i = 0; i < menor; i++)
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println(pal1.charAt(i)==pal2.charAt(i));
            }
            for (;i < mayor; i++)//"i" conserva el valor del bucle anterior
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println("La segunda palabra no tiene la letra " + (i+1));
            }
        }
        else//Segunda palabra es mayor, pero tambien nos vale en el caso de que midieran igual
        {
            int mayor = pal2.length();
            int menor = pal1.length();
            int i;
            for (i = 0; i < menor; i++)
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println(pal1.charAt(i)==pal2.charAt(i));
            }
            /*Siguiente bucle no se ejecutara si las palabras midieran igual
             * ya que entonces "i" no sera menor que "mayor" y por lo tanto
             * no se cumplirá la condicion del bucle
             */
            for (;i < mayor; i++)
            {
                System.out.print("¿Letra " + (i+1) + " es igual en ambas palabras?: ");
                System.out.println("La primera palabra no tiene la letra " + (i+1));
            }
        }
}
}

968
Hola Lorenzo31, muchas gracias por tus respuestas.

Si quito lo de static, Eclipse me lanza errores como este cada vez que llamo a alguno de los métodos.
Citar
Cannot make a static reference to the non-static method celAFar(double) from the
type Ej12

He probado lo de reiniciar el objeto Scanner, sin éxito... ya intenté algo parecido antes. Cerrarlo, con .close() y volver a crearlo con new Scanner justo antes de pedir el dato...

Pero nada, no hay manera..


Sin embargo, he encontrado una solución.

Cuando llamos a los métodos que presentan los distintos menús, (los métodos void), les paso el objeto Scanner como parámetro y lo utilizo en esos métodos sin crear/cerrar un nuevo scanner... y así consigo que funcione je je...
No me termina de gustar, pero bueno, peculiaridades del Java con las que hay que lidiar...

Lo raro es que pedro si le funcionase y a mi no. Voy a probar con otro IDE como NetBeans, a ver si percibo alguna diferencia.

Muchas gracias a ambos por vuestra colaboración. Un saludo.

969
Sí, te entiendo perfectamente. Lo que no entiendo es por qué a tí te funciona y a mi no xD
La línea de limpiar el buffer, la puse porque leí que soluciona este tipo de problemas... pero no me solucionó nada.


¿Puede tener algo que ver el IDE que usemos? En teoría no, se supone que aunque el IDE sea distinto, quien compila y ejecuta es la máquina Java..

Yo uso Eclipse.
Recientemente he querido probar con IntelliJ IDEA, que me han hablado bien... pero no me aclaro con él y aún no he sido capaz ni de ejecutar un programa  :P

No se si probar con NetBeans, a ver si noto algo distinto.

970
Hola Kabuto.

He compilado y ejecutado tu código y no me da ningún error.

Hola.
Gracias por tu interés.

¿Has podido ejecutar el programa completo?

El error lo da (al menos a mí) cuando antes de salir del bucle principal pregunta si quiero salir o no.
Si por ejemplo al principio, cuando da a elegir entre tres opciones (c/f/k) introduzco una letra distinta de estas, de manera que no muestra ningún menu y  se va directamente al final del bucle para preguntar si quiero salir o repetir. Ahí no hay problema.

En cuanto meto una opción válida, y accedo a los métodos de alguno de los menús donde hay que introducir números, es entonces cuando da error al llegar al momento donde he de recoger el char para decidir si salgo o no.

Esta es la salida que obtengo en la consola:
Citar
CONVERSOR DE TEMPERATURAS
-------------------------

Indique tipo de magnitud que va a introducir.
Opciones: (c)Celsius // (f)Farenheit // (k)Kelvin
Su opcion(c/f/k): f

Introduzca la magnitud en Farenheit: 345

Conversiones disponibles
(1) Farenheit a Celsius
(2) Farenheit a Kelvin
Su opcion (1/2): 2
345.0ºF equivalen a 446.8888888888889K
Exception in thread "main" java.util.NoSuchElementException
   at java.util.Scanner.throwFor(Unknown Source)
   at java.util.Scanner.next(Unknown Source)
   at estructura_modular.Ej12.main(Ej12.java:39)
¿Desea terminar? (S/N):

En situacione similares, lo había solucionado creando un segundo objeto Scanner.
Pero esta vez no me sirve, y lo de limpiar buffer haciendo un NextLine() previo a la pedida de datos, pues tampoco me está sirviendo...

971
Hola gente, es ya consábido el problema de los objetos Scanner para leer Strings tras haber leido números previamente.

Supuestamente se puede solucionar "limpiando" el buffer haciendo una llamada al método nextLine() sin asignarlo a ninguna variable.

Pero tengo aquí un caso, donde quiero leer un char tras leer números y nada, no hay manera.

Abajo os adjunto el código completo, por si alguien quiere compilarlo sin tener que cambiar nada.

Tiene muchas líneas porque hay varios métodos, pero tan solo hay que fijarse en la línea 39.

Ahí es donde leo un char para evaluar si finalizamos o no el bucle, pero al llegar ahí, peta el programa.

En la línea anterior intento lo de limpiar el buffer, pero no parece tener ningún efecto.

¿Alguna idea?


Código: [Seleccionar]
package estructura_modular;

import java.util.Scanner;

public class Ej12 {

public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
char opcion;
char salir = 'n';

do
{
System.out.println("\nCONVERSOR DE TEMPERATURAS");
System.out.println("-------------------------\n");
System.out.println("Indique tipo de magnitud que va a introducir.");
System.out.println("Opciones: (c)Celsius // (f)Farenheit // (k)Kelvin");
System.out.print("Su opcion(c/f/k): ");
opcion = teclado.next().toLowerCase().charAt(0);

switch(opcion)
{
case 'c':
menuCelsius();
break;
case 'f':
menuFarenheit();
break;
case 'k':
menuKelvin();
break;
default:
System.out.println("No se reconoce magnitud introducida.");
break;
}

System.out.print("¿Desea terminar? (S/N): ");
teclado.nextLine();//Limpiamos buffer de entrada
salir = teclado.next().toLowerCase().charAt(0);
}while (salir != 's');

System.out.println("\n\nFin de programa...");
teclado.close();
}

public static double celAFar(double m)
{
return ( 9 * m / 5) + 32;
}

public static double celAKel(double m)
{
return m + 273.15;
}

public static double farACel(double m)
{
return (m - 32) * 5 / 9;
}

public static double farAKel(double m)
{
return (m - 32) / 1.8 + 273;
}

public static double kelACel(double m)
{
return m - 273.15;
}

public static double kelAFar(double m)
{
return 1.8 * (m - 273) + 32;
}

public static void menuCelsius()
{
Scanner teclado = new Scanner(System.in);
int opcion;
System.out.print("\nIntroduzca la magnitud en Celsius: ");
double magnitud = teclado.nextDouble();

System.out.println("\nConversiones disponibles");
System.out.println("(1) Celsius a Farenheit");
System.out.println("(2) Celsius a Kelvin");
System.out.print("Su opcion (1/2): ");
opcion = teclado.nextInt();

switch(opcion)
{
case 1:
System.out.println(magnitud + "ºC equivalen a " + celAFar(magnitud) + "ºF");
break;
case 2:
System.out.println(magnitud + "ºC equivalen a " + celAKel(magnitud) + "K");
break;
default:
System.out.println("ERROR: No se reconoce opcion seleccionada.");
break;
}
teclado.close();
}

public static void menuFarenheit()
{
Scanner teclado = new Scanner(System.in);
int opcion;
System.out.print("\nIntroduzca la magnitud en Farenheit: ");
double magnitud = teclado.nextDouble();

System.out.println("\nConversiones disponibles");
System.out.println("(1) Farenheit a Celsius");
System.out.println("(2) Farenheit a Kelvin");
System.out.print("Su opcion (1/2): ");
opcion = teclado.nextInt();

switch(opcion)
{
case 1:
System.out.println(magnitud + "ºF equivalen a " + farACel(magnitud) + "ºC");
break;
case 2:
System.out.println(magnitud + "ºF equivalen a " + farAKel(magnitud) + "K");
break;
default:
System.out.println("ERROR: No se reconoce opcion seleccionada.");
break;
}
teclado.close();
}

public static void menuKelvin()
{
Scanner teclado = new Scanner(System.in);
int opcion;
System.out.print("\nIntroduzca la magnitud en Kelvin: ");
double magnitud = teclado.nextDouble();

System.out.println("\nConversiones disponibles");
System.out.println("(1) Kelvin a Celsius");
System.out.println("(2) Kelvin a Farenheit");
System.out.print("Su opcion (1/2): ");
opcion = teclado.nextInt();

switch(opcion)
{
case 1:
System.out.println(magnitud + "K equivalen a " + kelACel(magnitud) + "ºC");
break;
case 2:
System.out.println(magnitud + "K equivalen a " + kelAFar(magnitud) + "ºF");
break;
default:
System.out.println("ERROR: No se reconoce opcion seleccionada.");
break;
}
teclado.close();
}
}

972
Puf.. yo estoy haciendo el el primer curso, presencial, y con algunos profesores ya cuesta entender la materia (hay otros que son una maravilla)
Tú, online y sin poder empezar desde el principio.... tiene mucho mérito, tio. ¡¡Ánimo!! ;)

973
Cuando no te salió bien quizás era porque introduciste un espacio en blanco después de la palabra
Por ejemplo: "pato "

Lo normal es que si "nos pasamos" e intentamos acceder a una letra que no existe, el programa se detenga dando un error "Exception. Out of bounds..." o algo parecido.

Puedes probarlo, basta que en el bucle for, en la condición de salida, en lugar de i<cuantasLetras pon i<=cuantasLetras.

Es decir, supongamos la palabra "pato". Su .length() es igual a 4, porque tiene 4 letras. Guardamos ese valor en cuantasLetras.
Aunque su longitud sea 4, el indice de la última letra será 3, porque como dijimos empiezan a numerarse desde el 0.
Así que el String "pato" tiene los indices: 0(p), 1(a), 2(t) y 3(o).

Entonces, si ponemos como condición en el bucle que se ejecute mientras i<cuantasLetras.
Todo irá bien porque la i solo llegará hasta el 3.
Cuando valga 4, ya no se cumplirá la condición (4 no es menor que 4) y no ejecutará las instrucciones del bucle.

Pero si por error pusieramos como condición i<=cuantasLetras, cuando i llegara a valer 4, la condición sí se cumplirá (4 si es menor o igual que 4) y por lo tanto ejecutará las instrucciones del bucle. Pero entonces intentará acceder a la letra con indice número 4, que no existe porque "pato" tiene del 0 al 3 únicamente.
Entonces se produce una "excepción" (un error) y normalmente (depende del compilador) se para la ejecución del programa mostrando un mensaje de error.

Puedes probarlo para que veas que efecto produce.

Sobre mis explicaciones, je je, a veces me extiendo mucho, pero es que quiero ser bastante detallista, porque yo también soy estudiante, estoy cursando un CFGS de DAM y como bien dices, hay profesores que parece que olvidaron lo que es ser estudiante de algo totalmente nuevo y dan explicaciones muy genéricas, como dando por hecho que todo el mundo lo va a entender.
Y yo toda esta parte "básica" de Java y algorítmia en general, ya me la sé (pero no mucho más) así que las vagas explicaciones de algunos profesores no me afectan, pero tengo compañeros de clase que es la primera vez que teclean código de programación y algo tan "sencillo" como este ejercicio, recorrer un String y sacar cada una de sus letras, a algunos se les atraganta y otros lo hacen porque han visto un código de ejemplo, pero en realidad no entienden el proceso "interno" ni la lógica que sigue el programa para hacer lo que le estamos ordenando.

Que esa es la clave de todo, entender la lógica de la programación, y no tanto aprenderse de memoria cómo usar instrucciones y métodos.
Si no se entiende, si no se comprende como "piensa" un ordenador, luego es muy complicado meterse en asuntos más serios.

974
Sí los hay, pincha en el enlace del mensaje que te puse antes:

Aquí tabla con símbolos
< --> &lt;
> --> &gt;

975
Hola Hquinn.

Un par de cositas, que una vez explicadas, verás que se puede hacer más fácil.

Primero, indicar que un String viene a ser lo mismo que un vector (un array de 1 dimensión).
Es decir, puedes acceder a cada letra del String sin tener que usar el método .subString() (este es útil cuando queremos seleccionar más de un carácter del String) porque cada letra está guardada como si fuera un elemento individual con un número de indice que le identifica.

Aquí lo has hecho bien, porque de hecho el enunciado del ejercicio te pide que uses el subString() para que te familiarices con este método.
Pero esto te lo comento para que sepas que en realidad, no es necesario usar dicho método cuando queremos acceder a letras de manera individual.
Si será útil cuando queremos seleccionar varias letras seguidas juntas de una cadena.

Para acceder a cada letra, basta con indicar el nombre del String y junto a el, entre corchetes, el número de indice de cada letra.
Por ejemplo: entradaTeclado[0]

Con eso referimos a la primera letra del String, que están numeradas desde el 0 hasta la (longitud del String - 1).
Es decir, si un String tiene 5 letras, sus indices serán: 0, 1, 2, 3 y 4.

Entonces, en el bucle, puedes usar directamente la variable i para sacar cada letra del String por pantalla, que además ya la tienes establecida para que empiece desde 0 y vaya aumentando mientras no alcance la longitud del String, por lo que no tienes ni que sumarle ni restarle. Puedes usar la i tal cual:

Código: [Seleccionar]
for(int i=0;i<cuantasLetras;i++){ 
            System.out.println("Letra "+(i+1)+": " + entradaTeclado[i]);

Pero insisto, tú lo has hecho bien usando el método subString() porque así te lo pide el ejercicio.


Segundo, la comprobación que haces con el if dentro del bucle for, es innecesaria porque el bucle for ya tiene una condición de salida, ya le hemos dicho que se ejecute mientras "i sea menor que cuantasLetras".
En cuanto i deje de ser menor, el bucle for dejará de ejecutarse y no hay riesgo de que intentemos acceder a una letra que no existe.

Puedes quitar el if y verás que el programa funciona igual.

En ejercicios más complejos, si puede interesar usar el break para que en según que condicion, interrumpir el bucle antes de que alcance la condición de salida principal.

Otro detalle, menos importante.
Guardar la longitud del String en la variable cuantasLetras para usarla como condición del bucle for, es correctísimo y no supone ningún problema.

Sin embargo, si quisieras, puedes ahorrarte esa variable y escribir el bucle for directamente usando el metodo .length() de este modo:

Código: [Seleccionar]
for(int i=0; i < (entradaTeclado.length() - 1); i++){ 
            System.out.println("Letra "+(i+1)+": " + entradaTeclado[i]);

El resultado, como digo, es el mismo. La ventaja es que te ahorras declarar una nueva variable.
En algunos casos, puede que necesites emplear la longitud del String para más cosas a parte de como condición de un bucle, entonces si vale la pena crear una variable para guardar este dato y ahorrarte escribir varias veces el método .length() en el mismo programa.

Por lo demás, todo parece estar bien.

976
Aquí tabla con símbolos (pulsar en el enlace anterior para acceder a la tabla de símbolos donde pueden verse las equivalencias)
< --> &lt;
> --> &gt;

977
De nada, un placer  ;)

Es importante saber que en Java (y otros lenguajes) los métodos (ya sean constructores, funciones, procedimientos..) no solo se distinguen por el nombre que les damos, si no también por el tipo, orden y cantidad de parámetros que le indicamos que tiene que recibir.

De hecho, en una clase podemos tener definidos métodos con el mismo nombre y al lenguaje no le importará que los nombres se repitan, siempre y cuando varíen el tipo, orden y/o la cantidad de parámetros que recibirán.
Así, podríamos tener declarados:

miMetodo(int n){...};
miMetodo(double n){...};
miMetodo(float n){...};
miMetodo(String s){...};
miMetodo(boolean b){...};
miMetodo(int n, int m){...};
miMetodo(int n, int m, boolean b){...};
etc...


Podríamos repetir el nombre "miMetodo" tantas veces como quisieramos, que Java ejecutará un código u otro según los parámetros que le pasemos cuando hagamos la llamada al método.
No es recomendable hacer esto porque obviamente se presta a confusiones.

Sin embargo, en determinados casos puede tener sentido hacerlo y de hecho en la misma API de Java podemos encontrar multitud de métodos con el mismo nombre pero que reciben distinto número de parámetros. Eso sí, son métodos que hacen prácticamente lo mismo, por eso tiene sentido que se llamen igual.

En el caso concreto de los constructores (que son métodos en realidad), es totalmente normal crear varios con el mismo nombre pero recibiendo más o menos parámetros.
Lo normal, como tú mismo has hecho ya en tu código, es tener como mínimo el constructor básico que no recibe parámetros, y otro que recibe tantos parámetros como atributos tenga la clase (al menos los atributos que dependan de la información que proporciona el usuario).
Pero podría tener más. Supongamos una clase con 6 atributos por ejemplo, pues podrías tener constructores que solo recibe un parámetro, que recibe dos, que recibe tres, que recibe cuatro....y los otros atributos que no se reciben los inicializas tú en el código.

Como digo, esto se podría hacer y a Java le parecerá válido y correcto. Otra cosa es que a ti como programador te interese o no "complicar" tu código con tantos constructores. Sobre todo si luego vas a compartir tu clase con otros programadores, por muy bien que la documentes y expliques cada método y constructor, para el que no creó ese código le resultará confuso encontrarse con tantos constructores.

Siempre habrá casos concretos que pueda interesar tener algún constructor más de los dos habituales (con y sin parámetros), pero por lo general lo ideal es tener solo esos dos.


Antes preguntabas, si había algún problema en no poner el "constructor 1", el "básico" que no recibe parámetros.
No pasa nada si no lo pones, Java ya crea un constructor por "defecto" para este caso.
Pero es buena costumbre de programador crearlo tú, y además así te aseguras de que los atributos se inicializan a unos valores conocidos por ti, por ejemplo los típicos de "0" para los numéricos, cadena vacía "" para los String y espacio en blanco ' ' para los tipo char.

Esto te puede evitar luego sorpresas raras.

978
El error creo que se debe a que no respetas el orden de los parámetros que pasas.

El constructor de Cocina Casa espera primero un booleano y luego un entero
Pero tu en esta línea se los estás pasando en otro orden:
Código: [Seleccionar]
cocina = new CocinaCasa(objetoCocina.getNumeroFuegos(), objetoCocina.getEsIndependiente());
Cambialo así:
Código: [Seleccionar]
cocina = new CocinaCasa(objetoCocina.getEsIndependiente(), objetoCocina.getNumeroFuegos());
Es decir un constructor declarado como Constructor (int, boolean) es diferente de Constructor(boolean, int).

Aunque se llamasen exactamente iguales, Java los diferenciaría por el orden de los parámetros que espera recibir.

979

También es curioso, la única diferencia que veo entre a y aa es que a está afectada por const mientras que aa no lo está

Saludos!

Hola César. Efectivamente eso que mencionas es la clave.

La funciones (métodos) de la clase : name_size(), get_names(), get_ages() no las declaré como constantes.

Pero luego en las funciones donde modifico los operadores de comparacion y output, ahí los objetos que paso como parametros a, b y np sí los recojo como constantes, entonces por eso el compilador me ponía pegas al querer aplicarles métodos no constantes.
Si hago copia de ellos en objetos "temporales" no constantes, entonces ya no me pone pegas, que es la solución que encontré, pero para nada es la óptima.

Ahora que ya he entendido el problema, me ha bastado con añadir const a las declaraciones de los métodos y así ya puedo prescindir de tener que hacer copias temporales de los objetos que recojo como parámetro.

Y mira que ya había leído anteriormente una advertencia sobre esto de aplicar métodos no constantes a objetos constantes....pero hasta que no metes la pata y te tienes que calentar la cabeza, pues no lo aprendes je je...

Os dejo abajo el código final, con otro main() adaptadado para comprobar que funcionan las modificaciones a los operadores de comparación.
Os recuerdo enlace para descargar la std_lib_facilities.h y poder compilarlo. Me parece que el que puse en el primer mensaje no funciona.


Por cierto, muy potente esto de poder "enseñar" a los operadores como mostrar, recoger y comparar los objetos de nuestras clases. Como mola ir aprendiendo estas cosillas...

Un saludo y pronto volveré por aquí, con una docena de dudas más jeje...

Código: [Seleccionar]
#include "..\..\..\..\lib\std_lib_facilities.h"

namespace Nombres {
class Name_pairs
{
public:
void read_names();
void read_ages();
void sort();
int name_size() const { return name.size(); }
vector <string> get_names() const { return name; }
vector <double> get_ages() const { return age; }
private:
vector <string> name;
vector <double> age;
};

void Name_pairs::read_names()
{
string nombre;
do
{
cout << "\nIntroduza nombre(*=FIN): ";
cin >> nombre;
if (nombre != "*") name.push_back(nombre);

} while (nombre != "*");
}

void Name_pairs::read_ages()
{
int t = name.size();
double edad;
if (t == 0)
{
cout << "\nPrimero hay que introducir nombres...\n";
}
else
{
for (int i = 0; i < t; i++)
{
cout << "\nIntroduzca la edad de: " << name[i] << " --> ";
cin >> edad;
age.push_back(edad);
}
}
}

void operator<<(ostream& os, const Name_pairs& np)
{
int t = np.name_size();
if (t == 0)
{
cout << "\nNo hay datos que mostrar.\n";
}
else
{
for (int i = 0; i < t; i++)
{
cout << "\nNombre: " << np.get_names()[i] << " Edad: " << np.get_ages()[i];
}
}

}

bool operator==(const Name_pairs& a, const Name_pairs& b)
{
if (a.name_size() != b.name_size()) return false;//Si los vectores tienen distintos tamaños, los objetos no pueden ser iguales
for (int i = 0; i < a.name_size(); i++)//Recorremos vectores para comparar sus contenidos
{
if (a.get_names()[i] != b.get_names()[i]) return false;//Si algun nombre no coincide, se acabó, no son iguales
else if (a.get_ages()[i] != b.get_ages()[i]) return false;//Si alguna edad no coincide, se acabó, no son iguales
}

return true;//Si hemos llegado a esta línea, es que vectores son del mismo tamaño y sus elementos coinciden, así que son iguales
}

bool operator!=(const Name_pairs& a, const Name_pairs& b)
{
if (a.name_size() != b.name_size()) return true;
for (int i = 0; i < a.name_size(); i++)
{
if (a.get_names()[i] != b.get_names()[i]) return true;
else if (a.get_ages()[i] != b.get_ages()[i]) return true;
}

return false;
}

void Name_pairs::sort()
{
int t = name.size();
if (t == 0)
{
cout << "\nNo hay datos que ordenar.\n";
}
else
{
vector <string> name_temp;
vector <double> age_temp;
for (int i = 0; i < t; i++)
{
name_temp.push_back(name[i]);
age_temp.push_back(age[i]);
}

std::sort(name.begin(), name.end());

//Busca coincidencias entre los vectores de nombres original y ordenado para "copiar" el mismo orden en el vector de edad.
//Esta funcion podria ser errónea si hubieran nombres repetidos en el vector.
for (int i = 0; i < t; i++)
{
for (int j = 0; j < t; j++)
{
if (name_temp[i] == name[j]) age[j] = age_temp[i];
}
}
}

}
}//namespace Nombres

int main()
{
using namespace Nombres;

cout << system("cls");
Name_pairs listado, listado2;

listado.read_names();
listado.read_ages();
listado2 = listado;
cout << "\nSe ha hecho copia del listado, en listado2\n";
cout << "Antes de ordenar listado...";
cout << "\nlistado == listado2 --> ";
if (listado == listado2) cout << "Cierto.\n";
else cout << "Falso.\n";
cout << "\nlistado != listado2 --> ";
if (listado != listado2) cout << "Cierto.\n";
else cout << "Falso.\n";
cout << endl;
listado.sort();
cout << "Despues de ordenar listado...";
cout << "\nlistado == listado2 --> ";
if (listado == listado2) cout << "Cierto.\n";
else cout << "Falso.\n";
cout << "\nlistado != listado2 --> ";
if (listado != listado2) cout << "Cierto.\n";
else cout << "Falso.\n";
cout << endl;

return 0;
}

980
Añado las funciones que faltaban para cumplir el enunciado, es decir, modificar los operadores de comparacion == y != para que sepa como comparar correctamente dos objetos del tipo Name_pairs.
Ambas funciones son idénticas, solo cambian los valores que devuelven.

De nuevo he tenido que pasar los objetos que recibo como parámetros (a y b) a unas variables/objeto temporales (aa y bb). ¿Por qué no puedo operar directamente con a y b?

Código: [Seleccionar]
bool operator==(const Name_pairs& a, const Name_pairs& b)
{
Name_pairs aa = a;
Name_pairs bb = b;

if (aa.name_size() != bb.name_size()) return false;//Si los vectores tienen distintos tamaños, los objetos no pueden ser iguales
for (int i = 0; i < aa.name_size(); i++)//Recorremos vectores para comparar sus contenidos
{
if (aa.get_names()[i] != bb.get_names()[i]) return false;//Si algun nombre no coincide, se acabó, no son iguales
else if (aa.get_ages()[i] != bb.get_ages()[i]) return false;//Si alguna edad no coincide, se acabó, no son iguales
}

return true;//Si hemos llegado a esta línea, es que vectores son del mismo tamaño y sus elementos coinciden, así que son iguales
}

bool operator!=(const Name_pairs& a, const Name_pairs& b)
{
Name_pairs aa = a;
Name_pairs bb = b;

if (aa.name_size() != bb.name_size()) return true;
for (int i = 0; i < aa.name_size(); i++)
{
if (aa.get_names()[i] != bb.get_names()[i]) return true;
else if (aa.get_ages()[i] != bb.get_ages()[i]) return true;
}

return false;
}

Páginas: 1 ... 44 45 46 47 48 [49] 50

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".