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 ... 19 20 21 22 23 [24] 25 26 27 28 29 ... 50
461
Bueno, para empezar, sería saber en que lenguaje tienes que programarlo.


Luego, una forma que se me ocurre ahora mismo para resolverlo, sería utilizar una matriz de tipo char/caracteres. O también de String, podría servir.

Cada fila de la matriz podría estar compuesta de un tipo de carácter.
Por ejemplo, la primera fila, letras minúsculas.
Segunda, mayúsculas. Tercera, números. Cuarta, caracteres especiales.

abcdefghijklmn...
ABCDEFGHIJKLMN...
123456789012345...
|!"@·#$~%¬&/()...

Entonces, según lo que escoja el usuario, obtenemos posiciones al azar de las filas correspondientes.

Si solo quiere minúsculas, pues solo cogemos de la primera fila, la [ 0 ].
Y para la columna generamos un random, según la longitud de la matriz.
Supongamos que es 4x50.
Pues, escrito en una especie de pseudocódigo:
Código: [Seleccionar]
int col = random entre 0 y 49
obtener matriz[0][col]

Si quieres minúsculas y caracteres especiales, pues habría que coger de fila [ 0 ] y de [3]
¿Cómo hacemos para elegir aleatoriamente de una fila u otra.
Pues lo mismo, generando más valores random.
Podemos poner esos dos valores de fila en un array y sacar de ahí un valor u otro de forma random

Código: [Seleccionar]
int[] filasElegidas = {0,3}; //Minúsculas y especiales
int azar = random entre 0 y 1;
int fila = filasElegidas[azar];
int col = random entre 0 y 49
obtener matriz[fila][col]

Este proceso de obtención elementos al azar de la matriz, se haría dentro de un bucle que se repita tantas veces como el usuario haya indicado como longitud para su contraseña

462
Lo primero, es crear una clase Terminal con los tres atributos que mencionas: id, nombre y lugar.
Con sus getter, setters y un método toString() que podemos usar para decidir como queremos que se escriban los datos en el archivo TXT.

Código: [Seleccionar]
public class Terminal {

private String id;
private String lugar;
private String nombre;

public Terminal(String id, String nombre, String lugar) {
this.id = id;
this.lugar = lugar;
this.nombre = nombre;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getLugar() {
return lugar;
}

public void setLugar(String lugar) {
this.lugar = lugar;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

@Override
public String toString() {
return String.format("%s -- %s -- %s", id, lugar, nombre);
}
}

A continuación, una clase que se encargue gestionar las Terminales.
Las coleccionará en un ArrayList y tendrá métodos para registrar y modificar terminales.
Pero también para guardar en archivo TXT, recuperar esa información al iniciar el programa y proporcionar otros datos que necesitará la interfaz gráfica.
Cada método está documentado y tiene comentarios explicando como funciona.

Código: [Seleccionar]
public class RegistroTerminales {

private ArrayList<Terminal> terminales;

public RegistroTerminales() {
terminales = new ArrayList<Terminal>();
recuperarTXT();
}

/**
* Busca una Terminal por ID y la retorna
* @param id String con el ID a buscar
* @return El objeto Terminal asociado al ID
*/
public Terminal getTerminal(String id) {
Terminal buscar = null;
//Buscamos la terminal solicitada por ID
for (Terminal ter: terminales)
if (ter.getId().equals(id))
buscar = ter;
//Retornamos terminal encontrada o null si no existe ese ID
return buscar;
}

/**
* Registra una nueva Terminal, siempre que no hayan otras dos terminales
* en el mismo lugar indicado.<br>Durante el registro se autogenera un ID
* y se retorna.
* @param nombre Nombre de la Terminal
* @param lugar Lugar de la Terminal
* @return Nuevo ID de la Terminal
*/
public String registrarTerminal(String nombre, String lugar) {
String id = null;
//Comprobamos si ya hay dos terminales en el mismo lugar
if (contarLugar(lugar) >= 2)
JOptionPane.showMessageDialog(null, "Ya hay al menos dos terminales en el mismo LUGAR."
+ "\nNo se registrará esta terminal", "Registrar Terminal", JOptionPane.WARNING_MESSAGE);
else {
//Generamos ID
id = String.format("ID%04d", terminales.size());
//Registramos terminal
terminales.add(new Terminal(id, nombre, lugar));
JOptionPane.showMessageDialog(null, "Nueva terminal registrada.",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
//Guardamos en disco
guardarTXT();
}
//Retornamos ID, puede ser nulo si se rechazó el registro
return id;
}

/**
* Se modifica la Terminal asociada al ID recibido. Si se intenta modificar
* el lugar, previamente se comprobará si ya existen otras dos terminales el
* ese nuevo lugar, en cuyo caso se rechazará la modificación.
* @param id ID de la Terminal que se quiere modificar.
* @param nombre Nuevo nombre para la Terminal.
* @param lugar Nuevo Lugar para la Terminal.
*/
public void modificarTerminal(String id, String nombre, String lugar) {

Terminal modificar = null;
for (Terminal ter: terminales)
if (ter.getId().equals(id)) {
modificar = ter;
break;
}
if (modificar == null)
//No se ha encontrado terminal por esa ID, es muy improbable que esto ocurra
//pero aún así vamos a contemplar esta posibilidad.
JOptionPane.showMessageDialog(null, "No se ha encontrado la terminal con ID: " + id +
"\nPosible inconsistencia de datos, reinicie la aplicación.",
"Modificar Terminal", JOptionPane.ERROR_MESSAGE);
else {
/*
* Puesto que solo se admiten dos terminales en un mismo lugar, hay que
* comprobar que con la opción modificar no se puedan cambiar los "lugares"
* y superar ese limite de dos terminales x lugar
* Así que vamos a comprobar si se quiere modificar el lugar para comprobar
* si ya hay dos terminales en el nuevo lugar que se quiere establecer
*/
if (modificar.getLugar().equals(lugar)) { //El lugar no cambia, solo se modifica el nombre
modificar.setNombre(nombre);
JOptionPane.showMessageDialog(null, "Terminal modificada",
"Modificar Terminal", JOptionPane.INFORMATION_MESSAGE);
guardarTXT();
}
else {//El lugar SI cambia, solo lo admitimos si no existen ya dos terminales en el nuevo lugar
if (contarLugar(lugar) >= 2)
JOptionPane.showMessageDialog(null, "Ya hay al menos dos terminales en el mismo LUGAR."
+ "\nNo se modificará esta terminal", "Modificar Terminal", JOptionPane.WARNING_MESSAGE);
else {
modificar.setNombre(nombre);
modificar.setLugar(lugar);
JOptionPane.showMessageDialog(null, "Terminal modificada",
"Modificar Terminal", JOptionPane.INFORMATION_MESSAGE);
guardarTXT();
}
}
}
}

/**
* Hace un recuento de cuántas Terminales comparten lugar.<br>
* Hay un límite de 2 Terminales por lugar, este método ayuda
* a controlar este límite.
* @param lugar Lugar que se va a comprobar cuantas Terminales comparten.
* @return Cantidad de Terminales que comparten el lugar indicado.
*/
private int contarLugar(String lugar) {
int cont = 0;
for (Terminal ter: terminales)
if (ter.getLugar().equals(lugar))
cont++;

return cont;
}

/**
* Crea un array con todos los ID de Terminales registrados.<br>
* Se empleará para inicializar el JComboBox del panel "Modificar"
* para poder seleccionar ID
* @return Array con los ID.
*/
public String[] getIDRegistrados() {
String[] ids = new String[terminales.size()];
for (int c = 0; c < terminales.size(); c++)
ids[c] = terminales.get(c).getId();

return ids;
}

/**
* Lee el archivo TXT que contiene los datos de las Terminales registradas.
*/
private void recuperarTXT() {

try {
BufferedReader br = new BufferedReader(new FileReader("terminales.txt"));
String linea = br.readLine();
while(linea != null) {
String[] datos = linea.split(" -- ");
terminales.add(new Terminal(datos[0], datos[1], datos[2]));
linea = br.readLine();
}
br.close();
JOptionPane.showMessageDialog(null, "Se han recuperado " + terminales.size() +
"  terminales del archivo TXT", "Recuperar TXT", JOptionPane.INFORMATION_MESSAGE);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "No existe archivo terminales.txt",
"Recuperar TXT", JOptionPane.WARNING_MESSAGE);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error accediendo a terminales.txt",
"Recuperar TXT", JOptionPane.WARNING_MESSAGE);
}
}

/**
* Guarda los datos de las Terminales registradas en un archivo TXT.
*/
private void guardarTXT() {

try {
BufferedWriter bw = new BufferedWriter(new FileWriter("terminales.txt", false));
for (Terminal ter: terminales) {
bw.write(ter.toString());
bw.newLine();
}
bw.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error accediendo a terminales.txt",
"Guardar TXT", JOptionPane.WARNING_MESSAGE);
}
}

}

Y por último, la interfaz.
Un JFrame, con dos paneles con pestañas para elegir.
Una para crear nuevo Terminal, el otro para modificar las existentes.

Para modificar, se muestran los ID de las terminales existentes mediante un JComboBox y al ir seleccionado se muestran los datos de cada terminal, pudiendo modificar los datos.

Tanto para crear Terminal, como para modificar, se va a tener en cuenta el límite de solo 2 terminales en un mismo lugar.

Código: [Seleccionar]
public final class GestionTerminales extends JFrame{

private RegistroTerminales registro;
private JTextField jtNombreNuevo;
private JTextField jtLugarNuevo;
private JButton botonNuevo;
private JComboBox<String> selectorID;
private JTextField jtNombreModif;
private JTextField jtLugarModif;
private JButton botonModif;

public GestionTerminales() {

registro = new RegistroTerminales();

JTabbedPane paneles = new JTabbedPane();
paneles.addTab("Registrar", new PanelRegistrar());
paneles.addTab("Modificar", new PanelModificar());
paneles.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
getContentPane().add(paneles);

setTitle("Gestion Terminales");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

//Paneles de la interfaz gráfica
private final class PanelRegistrar extends JPanel {

public PanelRegistrar() {

jtNombreNuevo = new JTextField(8);
jtLugarNuevo = new JTextField(8);
botonNuevo = new JButton("Registrar");
botonNuevo.addActionListener(new AccionRegistrar());

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel pnCampos = new JPanel();
pnCampos.setLayout(new BoxLayout(pnCampos, BoxLayout.Y_AXIS));
pnCampos.add(new PanelLabelCampo("Nombre:", jtNombreNuevo));
pnCampos.add(new PanelLabelCampo("Lugar:", jtLugarNuevo));
pnCampos.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedSoftBevelBorder(),
BorderFactory.createEmptyBorder(20, 20, 20, 20)));
add(pnCampos);
add(new JSeparator());
JPanel pnBoton = new JPanel();
pnBoton.add(botonNuevo);
add(pnBoton);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
}

private final class PanelModificar extends JPanel {

public PanelModificar() {
selectorID = new JComboBox<String>(registro.getIDRegistrados());
selectorID.addActionListener(new AccionSeleccionarID());
jtNombreModif = new JTextField(8);
jtLugarModif = new JTextField(8);
botonModif = new JButton("Modificar");
botonModif.addActionListener(new AccionModificar());
//Si comenzamos sin terminales para modificar, desactivamos controles de este panel
if (selectorID.getItemCount() == 0) {
selectorID.setEnabled(false);
jtNombreModif.setEnabled(false);
jtLugarModif.setEnabled(false);
botonModif.setEnabled(false);
}
else //Sí hay terminales, seleccionamos la primera
selectorID.setSelectedIndex(0);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel pnCampos = new JPanel();
pnCampos.setLayout(new BoxLayout(pnCampos, BoxLayout.Y_AXIS));
pnCampos.add(new PanelLabelCampo("Seleccione ID:", selectorID));
pnCampos.add(new PanelLabelCampo("Nombre:", jtNombreModif));
pnCampos.add(new PanelLabelCampo("Lugar:", jtLugarModif));
pnCampos.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedSoftBevelBorder(),
BorderFactory.createEmptyBorder(20, 20, 20, 20)));
add(pnCampos);
add(new JSeparator());
JPanel pnBoton = new JPanel();
pnBoton.add(botonModif);
add(pnBoton);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
}

private final class PanelLabelCampo extends JPanel {

public PanelLabelCampo(String textoLabel, JComponent campo) {
add(new JLabel(textoLabel));
add(campo);
setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
}
}

//Listener de botones y combobox
private final class AccionRegistrar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos
String nombre = jtNombreNuevo.getText();
String lugar = jtLugarNuevo.getText();
//Comprobamos que no estan vacíos
if (nombre.isBlank())
JOptionPane.showMessageDialog(null, "Campo nombre no puede estar vacío",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
else if (lugar.isBlank())
JOptionPane.showMessageDialog(null, "Campo lugar no puede estar vacío",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
else {
//Registramos y obtenemos el ID autogenerado
String id = registro.registrarTerminal(nombre, lugar);
if (id != null) {//Registro aprobado
//Limpiamos formulario
jtNombreNuevo.setText(null);
jtLugarNuevo.setText(null);
//Actualizamos comboBox
selectorID.addItem(id);
//Comprobamos si es necesario activar los controles de panel Modificar
if (!selectorID.isEnabled()) {
selectorID.setEnabled(true);
jtNombreModif.setEnabled(true);
jtLugarModif.setEnabled(true);
botonModif.setEnabled(true);
}
}

}

}
}

private final class AccionModificar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos
String id = (String) selectorID.getSelectedItem();
String nombre = jtNombreModif.getText();
String lugar = jtLugarModif.getText();
//Comprobamos que no estan vacíos
if (nombre.isBlank())
JOptionPane.showMessageDialog(null, "Campo nombre no puede estar vacío",
"Modificar Terminal", JOptionPane.WARNING_MESSAGE);
else if (lugar.isBlank())
JOptionPane.showMessageDialog(null, "Campo lugar no puede estar vacío",
"Modificar Terminal", JOptionPane.WARNING_MESSAGE);
else
registro.modificarTerminal(id, nombre, lugar);

}
}

private final class AccionSeleccionarID implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String id = (String) selectorID.getSelectedItem();
Terminal ter = registro.getTerminal(id);
jtNombreModif.setText(ter.getNombre());
jtLugarModif.setText(ter.getLugar());
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GestionTerminales();
}
});
}

}

463
El problema de GET y que los datos sean visibles en la URL, no es tanto que el usuario pueda modificarlos.

Es sobre todo un problema de seguridad. Esa URL, con los datos personales, queda guardada en el historial de navegador.
Esto implica que si se trata de un ordenador compartido, otra persona puede consultar el historial de navegación y ver esos datos personales: nombre, teléfono, domicilio, nº seguridad social, contraseñas, claves.... La privacidad de esos datos es nula.

En ese caso, usar POST no es que sea mejor, es que es imprescindible.

Sin embargo, en otros casos donde no tenga importancia la privacidad, GET puede ser interesante.

Por ejemplo, en un buscador. En el mismo Google.
Supón que quiero compartir con otros una búsqueda de "Cursos Java", o guardarla para futura referencias.
Gracias a GET, tengo un enlace para compartir y guardar:
https://www.google.com/search?q=curso+java

No será necesario volver a escribir esos términos en el formulario de búsqueda de Google, basta con clickar en ese enlace y ya obtengo la búsqueda.

Esto en cambio, no es posible con POST.
Por ejemplo en este mismo foro, si vamos a la opción de búsqueda, escribimos unos términos y hacemos la búsqueda obtendremos unos resultados.
Pero el formulario funciona con método POST, así que no voy a disponer de una URL que represente la búsqueda que he hecho.
Por tanto no voy a poder guardarla, ni compartirla...siempre que quiera replicar esa búsqueda, tendré que teclear de nuevo esos términos en el formulario.

Así que en este caso puede ser más interesante usar GET..., o tal vez no..., quizás queramos proteger la privacidad del usuario y evitar que los términos de su búsqueda queden reflejados en una URL en el historial...

Como ves todo tiene unos contrapesos, no hay uno mejor o peor. Son diferentes y usar uno u otro dependerá de cada caso.

464
Es verdad que las meta keywords ya no cuenta para el posicionamiento. La culpa es del mal uso que hacían los webmasters de ellas al incluir cientos de palabras clave que "garantizaban" buen posicionamiento aunque luego no tuvieran nada que ver con el contenido de la página.
Así que como dejaron de ser descriptivas del contenido real, los principales buscadores las dejaron de lado.

Sin embargo, creo que no todos las han abandonado por completo.
Google si las ignora por completo, no cuentan ni para posicionar ni para indexar.

Yahoo!, al menos hasta hace poco, no las tenía en cuenta para posicionar pero si para indexar páginas.
Bing de Microsoft parece que sí seguía dándoles algo de relevancia para posicionamiento, pero muy poco, no son el factor determinante.

Así que a pesar de todo, puede ser interesante seguir usándolas, pero siempre teniendo en cuenta que lo que realmente dará buen posicionamiento será la calidad del contenido y no intentar usar palabras "mágicas".

Si miramos el código HTML de webs importantes, muchas siguen usándolas, por ejemplo Amazon...
Asi que, ¿por qué no usarlas nosotros también? Además, no supone ningún esfuerzo ponerlas.

Citar
<meta name="keywords" content="Amazon, amazon.es, compras online, electrónica, música, libros, videojuegos,  CDs, DVD,  video, TV, ordenadores, software, móviles, juegos, muebles, juguetes, ropa, accesorios, moda, zapatos, joyas, relojes, productos de oficina, deporte, productos deportivos, bebés, salud, cuidado personal, hogar, cocina, jardín, herramientas, recambios, mascotas, informática, tienda online, envíos gratis, bricolaje, decoración, eBooks, aire libre, supermercado, belleza, jardinería, regalos, instrumentos musicales">

465
Hummm... como no sabemos tu código no se cuál sería la mejor forma de ayudarte.

Pero si te sirve de inspiración, dejo aquí un ejemplo sencillo usando la clase LocalDate:

Código: [Seleccionar]
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;

public class Fecha {

public static void main(String[] args) {

Scanner teclado = new Scanner(System.in);
System.out.print("Dia: ");
int dia = teclado.nextInt();
System.out.print("Mes: ");
int mes = teclado.nextInt();
System.out.print("Año: ");
int anio = teclado.nextInt();

//Construimos fecha
LocalDate fecha = LocalDate.of(anio, mes, dia);
//Obtenemos fecha actual
LocalDate hoy = LocalDate.now();

//Elegimos formato para mostrar las fechas
DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd/MM/yyyy");

System.out.println("\nFecha pedido: " + fecha.format(formato));
System.out.println("Fecha del sistema: " + hoy.format(formato));

//Comparamos fechas
if (fecha.isBefore(hoy))
System.out.println("Fecha de pedido no puede ser inferior a la del sistema");
else
System.out.println("Fecha aceptada");

teclado.close();

}

}

Si lo ejecutamos, vemos esto en pantalla:
Citar
Dia: 1
Mes: 1
Año: 2021

Fecha pedido: 01/01/2021
Fecha del sistema: 06/04/2021
Fecha de pedido no puede ser inferior a la del sistema

466
Lo de modificar nota te falla porque, a pesar de que buscas el carnet de alumno, no estás recuperando en que posición se encuentra ese carnet.
Usas una variable llamada "nueva" inicializada a 0 para elegir las calificaciones que vas a alterar, por eso siempre te va a modificar la primera línea de los arreglos.
Te señalo en rojo donde está el problema:
Citar
   public static void modificar(){
      boolean elCarnetEsta = false;

      String car = JOptionPane.showInputDialog("INGRESA EL CARNET DEL ALUMNO");

      for(int contador=0; contador < tamaño; contador++)
         if (car.equals(carnet[contador])){
            elCarnetEsta = true;

            int seleccion;
            int nueva = 0;
            seleccion =Integer.parseInt(JOptionPane.showInputDialog("QUE NOTA DESEAS CAMBIAR: \n1.\n2.\n3.\n4."));

            if(seleccion==1){

               calific[nueva] =Integer.parseInt(JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));

            }

            else if(seleccion==2){

               calific2[nueva] =Integer.parseInt(JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));

            }

            else if(seleccion==3){

               calific3[nueva] =Integer.parseInt(JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));

            }

            else if(seleccion==4){

               calific4[nueva] =Integer.parseInt(JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));

            }

         }

      if(elCarnetEsta == false) {
         JOptionPane.showMessageDialog(null, "EL CARNET NO EXISTE");
      }

   }

No hay que usar esa variable, basta con usar la variable "contador" del mismo bucle donde estamos buscando el carnet.
Además esa misma variable nos sirve para recalcular el promedio:
Citar
   public static void modificar(){
      boolean elCarnetEsta = false;

      String car = JOptionPane.showInputDialog("INGRESA EL CARNET DEL ALUMNO");

      for(int contador=0; contador < tamaño; contador++)
         if (car.equals(carnet[contador])){
            elCarnetEsta = true;
            
            int seleccion = Integer.parseInt(
                  JOptionPane.showInputDialog("QUE NOTA DESEAS CAMBIAR: \n1.\n2.\n3.\n4."));

            if(seleccion==1)
               calific[contador] = Integer.parseInt(
                     JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
            else if(seleccion==2)
               calific2[contador] = Integer.parseInt(
                     JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
            else if(seleccion==3)
               calific3[contador] = Integer.parseInt(
                     JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
            else if(seleccion==4)
               calific4[contador] = Integer.parseInt(
                     JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
            
            //Nota cambiada, hay que recalcular el promedio
            promedios[contador] = (calific[contador] + calific2[contador] +
                  calific3[contador] + calific4[contador]) / 4;

            //Ya hemos encontrado alumno y cambiado su nota, podemos interrumpir este bucle
            break;
         }

      if(elCarnetEsta == false) {
         JOptionPane.showMessageDialog(null, "EL CARNET NO EXISTE");
      }

   }


Con esto ya se puede Agregar Estudiante y Modificar Nota.
Lo de Listar Estudiante habría que hacer un pequeño cambio para mostrar el promedio:
Citar
   public static void listar(){

      //Mostrar alumno y su calificacion en pantalla:
      System.out.println("Numero\tCarnet\tNombre\tnota1\tnota2\tnota3\tnota4\tPromedio");
      for(int contador=0; contador < nombres.length; contador++)
         System.out.println(contador+1+"\t" + carnet[contador]+"\t"+nombres[contador]+"\t"
               +calific[contador]+"\t"+calific2[contador]+"\t"+calific3[contador]+
               "\t"+calific4[contador]+"\t"+promedios[contador]);
   }

Bien, ya solo te queda hacer lo de Eliminar Estudiante, inténtalo y lo consigas o no, compártelo por aquí y te ayudamos a corregirlo.

Antes de terminar, quiero comentar un par de cosas.

En cada método, al terminar, haces una llamada al método menu(), que es el menu principal que muestra las opciones.
Esto no es necesario, es más, es peligroso...y ahora verás por qué..

Cuando el programa se inicia, comienza el método main() que llama a menu() y lo pone en marcha.
main() no hace nada, ahora mismo es menu() quien se encarga de todo
main() > menu()

Si dentro de menu(), llamamos por ejemplo a agregar(), esto no significa que el método menu() termine. Sigue ejecutándose, lo que ocurre es que queda a espera de que agregar() haga sus cosas y termine.
Ahora, es agregar() quien está al cargo de la ejecución del programa:
main() > menu() > agregar()

El método agregar() lo que hace es iniciar un bucle y pedir datos al usuario.
Si nos fijamos en cómo he escrito yo su código:
Citar
   public static void agregar(){

      //Pedir tamaño del Arreglo al usuario:
      tamaño=Integer.parseInt(JOptionPane.showInputDialog
            ("¿De que tamaño desea su Arreglo?"));

      //recibe los arreglos globalizados arriba
      nombres = new String[tamaño];
      carnet = new String[tamaño];
      calific = new int[tamaño];
      calific2 = new int[tamaño];
      calific3 = new int[tamaño];
      calific4 = new int[tamaño];
      promedios = new int[tamaño];
      
      //Pedimos datos
      for (int contador = 0; contador < tamaño; contador++) {
         //Carnet
         carnet[contador]=JOptionPane.showInputDialog
               ("Carnet del alumno");
         //Nombre
         nombres[contador]=JOptionPane.showInputDialog
               ("Nombre?");
         //Calificaciones
         calific[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 1 de "
                           +nombres[contador]+"?"));
         calific2[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 2 de "
                           +nombres[contador]+"?"));
         calific3[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 3 de "
                           +nombres[contador]+"?"));
         calific4[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 4 de "
                           +nombres[contador]+"?"));
         //Calculamos promedio
         promedios[contador] = (calific[contador] + calific2[contador] +
               calific3[contador] + calific4[contador]) / 4;
      }
      //Fin del bucle que pide datos
   }

Cuando este bucle termina, ahí donde he puesto el comentario azul, agregar() ya no tiene nada más que hacer, así que este método termina y devuelve el hilo de ejecución al método menu()
main() > menu()
Esto es lo ideal, ahora menu() puede volver llamar a agregar(), o a listar().., o terminar si el usuario lo ordena y fin del progama.

Pero, ¿y si hacemos lo que tú has hecho, llamar a menu() al terminar el método:
Citar
   public static void agregar(){

      //Pedir tamaño del Arreglo al usuario:
      tamaño=Integer.parseInt(JOptionPane.showInputDialog
            ("¿De que tamaño desea su Arreglo?"));

      //recibe los arreglos globalizados arriba
      nombres = new String[tamaño];
      carnet = new String[tamaño];
      calific = new int[tamaño];
      calific2 = new int[tamaño];
      calific3 = new int[tamaño];
      calific4 = new int[tamaño];
      promedios = new int[tamaño];
      
      //Pedimos datos
      for (int contador = 0; contador < tamaño; contador++) {
         //Carnet
         carnet[contador]=JOptionPane.showInputDialog
               ("Carnet del alumno");
         //Nombre
         nombres[contador]=JOptionPane.showInputDialog
               ("Nombre?");
         //Calificaciones
         calific[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 1 de "
                           +nombres[contador]+"?"));
         calific2[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 2 de "
                           +nombres[contador]+"?"));
         calific3[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 3 de "
                           +nombres[contador]+"?"));
         calific4[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 4 de "
                           +nombres[contador]+"?"));
         //Calculamos promedio
         promedios[contador] = (calific[contador] + calific2[contador] +
               calific3[contador] + calific4[contador]) / 4;
      }
      //Fin del bucle que pide datos
      menu(); //Llamamos a menu()
   }

Esta llamada, implica que el método agregar() NO TERMINA.
Lo que hace es generar una nueva instancia de menu(), pero no el mismo menu() que le había llamado a él, este es "otro" menu() distinto:

main() > menu() > agregar() > menu()

Y si este nuevo menu(), llama ahora a listar()...

main() > menu() > agregar() > menu() > listar()

Y como listar(), en tu código, cuando termina también llama a menu(), pues...
main() > menu() > agregar() > menu() > listar() > menu()

¿Ves lo que ocurre?
Los métodos no finalizan, porque se están produciendo unas llamadas "recursivas" que hacen que el hilo de ejecución se vaya pasando de un método a otro, pero sin que ninguno termine...los métodos se van anidando unos dentro de otros.

¿Esto es un problema?
Pues sí. Es cierto que en este caso, al ser un ejercicio sencillo, no notamos nada raro a nivel usuario.
Pero en un programa más complejo, podríamos encontrarnos con que unos datos que yo he introducido, luego se viesen alterados por un método que había quedado anidado anteriormente.
Y además, cada método anidado se almacena en una "pila", y esta pila tiene un límite. El límite es bastante amplio, pero si esto ocurre en un programa profesional de una empresa que tiene el ordenador funcionando 24 horas al día, tarde o temprano la pila se desbordaría y el programa caería.


Por eso los métodos de este programa, no deben terminar llamando de nuevo a menu().
No es necesario, cuando los métodos terminen sus tareas, menu() recuperará automáticamente el hilo de ejecución.

Por último te dejo mi código al completo tal y como lo tengo ahora.
He quitado algunas cosas como el objeto Scanner que no va a ser necesario, o un método llamado buscar() que habías puesto vacío, que tampoco parece que vaya a tener función alguna.
Un saludo.

Código: [Seleccionar]
import javax.swing.JOptionPane;


public class Arreglo {

//Crear y establecer tamaño de los Arreglos de manera global para que
//funcione en los demas metodos:

public static int tamaño;

private static String carnet[];
private static String nombres[];
private static int calific[];
private static int calific2[];
private static int calific3[];
private static int calific4[];
private static int promedios[];


public static void main(String[] args) {
menu();
}

public static void menu(){
String opcion;

do {

opcion =JOptionPane.showInputDialog("------------REGISTRO DE ESTUDIANTES------------"
+ " \n1. INGRESAR ESTUDIANTES\n2. MODIFICAR NOTA\n3. ELIMINAR ESTUDIANTE\n4. LISTAR ESTUDIANTES\ns. Salir"
+ "\n------------------------------------------------\nINGRESE LA OPCION [1 - 4]: ");

switch (opcion) {
case "1":
agregar();
break;
case "2":
modificar();
break;
case "3":
eliminar();
break;
case "4":
listar();
break;
case "s":
System.exit(0);
break;
default:
break;
}
} while (true);

}

public static void agregar(){

//Pedir tamaño del Arreglo al usuario:
tamaño=Integer.parseInt(JOptionPane.showInputDialog
("¿De que tamaño desea su Arreglo?"));

//recibe los arreglos globalizados arriba
nombres = new String[tamaño];
carnet = new String[tamaño];
calific = new int[tamaño];
calific2 = new int[tamaño];
calific3 = new int[tamaño];
calific4 = new int[tamaño];
promedios = new int[tamaño];

//Pedimos datos
for (int contador = 0; contador < tamaño; contador++) {
//Carnet
carnet[contador]=JOptionPane.showInputDialog
("Carnet del alumno");
//Nombre
nombres[contador]=JOptionPane.showInputDialog
("Nombre?");
//Calificaciones
calific[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 1 de "
+nombres[contador]+"?"));
calific2[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 2 de "
+nombres[contador]+"?"));
calific3[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 3 de "
+nombres[contador]+"?"));
calific4[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 4 de "
+nombres[contador]+"?"));
//Calculamos promedio
promedios[contador] = (calific[contador] + calific2[contador] +
calific3[contador] + calific4[contador]) / 4;
}
//Fin del bucle que pide datos
}

public static void modificar(){
boolean elCarnetEsta = false;

String car = JOptionPane.showInputDialog("INGRESA EL CARNET DEL ALUMNO");

for(int contador=0; contador < tamaño; contador++)
if (car.equals(carnet[contador])){
elCarnetEsta = true;

int seleccion = Integer.parseInt(
JOptionPane.showInputDialog("QUE NOTA DESEAS CAMBIAR: \n1.\n2.\n3.\n4."));

if(seleccion==1)
calific[contador] = Integer.parseInt(
JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
else if(seleccion==2)
calific2[contador] = Integer.parseInt(
JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
else if(seleccion==3)
calific3[contador] = Integer.parseInt(
JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));
else if(seleccion==4)
calific4[contador] = Integer.parseInt(
JOptionPane.showInputDialog("NUEVA NOTA ["+seleccion+"]"));

//Nota cambiada, hay que recalcular el promedio
promedios[contador] = (calific[contador] + calific2[contador] +
calific3[contador] + calific4[contador]) / 4;

//Alumno encontrado y cambiado su nota y promedio, podemos interrumpir este bucle
break;
}

if(elCarnetEsta == false) {
JOptionPane.showMessageDialog(null, "EL CARNET NO EXISTE");
}

}

public static void listar(){

//Mostrar alumno y su calificacion en pantalla:
System.out.println("Numero\tCarnet\tNombre\tnota1\tnota2\tnota3\tnota4\tPromedio");
for(int contador=0; contador < nombres.length; contador++)
System.out.println(contador+1+"\t" + carnet[contador]+"\t"+nombres[contador]+"\t"
+calific[contador]+"\t"+calific2[contador]+"\t"+calific3[contador]+
"\t"+calific4[contador]+"\t"+promedios[contador]);
}

public static void eliminar(){

}

}

467
¿Puedes publicar el enunciado original del ejercicio?
Tengo dudas de si la primera opción, la de "agregar estudiantes", se ha de hacer como lo has hecho tú, donde se registran TODOS los estudiantes...
o en cambio, dicha opción debería permitir ingresar estudiantes de uno en uno, con lo cuál el tamaño de los arrays debería decidirse previamente y no alterarse durante el transcurso del programa.

También sería interesante saber si para las calificaciones se puede usar una matriz (un array de dos dimensiones) o hay que usar cuatro arrays separados.

De momento, vamos a suponer que hay que hacerlo como tú lo has hecho.

Todos los estudiantes se registran al mismo tiempo.
Bien, esta parte del registro, se puede mejorar.
Por ejemplo, no necesitas crear un bucle para rellenar cada array.
Código: [Seleccionar]
//Insertar carnet de alumnos al Arreglo String
for(int contador=0; contador < carnet.length; contador++)
carnet[contador]=JOptionPane.showInputDialog
("Carnet del alumno");

//Insertar nombres de alumnos al Arreglo String:
for(int contador=0; contador < nombres.length; contador++)
nombres[contador]=JOptionPane.showInputDialog
("Nombre?");

//Insertar calificaciones de cada alumno al Arreglo int:
for(int contador=0; contador < calific.length; contador++)
calific[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 1 de "
+nombres[contador]+"?"));
for(int contador=0; contador < calific2.length; contador++)
calific2[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 2 de "
+nombres[contador]+"?"));

for(int contador=0; contador < calific3.length; contador++)
calific3[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 3 de "
+nombres[contador]+"?"));

for(int contador=0; contador < calific4.length; contador++)
calific4[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 4 de "
+nombres[contador]+"?"));

Se puede crear uno solo y que vaya pidiendo los datos correspondientes a cada array:
Código: [Seleccionar]
//Pedimos datos
for (int contador = 0; contador < tamaño; contador++) {
//Carnet
carnet[contador]=JOptionPane.showInputDialog
("Carnet del alumno");
//Nombre
nombres[contador]=JOptionPane.showInputDialog
("Nombre?");
//Calificaciones
calific[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 1 de "
+nombres[contador]+"?"));
calific2[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 2 de "
+nombres[contador]+"?"));
calific3[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 3 de "
+nombres[contador]+"?"));
calific4[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 4 de "
+nombres[contador]+"?"));
}

Respecto a calcular el promedio, de nuevo sería interesante disponer del enunciador original, pero seguramente lo que se ha de promediar son las 4 notas de cada alumno.
Es decir, por cada alumno, calcular el promedio de sus 4 notas.

Pero no sumar TODAS las notas y de ahí sacar un promedio.
De hecho, lo que tú has programado con esos bucles anidados, supone una barbaridad de iteraciones innecesarias:
Código: [Seleccionar]
//Sumar notas
for (int i = 0; i<calific.length; i++){
for (int j = 0; j<calific2.length; j++){
for (int k = 0; k<calific3.length; k++){
for (int f = 0; f<calific4.length; f++){

suma = calific[i] + calific2[j] + calific3[k] + calific4[f];
promedio = suma/4;

}


}

}

}
Supón que los arrays tienen 10 elementos, porque se ha elegido introducir a 10 alumnos.
Si anidas los bucles, lo que haces es que el primer bucle va a repetir 10 veces, las 10 iteraciones del segundo bucle, quien a su vez repite 10 veces las del tercer bucle, quien a su vez repite las 10 del cuarto bucle...
10x10x10x10 = 10.000 iteraciones
Es decir, estás haciendo que estos cálculos se repitan diez mil veces:
Código: [Seleccionar]
suma = calific[i] + calific2[j] + calific3[k] + calific4[f];
promedio = suma/4;
Y en cada repetición se están mezclando distintas notas, de distintos alumnos... así que ninguna de esas diez mil repeticiones nos va a dar el resultado que realmente necesitamos.

Si por cada alumno, vamos a necesitar un promedio de sus 4 notas, entonces va a ser conveniente tener otro array más destinado a guardar esos promedios.

Los promedios habrá que mostrarlos cuando se elija la opción de Listar Estudiantes, así que en realidad no sería estrictamente necesario tener los promedios guardados en un arreglo. Se podría hacer el cálculo "al vuelo" al mismo tiempo que se va listando cada Estudiante y mostrarlo directamente en pantalla.

Pero usar un arreglo específico para los promedios puede servir para organizar mejor las ideas, para que quede más clara la información que se está manejando en el programa.
Y además añade una dificultad extra: cuando se modifique la nota de un estudiante, entonces habrá que recalcular de nuevo el promedio.

Así que propongo añadir un nuevo arreglo para los promedios:

Citar
public class Arreglo {

   //Crear y establecer tamaño de los Arreglos de manera global para que
   //funcione en los demas metodos:

   public static int tamaño;

   private static String carnet[];
   private static String nombres[];
   private static int calific[];
   private static int calific2[];
   private static int calific3[];
   private static int calific4[];
   private static int promedios[];

Citar
   public static void agregar(){

      //Pedir tamaño del Arreglo al usuario:
      tamaño=Integer.parseInt(JOptionPane.showInputDialog
            ("¿De que tamaño desea su Arreglo?"));

      //recibe los arreglos globalizados arriba
      nombres = new String[tamaño];
      carnet = new String[tamaño];
      calific = new int[tamaño];
      calific2 = new int[tamaño];
      calific3 = new int[tamaño];
      calific4 = new int[tamaño];
      promedios = new int[tamaño];

Y cuando el usuario ha dado las 4 notas del Estudiante que está introduciendo, calculamos el promedio:
Citar
      //Pedimos datos
      for (int contador = 0; contador < tamaño; contador++) {
         //Carnet
         carnet[contador]=JOptionPane.showInputDialog
               ("Carnet del alumno");
         //Nombre
         nombres[contador]=JOptionPane.showInputDialog
               ("Nombre?");
         //Calificaciones
         calific[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 1 de "
                           +nombres[contador]+"?"));
         calific2[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 2 de "
                           +nombres[contador]+"?"));
         calific3[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 3 de "
                           +nombres[contador]+"?"));
         calific4[contador]=Integer.parseInt
               (JOptionPane.showInputDialog
                     ("Cual es la nota 4 de "
                           +nombres[contador]+"?"));
         //Calculamos promedio
         promedios[contador] = (calific[contador] + calific2[contador] +
               calific3[contador] + calific4[contador]) / 4;

      }

Bien, con esto lo de Agregar Estudiantes, podría quedar terminado de este modo.
Lo de listar los alumnos al terminar no lo he puesto, ya que para eso hay una opción específica en el menú, pero bueno, se puede dejar si quieres:
Código: [Seleccionar]
public static void agregar(){

//Pedir tamaño del Arreglo al usuario:
tamaño=Integer.parseInt(JOptionPane.showInputDialog
("¿De que tamaño desea su Arreglo?"));

//recibe los arreglos globalizados arriba
nombres = new String[tamaño];
carnet = new String[tamaño];
calific = new int[tamaño];
calific2 = new int[tamaño];
calific3 = new int[tamaño];
calific4 = new int[tamaño];
promedios = new int[tamaño];

//Pedimos datos
for (int contador = 0; contador < tamaño; contador++) {
//Carnet
carnet[contador]=JOptionPane.showInputDialog
("Carnet del alumno");
//Nombre
nombres[contador]=JOptionPane.showInputDialog
("Nombre?");
//Calificaciones
calific[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 1 de "
+nombres[contador]+"?"));
calific2[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 2 de "
+nombres[contador]+"?"));
calific3[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 3 de "
+nombres[contador]+"?"));
calific4[contador]=Integer.parseInt
(JOptionPane.showInputDialog
("Cual es la nota 4 de "
+nombres[contador]+"?"));
//Calculamos promedio
promedios[contador] = (calific[contador] + calific2[contador] +
calific3[contador] + calific4[contador]) / 4;
}
}

En el siguiente post vamos a ver lo de Modificar Nota

468
Uy, pues no creas que tengo tanta sapiencia en diseño web.
Seguro que cuando completes el curso sabrás más que yo je je..


Pero sí, para aplicar estilos a los elementos HTML invocamos una o varias de sus "propiedades" y le asignamos un nuevo "valor".
En el curso CSS se explica así:


469
Hola, el punto y coma no es obligatorio cuando aplicamos estilo solo a una propiedad.

Por ejemplo, a este párrafo le ponemos fondo rojo "tomate"

Código: [Seleccionar]
<p style="background-color:tomato">Ejemplo de parrafo.</p>
No necesita el punto y coma.

En cambio, si además queremos poner el color de texto en blanco:
Código: [Seleccionar]
<p style="background-color:tomato color:white">Ejemplo de parrafo.</p>
Esa línea NO va a funcionar, porque estamos alterando dos propiedades sin separarlas con punto y coma, entonces el navegador no sabe donde comienza una indicación y donde termina la otra.

Esa es la función del punto y coma, separar las instrucciones unas de otras:

Código: [Seleccionar]
<p style="background-color:tomato; color:white">Ejemplo de parrafo.</p>

Sobre el espacio en blanco, son irrelevantes, el navegador los ignora. Puedes no ponerlo, poner uno, poner veinte...., no importan.
Va a funcionar igual:
Código: [Seleccionar]
<p style="background-color:                  tomato; color:white">Ejemplo de parrafo.</p>

Lo del espacio en blanco queda a gusto del programador. Poner un espacio en blanco puede ser útil para que sea más legible a simple vista, para que la propiedad que alteramos quede separada del valor que le asignamos.
Habitualmente estaremos usando algún editor de texto que resalte la sintaxis con colores, así que ya resultará legible de por sí.

Pero nunca sabemos si en algún momento vamos a tener que editar un código HTML con un editor más simple, tipo Bloc de Notas.
En ese caso, se agradece un montón si el código HTML utiliza espacios en blanco e indentaciones, que son cosas que al navegador le da igual y las ignora, pero para el ojo humano supone la diferencia entre un elegante texto legible y un horror de instrucciones apelotonadas.

470
No me manejo demasiado con C, y aún menos tratándose de trabajar con ficheros.

Pero diría que en esta opción del switch, no estás leyendo el fihero de texto:

Código: [Seleccionar]
case 'a':

printf("PASSWORD:");scanf("%s",write);
fflush(stdin);

if(strcmp(f.pass_admin,write)==0){
   
printf("acceso permitido");
printf("\nVolver al menu de acceso?(S),pulse cualquier otra letra para salir del programa:");scanf("%c",&exit);
break;

Es decir, si reinicias programa y directamente eliges ACCEDER, no se está leyendo el fichero y por tanto el programa desconoce cuál es el password guardado para poder comparar con el que se introduce por teclado.

471
Comunidad / Re: Presentación :D
« en: 01 de Abril 2021, 11:47 »
Por supuesto que eres bienvenida, ¡aquí todos sois valiosos! Sin vosotros no hay foro.

Espero que puedas aprender cosas nuevas y compartir lo que ya sabes, no dudes en participar en la comunidad.

Un saludo.

472
Citar
while(band==false){
      if(vector[ i]==num){ //Al compilarlo aquí me marca el error
         band = true;
      }
      i++;
   }

Te dará error porque la variable i, en ese punto del programa, ya no existe.

Tú la has declarado previamente en el bucle for

Citar
   for (int i=0;i<tam;i++){
      vector [ i]=rand()%(100-1);
   }

Pero eso implica que su "ámbito" se reduce a lo que ocurre DENTRO de ese bucle for.
Fuera de ese bucle, la variable i no existe.

Entonces, para poder usarla de nuevo, has de declararla nuevamente y mejor si lo haces en el cuerpo del programa principal, para que su "ámbito" abarque todo el código en adelante.
Además de declararla, conviene inicializarla a valor 0, para que la búsqueda comience desde el principio del vector.

Por cierto, durante la búsqueda solo debería incrementarse cuando no se encuentra coincidencia.
Si encuentra coincidencia y también se incrementa, luego no informará correctamente de la posición donde ha encontrado el número que se busca.

Además, el bucle while ha de detenerse en el caso de que ya se haya recorrido TODO el vector, es decir, cuando i sea igual a tam.
No podemos dejarlo solo en manos de la variable "bandera", porque si nos piden buscar un número que no existe, bandera NUNCA será true y el bucle podría resultar infinito.
Citar
   cout<<"\nIngrese el numero que quieres buscar: ";
   cin>>num;
   int i = 0;
   while(band==false && i < tam){
      if(vector[ i]==num){ //Al compilarlo aquí me marca el error
         band = true;
      }
      else
         i++;

   }
   if (band==false){
      cout<<"\nEl numero a buscar no existe en el Vectro";
   }
   else if(band==true){
         cout<<"\nEl numero a sido encontadro en la posicion: "<<i-1;
   }

473
Has de recorrer de nuevo el arreglo de precios.

Puedes hacer dos recorridos, uno para mostrar los BARATOS y otro para mostrar los CAROS

Código: [Seleccionar]
#include <stdio.h>
#include <stdlib.h>

#define total 35
int main( )
{

// VARIABLES: PRODUCTO Y CONTADOR
int producto[total];
int i;

printf("\n\n\n Calcular cuales son los productos mas baratos y cuales son los mas caros\n\n\n\n\n");

for(i=0; i<total; i++)
{
printf("Ingresa el precio del producto %d: $ ",i+1);
scanf("%d", &producto[i]);
}

system("cls");

printf("Productos mas BARATOS\n");
for(i=0; i<total; i++)
{
if (producto[i] < 15)
printf("Producto #%d --> %d$\n", i+1, producto[i]);
}

printf("\n\nProductos mas CAROS\n");
for(i=0; i<total; i++)
{
if (producto[i] > 40)
printf("Producto #%d --> %d$\n", i+1, producto[i]);
}

printf("\n\n");
system("pause");
return 0;
}

474
Esa no es la base para pedir una cadena, es otro programa que hace otra cosa.
Por otra parte, no soy experto en C (yo soy más de Java), pero tengo entendido que usar gets para leer cadenas no es lo ideal.
De hecho muchos compiladores te lo indican como "inseguro", debido a que si el usuario teclea más caracteres que los que caben en el array de char, el programa produce excepción y termina abruptamente.

Es mejor usar fgets que se puede indicarle el límite de caracteres y permite hacer una entrada de datos segura.

Mira, este sería un ejemplo haciendo el ejercicio simplificado que propuse antes, leer una cadena y luego cada dos caracteres cambiarlo por un asterisco.

Código: [Seleccionar]
#include <stdio.h>
#include <stdlib.h>

int main()
{
system("cls");
char cadena[80];

printf("Ingrese una cadena de caracteres: ");
fgets(cadena, 80, stdin);

printf("\nCadena original:\n");
printf(cadena);

for (int i = 0; i < 80; i+=2)
cadena[i] = '*';

printf("\nCadena modificada:\n");
printf(cadena);

printf("\n");
system("pause");
return 0;
}

Si lo ejecutamos, veremos que funciona:
Citar
Ingrese una cadena de caracteres: esto es una cadena

Cadena original:
esto es una cadena

Cadena modificada:
*s*o*e* *n* *a*e*a*
Presione una tecla para continuar . . .

Ahí en ese código podemos ver que en el bucle podemos alterar la cadena, recorriendo las posiciones del array y cambiando los caracteres según deseamos.

Pues bien, trata de pensar cómo cambiar el código de ese bucle para cambiar CADA caracter, por el que se encuentra dos posiciones a su derecha.

Es decir, el caracter en posición
  • , se ha de cambiar por el que está en [2]

El que está en posición [1], por el de posición [3]
El que está en [2] por el que está en [4].

Y así sucesivamente...

Piénsalo, intenta algo, aunque no funcione o sea un desastre.., pero inténtalo.
Si te dan una solución hecha, no adquieres ningún conocimiento.
Pero si estrujas el cerebro y desarrollas alguna idea, aunque no funcione o sea una locura, créeme que sí sacarás algo productivo de todo eso.

475
No soy usuario Linux.

Pero ese primer texto, será un XML de configuración del propio Notepad++ que habrá creado la primera vez que se inicia.
Ignóralo, cierra la pestaña donde se te muestra y ya está. No debería volver a salirte la próxima vez que inicies Notepad++.

Este programa recuerda las pestañas que tenías abiertas en tu última sesión de trabajo y te las muestra cada vez que inicies, a no ser que las cierres antes de terminar la sesión.

476
Prueba a realizar primero una versión simplificada.. no se..., leer la cadena y cada dos caracteres cambiarlo por un asterisco o algo así.

Lo consigas o no, publica aquí tu código y luego intentamos cumplir lo que pide el enunciado.

477
Aprender a programar desde cero / Re: Analisis sintactico
« en: 18 de Marzo 2021, 02:32 »
Hola.

La verdad es que en esta ocasión va a ser un poco más difícil.
Primero, porque esta vez no sabemos el máximo de "partes" que vamos a tener que evaluar.
En el ejercicio anterior si lo sabíamos: dia, hora inicio y hora fin.
Eran tres partes, nos daba igual si el usuario metía una cadena de 500 partes, solo íbamos a preocuparnos de las 3 primeras.
Trabajábamos con partes[0], partes[1] y partes[2]... si habían más, no era asunto nuestro.

Pero esta vez no, si el usuario es un loco que mete 500 partes, vamos a tener que evaluarlas todas.
Así que el programa tiene que funcionar igual si meten 1 sola parte, 3, 15, 500, 80.000,... no hay límite de partes.
Por tanto habrá que usar bucle para recorrer todo el array de partes, mida lo que mida.

Otra cosa, averiguar si una parte es un mes o no, es sencillo.
Comprobar si TODAS las partes son meses, tampoco es problema.
Pero, comprobar si además son meses que están en el orden correcto...., esto ya son palabras mayores.

Vamos a tener que buscar una estrategia distinta. EL método que has puesto para comprobarMes() es correcto, pero vamos a necesitar algo más que eso.

Necesitamos tener algún tipo de lista con todos los meses y que estén ordenados.
Primero había pensado en usar un enum, que rara vez veo la ocasión de usar uno... pero al final he pensado que será más útil y versátil declarar un array con los 12 meses, en su orden correcto.
Código: [Seleccionar]
private static final String[] MESES = {"ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO", "JULIO",
"AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE", "DICIEMBRE"};

Con esto ya podemos ayudarnos, ya no solo para comprobar si una parte es un mes o no, si no también para comprobar si en el caso de tener varias partes, son meses ordenados.

Para comprobar si una parte (un String) es un mes, se podría seguir usando el mismo método que tu habías puesto.
Pero ya que vamos a tener este array a nuestra disposición, se puede simplificar de esta manera:
Código: [Seleccionar]
public static boolean comprobarMes(String mes) {
//Recorremos array de meses y comparamos con el mes recibido
for (String m: MESES)
if (m.equals(mes.toUpperCase())) //Si coincide con alguno de la lista...
return true; //...es que es un mes
//Si el bucle for no ha retornado true, es que no hemos recibido un mes válido
return false;
}

Con esto, ya podemos comprobar si una "parte" es un mes o no.

Pero lo difícil es comprobar si TODAS las "partes" corresponden a una secuencia de meses ordenada

Por ejemplo: febrero enero abril
TODOS son meses, pero no están en orden
En cambio: febrero marzo abril
TODOS son meses, y además SÍ están en orden.

Esto es lo que hay que comprobar.
Para ello he escrito un método, que puede ser un poco lioso, pero en realidad no lo es tanto.

Consta de dos secciones.
El método recibirá el array de "partes" al completo y primero comprobará si TODOS son meses.
Esto es sencillo, se recorre con un bucle y cada "parte" se analiza con comprobarMes().
Si alguno retorna FALSE, es que al menos una "parte" no es un mes, así que ya no hay nada más que comprobar, retornamos FALSE y se acabó.

Pero si todas las partes son TRUE, pues pasamos a la siguiente sección, sabemos que TODOS son meses, pero hay que ver si están en orden.
Esta es la parte que puede ser un poco confusa.

Para lograrlo lo que hago es coger el primer elemento del array partes y averiguar a que posición corresponde en el array de MESES.
Para esto, me apoyo en este otro método:
Código: [Seleccionar]
public static int posicionEnArray(String mes) {
for (int i = 0; i < MESES.length; i++)
if (MESES[i].equals(mes.toUpperCase()))
return i; //Devuelvo posición que ocupa en el array MESES

return -1; //En el improbable caso de que no sea un mes lo que evaluamos
}

Con esto consigo saber a que posición en MESES, equivale el primer mes que tengo en el array partes.
Y luego hago lo mismo con el último mes que tengo en partes.

Supongamos que partes es: marzo abril mayo junio

Tengo que "marzo" (partes[0]) equivale a "MARZO" (meses[2])
Y "junio" (partes[3]) equivale a "JUNIO" (MESES[5])

Tengo localizados el indice 2 como "inicio" y el indice 5 como "fin".
Bien, ahora lo primero que compruebo es que realmente "inicio" es menor que "fin", pues de lo contrario, es evidente que no están ordenados.

Y si "inicio" es menor que "fin", pues ahora lo que hago es recorrer de forma paralela los dos arrays.
El array partes lo recorro al completo desde el principio [ 0 ] hasta el final [3]
Pero MESES, solo recorro el rango entre "inicio" [2] y "fin" [5]

Y voy comparando un mes con otro, si coincide, aumento ambos índices y sigo recorriendo de formar paralela los siguientes meses.
Si alguno no coincide, es que no están ordenados, así que retorno FALSE.
Si llego al final del método sin que se haya retornado FALSE en ningún momento, es que todo está bien y tengo meses ordenados, pues retorno TRUE.

La explicación puede ser liosa, quizás viendo el código de este método se entienda mejor:
Código: [Seleccionar]
public static boolean soloMesesOrdenados(String[] partes) {

//Comprobamos si en las "partes" SOLO hay meses
for (String p: partes)
if (!comprobarMes(p))
return false; //Al menos uno, NO es un mes

/*
* Si el método todavía continua por aquí,
* es que TODOS son meses. Ahora hay que
* comprobar si están en orden.
* Para ello averiguamos que posición del array
* de MESES corresponde a nuestra primera "parte
* y a la última.
* Así sabemos que sección del array MESES hemos
* de buscar que coincida plenamente con
* el array de "partes"
*/
int inicio = posicionEnArray(partes[0]);
int fin = posicionEnArray(partes[partes.length-1]);
/*
* Tenemos el rango, pero antes de comparar
* hay que comprobar que inicio es menor que fin
* de lo contrario, es que no está ordenado
*/
if (inicio < fin) {
//Hay que usar distintos indices para cada array
int indiceMeses = inicio;
int indicePartes = 0;

while(indiceMeses <= fin) {
if (!MESES[indiceMeses].equals(partes[indicePartes].toUpperCase()))
return false; //Si no se cumple una comparación, es que no están en orden
else {
//Incrementamos indices para seguir comparando meses
indiceMeses++;
indicePartes++;
}
}
}
else
return false; //Inicio es mayor o igual a fin, imposible que esté ordenado

//Llegando aquí sin retornar false, es que las "partes" siguen el orden correcto de MESES
return true;
}

Bien, ya tenemos todos los métodos necesarios.
¿Cómo lo hacemos en el main?

Pues recogemos la cadena y separamos en partes con split(" ").

Si obtenemos un array de 0 elementos, indicamos que no se puede analizar la cadena, aunque en realidad esto no va a ocurrir nunca. Escriba lo que escriba el usuario, al menos un elemento siempre vamos a obtener.

Si el array solo tiene 1 elemento, entonces no es necesario comprobar si tenemos una lista ordenada de meses, solo hay que comprobar si ese elemento es un mes.

Si lo es, lo imprimimos en pantalla de color verde, si no, lo imprimimos en rojo.

Pero, si tenemos más de 1 elemento, entonces sí que lo primero es comprobar si tenemos una lista de solo meses bien ordenados.
Si es así, sacamos la cadena completa en color azul.

De lo contrario, pues con bucle, analizamos cada una de las partes del array que nos ha dado el split().
Los que sean meses los imprimimos en verde, lo que no en rojo.

Este es el código completo:
Código: [Seleccionar]
public class Meses {

private static final String[] MESES = {"ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO", "JULIO",
"AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE", "DICIEMBRE"};

public static void main(String[] args) {

Scanner scn = new Scanner(System.in);
String cadena ="";

while (!cadena.equals("salir")){

System.out.println("\n\n\t Ingresa la cadena de texto con el formato indicado");
System.out.println("\t mes (espacio) mes.");
System.out.println("\t Escriba \"salir\" para terminar programa");
System.out.print("\n\t Cadena: ");
cadena = scn.nextLine();

if (!cadena.equals("salir")) {

String[] partes = cadena.split(" ");

if (partes.length == 0)
System.out.println("\nNo se ha recibido una cadena analizable");
else if (partes.length == 1){
//Solo tenemos un supuesto mes
if (comprobarMes(partes[0]))
System.out.print("\033[32m" + partes[0] + "\u001B[0m");
else
System.out.print("\033[31m" + partes[0] + "\u001B[0m");
}
else {
//Tenemos varios supuestos meses
//Hay que comprobar si todos son meses y ordenados, para pintarlos de azul
if (soloMesesOrdenados(partes))
System.out.println("\033[34m" + cadena + "\u001B[0m");
else {
//No estan ordenados, incluso algunas partes quizás no sean meses
//Repasamos una a una para elegir color de salida
for (String parte: partes)
if (comprobarMes(parte))
System.out.print("\033[32m" + parte + " \u001B[0m");
else
System.out.print("\033[31m" + parte + " \u001B[0m");
}
}

}

}

System.out.println("Fin de programa");
scn.close();
}

public static boolean comprobarMes(String mes) {
//Recorremos array de meses y comparamos con el mes recibido
for (String m: MESES)
if (m.equals(mes.toUpperCase())) //Si coincide con alguno de la lista...
return true; //...es que es un mes
//Si el bucle for no ha retornado true, es que no hemos recibido un mes válido
return false;
}

public static int posicionEnArray(String mes) {
for (int i = 0; i < MESES.length; i++)
if (MESES[i].equals(mes.toUpperCase()))
return i; //Devuelvo posición que ocupa en el array MESES

return -1; //En el improbable caso de que no sea un mes lo que evaluamos
}

public static boolean soloMesesOrdenados(String[] partes) {

//Comprobamos si en las "partes" SOLO hay meses
for (String p: partes)
if (!comprobarMes(p))
return false; //Al menos uno, NO es un mes

/*
* Si el método todavía continua por aquí,
* es que TODOS son meses. Ahora hay que
* comprobar si están en orden.
* Para ello averiguamos que posición del array
* de MESES corresponde a nuestra primera "parte
* y a la última.
* Así sabemos que sección del array MESES hemos
* de buscar que coincida plenamente con
* el array de "partes"
*/
int inicio = posicionEnArray(partes[0]);
int fin = posicionEnArray(partes[partes.length-1]);
/*
* Tenemos el rango, pero antes de comparar
* hay que comprobar que inicio es menor que fin
* de lo contrario, es que no está ordenado
*/
if (inicio < fin) {
//Hay que usar distintos indices para cada array
int indiceMeses = inicio;
int indicePartes = 0;

while(indiceMeses <= fin) {
if (!MESES[indiceMeses].equals(partes[indicePartes].toUpperCase()))
return false; //Si no se cumple una comparación, es que no están en orden
else {
//Incrementamos indices para seguir comparando meses
indiceMeses++;
indicePartes++;
}
}
}
else
return false; //Inicio es mayor o igual a fin, imposible que esté ordenado

//Llegando aquí sin retornar false, es que las "partes" siguen el orden correcto de MESES
return true;
}

}

Y esto una prueba de la salida en consola:



Por último, sobre imprimir el texto en colores por consola
La consola de Java es limitada, sin embargo, se puede usar las secuencias de escape del standard ANSI para formatear en colores, tal y como hago en el código.

Esta secuencias funcionan sin problemas en la mayoría de IDE's y en las consolas de Linux y Macintosh (son primos hermanos, descendientes de UNIX)

Pero por ejemplo no funcionan, por defecto, en la consola del IDE Eclipse ni en la consola de Microsoft Windows.

En mi caso, uso Eclipse, y para que me funcione he tenido que instalar un plugin llamado "ANSI escape in console".

Para que funcione en la consola de Windows, en Windows anteriores había que cargar el ANSI.SYS al inicio.
En Windows 10 creo que eso ya no sirve y he leído algo sobre una librería llamada JANSI
Pero no lo he probado, no suelo usar la consola de Windows en Java.


Lo comento por si alguien se encuentra con que no le funciona lo de colorear el texto en consola. Se debe a esto, pero vamos, lo importante es comprender la lógica del programa.
Si luego salen bien o no los colores, es lo de menos.

Un saludo.

478
OK.

Antes de recuperar el valor de un campo de texto, puedes preguntar si contiene algo escrito o no.
Si no tiene nada escrito, ya decides si quieres lanzar un mensaje de advertencia para obligar al usuario a que introduzca un valor, o simplemente ignorar ese campo y no intentar recuperar su contenido.

He escrito un ejemplo rápido y sencillo con 3 campos para recibir valores y sumarlos en un cuarto campo.

La suma funciona aunque falte un valor, o dos, o incluso si faltan todos (resultado entonces será 0)



Lo que hago es que en la acción del botón, declaro unos int inicializados a 0.
A cada uno de estos int, le asignaré el valor de cada campo, pero solo si estos campos tienen algún valor introducido.
Si no lo tienen, no recojo nada y dejo los int con valor 0.

Código: [Seleccionar]
private class AccionSumar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int valor1 = 0, valor2 = 0, valor3 = 0;
//Recuperamos los valores de los campos de texto,
//pero solo NO están vacíos
if (!campo1.getText().isBlank())
valor1 = Integer.parseInt(campo1.getText());
if (!campo2.getText().isBlank())
valor2 = Integer.parseInt(campo2.getText());
if (!campo3.getText().isBlank())
valor3 = Integer.parseInt(campo3.getText());
//Hacemos suma para el campo de resultado
resultado.setText(Integer.toString(valor1 + valor2 + valor3));
}
}


De este modo, al hacer la suma no hay problemas y se realizará falten o no valores.
No se si esto te puede servir.

Dejo el código completo para quien quiera probarlo:

Código: [Seleccionar]
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class SumaCampos extends JFrame{

private JTextField campo1;
private JTextField campo2;
private JTextField campo3;
private JTextField resultado;
private JButton btSumar;

public SumaCampos() {
campo1 = new JTextField(5);
campo2 = new JTextField(5);
campo3 = new JTextField(5);
resultado = new JTextField(5);
resultado.setEditable(false);
resultado.setForeground(Color.BLUE);
btSumar = new JButton("SUMAR");
btSumar.addActionListener(new AccionSumar());

JPanel panelValores = new JPanel();
panelValores.add(new PanelCampo("Valor 1", campo1));
panelValores.add(new JLabel("+"));
panelValores.add(new PanelCampo("Valor 2", campo2));
panelValores.add(new JLabel("+"));
panelValores.add(new PanelCampo("Valor 3", campo3));
panelValores.add(new JLabel("="));
panelValores.add(new PanelCampo("Resultado", resultado));
JPanel panelBoton = new JPanel();
panelBoton.add(btSumar);

setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
add(panelValores);
add(new JSeparator());
add(panelBoton);

setTitle("Sumar campos");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

private class PanelCampo extends JPanel {

public PanelCampo(String texto, JTextField campo) {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JLabel(texto));
add(campo);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10, 5, 10, 5),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class AccionSumar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int valor1 = 0, valor2 = 0, valor3 = 0;
//Recuperamos los valores de los campos de texto,
//pero solo NO están vacíos
if (!campo1.getText().isBlank())
valor1 = Integer.parseInt(campo1.getText());
if (!campo2.getText().isBlank())
valor2 = Integer.parseInt(campo2.getText());
if (!campo3.getText().isBlank())
valor3 = Integer.parseInt(campo3.getText());
//Hacemos suma para el campo de resultado
resultado.setText(Integer.toString(valor1 + valor2 + valor3));
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new SumaCampos();
}
});
}

479
Tendrás que dar más detalles.
De cuál lenguaje se trata (Java, HTML, Visual,...?), aque error te refieres y ya lo ideal sería que compartieses aquí tu código.

Por otro lado, si el error te refieres a intentar hacer una suma cuando hay campos en blanco, pues lo primero es preguntar por código si hay campos vacíos.
¿Cómo se pregunta? Pues ya depende de cada lenguaje, de ahí la importancia de que nos des más información.

480
Para el JFrame principal podemos usar un BorderLayout.
En el centro colocaremos el panel que muestra los asientos.

Debajo, en la parte "sur", estaría el panel "contenedor" que iría alternando entre los paneles de "login" y el de validación de reservas.
Para hacer que alterne entre uno y otro, usaremos el CardLayout.

Luego además, arriba en la parte "norte", podemos incluir un botón de "ayuda" que muestre los datos de los usuarios registrados.
Para probar el programa hay que introducir cédulas de usuarios registrados, para no tener que mirar el código para ver que cédulas se pueden usar, incluimos ese botón para mostrar en pantalla directamente la lista de usuarios registrados y así enseguida vemos que cédulas podemos usar.

Entre los atributos, tenemos un ArrayList con los Usuario de prueba ya registrados.
Los he puesto en un ArrayList, y no en un arreglo tal y como los habíamos creado en la clase Usuario, porque el enunciado pide que cuando un usuario ha hecho reserva, ya no puede hacer más compras. Así que para controlar esto, lo más rápido es eliminar a este usuario de la lista de registrados y así no puede volver a validarse.
Y para eliminar usuarios de una lista, es más fácil con ArrayList.

Otro atributo es una referencia al "usuario activo", es decir, el usuario que ha validado su cédula y se dispone a hacer reservas.
Tenerlo aquí referenciado es muy cómodo para luego enviar sus datos al fichero de texto y también para saber a quien hay que eliminar del ArrayList cuando haya hecho su compra.

Muestro primero los atributos de esta clase y su constructor donde se ve como se maqueta todo esto que he comentado:
Código: [Seleccionar]
public final class Cine extends JFrame{
private ArrayList<Usuario> usuarios;
private Usuario usuarioActivo;
private PanelAsientos asientos;
private PanelLogin pnLogin;
private PanelReservar pnReservar;
private CardLayout grupoPaneles;
private JPanel pnSur;
private JButton btCedulas;

public Cine() {
usuarios = new ArrayList<Usuario>(Arrays.asList(Usuario.fabricaUsuarios()));
asientos = new PanelAsientos();

pnReservar = new PanelReservar();
pnReservar.btReservar.addActionListener(new AccionReservar());
pnReservar.btVolver.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pnReservar.reset();
pnLogin.reset();
grupoPaneles.first(pnSur); //Volvemos a mostrar panel login
}
});

pnLogin = new PanelLogin();
pnLogin.btAcceder.addActionListener(new AccionLogin());
pnSur = new JPanel();
grupoPaneles = new CardLayout();
pnSur.setLayout(grupoPaneles);
pnSur.add(pnLogin, "login");
pnSur.add(pnReservar, "reservar");

JPanel pnNorte = new JPanel();
btCedulas = new JButton("<html><p style=\"text-align: center\">AYUDA<br>Ver cédulas disponibles</p></html>");
btCedulas.setFocusPainted(false);
btCedulas.addActionListener(new AccionVerCedulas());
pnNorte.add(btCedulas);

setLayout(new BorderLayout());
add(pnNorte, BorderLayout.NORTH);
add(asientos, BorderLayout.CENTER);
add(pnSur, BorderLayout.SOUTH);

setTitle("Reservas de Cine");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

Ahora, en esta misma clase, habría que escribir las clases ActionListener que darán funcionalidad a los botones de la interfaz.
Estos ActionListener es donde se va a contener la lógica del programa, como validar un usuarios, como validar reserva, que hacer si nos han pedido asientos que no existen o están reservados, etc...

El primer ActionListener que podemos ver es el correspondiente al botón "ayuda" del panel norte.
Es muy simple, para mostrar los usuarios registrados, recorremos el ArrayList donde tenemos los usuarios y creamos un String con sus datos para mostrarlos en un JOptionPane:

Código: [Seleccionar]
private class AccionVerCedulas implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
StringBuilder mensaje = new StringBuilder();
for (Usuario usu: usuarios)
mensaje.append(usu + "\n");

JOptionPane.showMessageDialog(null, mensaje, "Cédulas para probar programa",
JOptionPane.INFORMATION_MESSAGE);
}
}


El siguiente ActionListener es para validar el usuario.
Lo que hace es pedir al PanelLogin la cédula que ha introducido el usuario.
Comprueba si existe en el ArrayList de Usuarios, si existe, selecciona al Usuario correspondiente como "usuario activo" y pide al CardLayout que muestre el panel para validar reservas.
Si no existe nadie con esa cédula, se informa en pantalla.

Código: [Seleccionar]
private class AccionLogin implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String cedula = pnLogin.getCedula();
boolean encontrado = false;
for (Usuario usu: usuarios) {
if (usu.getCedula().equals(cedula)) {
encontrado = true;
usuarioActivo = usu;
}
}
if (encontrado)
grupoPaneles.show(pnSur, "reservar");
else
JOptionPane.showMessageDialog(null, "No existe usuario con cédula: " + cedula,
"Acceso Usuarios", JOptionPane.WARNING_MESSAGE);
}
}

A continuación, viene el más importante de todos, la acción para validar reservas.
En la lógica a seguir hay que tener en cuenta que hay un máximo de 5 reservas. El usuario puede solicitar todos los asientos que quiera, pero solo se admite 5 reservas.
Y de estas 5 reservas, puede que todas estén disponibles, puede que solo algunas, puede que ninguna....

Lo primero es pedir a PanelReservas que nos devuelva lo que haya tecleado el usuario.
Si el usuario ha cumplido con el formato, habrá escrito algo como: 1A,3B,4C

De esa cadena, hay que extraer los códigos de asientos, y esto lo hacemos con el método split() de la clase String, a quien podemos pedirle que "corte" la cadena donde encuentre una coma y nos devuelva los "trocitos" en un arreglo.
Cada elemento de este arreglo, tendrá el código de asiento elegido.

Así que pasaremos cada uno de estos códigos a la clase PanelAsientos para que comprueben si está disponible.
De la lista de asientos pedidos, como ya hemos dicho, solo procesaremos los 5 primeros (o menos si ha pedido menos de 5) y de estos asientos, iremos guardando en un ArrayList los que la clase PanelAsientos compruebe que sí están disponibles.

Al finalizar esto, si el ArrayList de asientos validados está vacío (isEmpty()) es que ningún asiento de los solicitados está disponible.
En cambio, si hay asientos validados en el ArrayList, pues ya tenemos los necesario para informar al usuario de cuántos asientos puede reservar y cuál será el valor total.

Así que le informamos y pedimos que lo confirme con un JOptionPane.
Si lo confirma, los asientos elegido pasan a estar reservados y cambiarán de color en la interfaz.
El usuario será eliminado de la lista, ya no podrá hacer más compras.
Y el panel sur de la interfaz, volverá a mostrar el PanelLogin para validar una nueva cédula.

Además, tal y como pide el enunciado, se guardará en un archivo de texto los datos de esa transacción.

Código: [Seleccionar]
private class AccionReservar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String peticionReservas = pnReservar.getReservas();
String[] reservas = peticionReservas.split(",");
/*
* Comprobamos si existen los asientos solicitados
* y si están reservados o no. Solo se admiten 5 reservas
* máximo. Si ha solicitado más, serán ignoradas.
*/
int limite = (reservas.length > 5)? 5:reservas.length;
//En este arraylist anotamos los asientos solicitados que podrían reservarse
ArrayList<Asiento> reservasValidas = new ArrayList<Asiento>();
for (int i = 0; i < limite; i++) {
Asiento asiento = asientos.compruebaAsiento(reservas[i]);
if (asiento != null)
reservasValidas.add(asiento);
}
if (reservasValidas.isEmpty())
JOptionPane.showMessageDialog(null, "No hay asientos reservables en su petición.\n"
+ "Indique nombres de asientos que se muestren disponibles con color verde",
"Reservar asientos", JOptionPane.INFORMATION_MESSAGE);
else {
//Calculamos importe total de la reserva y pedimos confirmación
StringBuilder reservados = new StringBuilder();
int importe = 0;
for (Asiento asi: reservasValidas) {
reservados.append("[" + asi.getText() + "] ");
importe += asi.VALOR;
}
String confirmacion = String.format("Asientos a reservar: %s\nImporte total: %d\n"
+ "¿Confirmar reserva?", reservados.toString(), importe);
int respuesta = JOptionPane.showConfirmDialog(null, confirmacion,
"Reservar asientos", JOptionPane.YES_NO_OPTION);

if (respuesta == JOptionPane.YES_OPTION) {
//Reservamos asientos
for (Asiento asi: reservasValidas)
asi.reservar();
//Generamos archivo
crearArchivo(reservados.toString(), importe);
//Este usuario, ya no puede hacer mas reservas, lo sacamos de la lista
usuarios.remove(usuarioActivo);
usuarioActivo = null;
//Volvemos a inicio
pnReservar.reset();
pnLogin.reset();
grupoPaneles.first(pnSur);
}
}
}
}

Lo último que falta, son dos métodos.
Uno es el que se encarga de escribir en archivo de texto los datos de cada transacción.
Y el otro es simplemente el método main() que pone todo el programa en marcha.
Código: [Seleccionar]
private void crearArchivo(String reservados, int importe) {
try {
String fecha = String.format("%d/%d/%d", LocalDate.now().getDayOfMonth(),
LocalDate.now().getMonthValue(), LocalDate.now().getYear());

String hora = String.format("%d:%d", LocalTime.now().getHour(), LocalTime.now().getMinute());

BufferedWriter bw = new BufferedWriter(new FileWriter("reservasCine.txt", true));
bw.write(String.format("Usuario: %s\nAsientos reservados: %s\nImporte: %d\nFecha: %s Hora: %s\n",
usuarioActivo, reservados, importe, fecha, hora));
bw.write("\n\t************************\n");
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Cine();
}
});
}


Si ponemos todo esto en marcha, vemos una sencilla interfaz con los asientos disponibles y algunos marcados en rojo que han sido reservados al azar.



Con el botón superior de "ayuda", podemos ver lista de usuarios para saber que cédulas podemos probar.



Abajo podemos validar cédula, y si tiene éxito, el panel inferior cambia para que podemos hacer reservas.
Aquí me pido reservar toda la fila 1 al completo:



Pero como el límite solo son 5 reservas, me ofrece solo los 5 primeros asientos y el importe total para que lo confirme:



Si acepto, volvemos a la pantalla de login y en pantalla se ve como los 5 primeros asientos de la primera fila, ahora están señalizados en color rojo porque han quedado reservados.



Y la transacción con datos del usuario, asientos, importe, fecha y hora... quedan registrados en un archivo de texto:



Y eso es todo.
Pregunta cualquier cosa que no esté clara o no entiendas.

Adjunto un zip en este mensaje con todo el código fuente.
Saludos.

Páginas: 1 ... 19 20 21 22 23 [24] 25 26 27 28 29 ... 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".