Instalar htop 2.0 desde código fuente

Hace unos pocos días me entere por la cuenta de @nixcraft en twitter que htop 2.0 había sido liberado en el FOSDEM 2016 por Hisham Muhammad su autor original desde 2004.

htop 2.0 vídeo charla multiplataforma

Aparte de que la principal mejora es que es multiplataforma para Linux, FreeBSD, OpenBSD and Mac OS X gracias a las contribuciones que ha tenido en Github. Se han incluido muchas otras mejoras (si tienes disponible ncurses 6) (en CentOs 6.X de base solo se ofrece ncurses 5 ya que fue liberado ncurses 6 en agosto de 2015).

Principales mejoras

htop 2.0 apariencia en ejecución

htop 2.0 apariencia en ejecución

Algunas de las principales mejoras en htop 2.0 son:

  • Soporte de load con gráfica de puntos
  • Mostrar los GB de memoria en lugar de MB
  • Mostrar las variables de entorno de cada proceso presionando ‘e’
  • Código independizado para cada plataforma (más facilidad para futuros desarrollos y plataformas)
  • Enfoque de programación orientada a objetos en el código fuente (OOP).

Instalación desde fuentes

He creado un pequeño script en Github para que puedas instalarlo fácilmente desde mi colección de scripts con el comando:

wget https://raw.githubusercontent.com/shakaran/scripts/master/setup-htop2.sh -O - | bash

O bien con curl:

curl -fsSL https://raw.githubusercontent.com/shakaran/scripts/master/setup-htop2.sh | bash

Instalarlo con el script es…

Como instalar GIT en un servidor CentOS

Git es un software de control de versiones diseñado por Linus Torvalds, pensando en la eficiencia y la confiabilidad del mantenimiento de versiones de aplicaciones cuando estas tienen un gran número archivos de código fuente.

Generalmente es algo que los desarrolladores web deberían usar para proyectos en grupo o creación de código colaborativo. Si en tu hospedaje necesitas tenerlo e instalarlo, es algo sencillo de hacer.

En el momento de publicar este artículo la última versión es 1.7.8.4 1.7.12.1, puede variar cuando tu realices estos pasos, para ver el último código disponible accede a http://kernel.org/pub/software/scm/git/

Para instalarlo en CentOS, concretamente lo he probado en Centos 5.5 6.3, haz lo siguiente:

1 – Primero debes instalar las dependencias con:

# yum install gettext-devel expat-devel curl-devel zlib-devel openssl-devel

2 – Baja el último código disponible con wget:

# wget http://git-core.googlecode.com/files/git-1.7.8.4.tar.gz

3 – Descomprime el código fuente:

# tar xvfz git-*.tar.gz

4 – Muevete a la carpeta descomprimida:

# cd git-*

5 – Compila el código fuente

# make prefix=/usr/local/ all

6 – Instala GIT

# make prefix=/usr/local/ install

7 – Eliminar los archivos generados y descargados

# cd ..; rm -rf git-*

Un granito de libertad cada 15 segundos

Cada 15 segundos, una nueva línea es escrita en el kernel Linux.

Y no lo digo yo, sino el  desarrollador/mantenedor del Kernel Greg Kroah-Hartman:

We add 11,000 lines, remove 5500 lines, and modify 2200 lines every single day.

Haciendo las matemáticas, es una simple regla de tres. Si se escriben 11 mil, pero 5500 son borradas y las modificadas no son nuevas. Nos quedan 5500 y como cada día tiene 24 horas * 60 min * 60 seg = 84600 segundos, pues nos quedan 84600/5500 = 15.38 segundos para escribir una línea. Truncando 15 segundos.

Vía: Entrevista a Greg Kroah-Hartman realizada por How Software is Built

JDBC y HSQLDB: crear bases de datos con Java y el motor de base de datos de OpenOffice

java-jdbc-hsqldb-openoffice

HSQLDB es un sistema de bases de datos relacional SQL escrito en Java, de unos 600 kb usado por aplicaciones como OpenOffice. Dispone de un controlador JDBC y ofrece un pequeño y rápido sistema de bases de datos que gestiona tablas basadas en disco y memoria con un modo servidor y embebido, además de incluir un pequeño servidor web,  herramientas de manejo y de consulta basadas en memoria que pueden correr en forma de aplicaciones.

Instalar HSQLDB

En Ubuntu para usuarlo es necesario instalar el servidor hsqldb:

sudo apt-get install hsqldb-server

A continuación expondré un pequeño ejemplo no muy sofisticado para mostrar un posible uso básico. Presupongo un cierto conocimiento en Java y de bases de datos, asi como del lenguaje SQL.

Explicare unas breves líneas de cada parte del código sin profundizar demasiado, ya que el código esta bastante estructurado y es casi auto-explicativo para alguien que tenga ciertos conocimientos en la materia.

También ciertas partes del código o mensajes están en inglés, esto es así, porque generalmente estoy acostumbrado a hacerlo de tal modo (y para mí es una buena práctica de uso hacerlo), de todas formas no es un inglés demasiado complicado.

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import java.util.Properties;

public class BDprac
{
    static Connection con  = null;
    static Statement  st   = null;  
    static ResultSet  res  = null; 
    static String     sql  = null;
    private static final String DBH = "jdbc:hsqldb:file:src/bd";
    // With memory: "jdbc:hsqldb:mem:bdname"
    
    public static void main(String args[]) throws IOException
    {
        loadHSQLDB();
        connectDB();
        createStatement();
        dropTables();
        createTables();
        restoreDB();
        menu();
        closeHSQLDB();
    }
    
    public static void loadHSQLDB()
    {
        System.out.println("* Starting...");
        try
        {
            Class.forName("org.hsqldb.jdbcDriver"); //Load HSQLDB driver
            System.out.println("* Loading HSQLDB driver...");
        } 
        catch(Exception e)
        {  
            System.err.println("ERROR: failed to load HSQLDB JDBC driver.");
            e.printStackTrace();
            return;  
        } 
    }
    
    public static void connectDB()
    {
        try
        {   // Connect to the database or create if it don't exist 
            con = DriverManager.getConnection(DBH); 
            System.out.println("* Creating HSQLDB connection...");
        }
        catch(Exception e)
        {
            System.err.println("Error: " + e.getMessage());
            return;
        }
    }
    
    public static void createStatement()
    {
        try
        {
            st  = con.createStatement(); 
        }
        catch (Exception e)
        {  
            System.err.println("Error: createStatement: " + e.getMessage());   
            return;
        }
    }
    
    public static void dropTables()
    {
        try 
        {   // Drop tables
            st.executeUpdate("DROP TABLE IF EXISTS stusub;DROP TABLE IF EXISTS student;DROP TABLE IF EXISTS subject;");
            System.out.println("* Drop table if exists...");
        }
        catch (Exception e)
        {  
            System.err.println("Warning: drop table: " + e.getMessage());   
        }  
    }
    
    public static void createTables()
    {
        try 
        {   // Create tables
            sql = "CREATE TABLE student ( " +
                                            "id         INTEGER NOT NULL PRIMARY KEY, " +
                                            "name       VARCHAR(25) NOT NULL, " +
                                            "lastname   VARCHAR(100), " +
                                            "address    VARCHAR(100), " +
                                            "city       VARCHAR(100), " +
                                            "pcode      VARCHAR(5), " +
                                            "email      VARCHAR(80), " +
                                            "mobile     VARCHAR(50), " +
                                            "subject VARCHAR(40)," +
                                            "CONSTRAINT UNIQUE_STU UNIQUE(name)" +
                                         ");";  
            st.executeUpdate(sql);  
            System.out.println("* Creating student table...");
            
            sql = "CREATE TABLE subject ( " +
                                            "id         INTEGER NOT NULL PRIMARY KEY, " +
                                            "name       VARCHAR(100) NOT NULL, " +
                                            "CONSTRAINT UNIQUE_SUB UNIQUE(name)" +
                                         ");";  
            st.executeUpdate(sql);  
            System.out.println("* Creating subject table...");
            
            sql = "CREATE TABLE stusub ( " +
                                            "id             INTEGER NOT NULL PRIMARY KEY, " +
                                            "subject        INTEGER NOT NULL, " +
                                            "student       INTEGER NOT NULL, " +
                                            "FOREIGN KEY (student) REFERENCES student(id), " +
                                            "FOREIGN KEY (subject) REFERENCES subject(id), " +
                                            "CONSTRAINT UNIQUE_STUSUB UNIQUE(subject, student)" +
                                         ");";  
            st.executeUpdate(sql);  
            System.out.println("* Creating student-subject table...");
        } 
        catch (Exception e)
        {  
            System.err.println("Warning: CREATE TABLE: " + e.getMessage());   
        }
    }
    
    public static void restoreDB()
    {
        try 
        {   // Restore the database  
            st.executeUpdate("DELETE FROM stusub;DELETE FROM student;DELETE FROM subject;");
            System.out.println("* Restore the original databases, removing all previous inserting data.");
        }
        catch (Exception e)
        {  
            System.err.println("Warning: error on vacuum tables: " + e.getMessage());   
        } 
    }
    
    public static void menu()
    {
        boolean exit = false;
        boolean insert = false;
        int option;
        
        while(!exit)
        {
            System.out.println("\t.: Menu :.\n" +
                               "\t0 - Salir\n" +
                               "\t1 - Insertar alumnos y asignaturas por defecto.\n" +
                               "\t2 - Modificar el nombre de una asignatura (0 - Literatura).\n" +
                               "\t3 - Consultar alumnos por apellido.\n" +
                               "\t4 - Listar todos los alumnos.\n" +
                               "\t5 - Listar todas las asignaturas.\n"
                               );  
            
            try
            {        
                System.out.print("Introduzca una opción numérica:");
                option = Integer.parseInt(read());                   
            }
            catch(NumberFormatException ex){
                System.out.println("La opción no es un número.");
                option = -1;
            }

            switch(option)
            {
                case 0:
                    exit = true;
                break;
                case 1:
                    if(!insert)
                    {
                        insertData();
                        insert = true;
                        System.out.println("Datos correctamente insertados.\n");
                    }
                    else System.out.println("Datos ya insertados previamente.\n");
                break;
                case 2:
                    if(!insert)
                    {
                        System.out.println("Deben insertarse datos previamente.");
                    }
                    else
                    {
                        System.out.print("Introduzca el nuevo nombre para la asignatura 'Literatura':");
                        updateSubject(read());
                    }
                break;
                case 3:
                    if(!insert)
                    {
                        System.out.println("Deben insertarse datos previamente.");
                    }
                    else
                    {
                        System.out.print("Introduzca el apellido a consultar:");
                        showSubjectByLastName(read());
                    }
                break;
                case 4:
                    if(!insert)
                    {
                        System.out.println("Deben insertarse datos previamente.");
                    }
                    else
                    {
                        showStudents(); 
                    }
                break;
                case 5:
                    if(!insert)
                    {
                        System.out.println("Deben insertarse datos previamente.");
                    }
                    else
                    {
                        showSubjects();
                    }
                break;
                default:
                    System.out.println("Opcion incorrecta.\n");
                break;
            }
        }
    }
    
    public static void closeHSQLDB()
    {
        // Save temporal data and close
        try
        {
            st = con.createStatement();  
            st.executeUpdate("SHUTDOWN");  
            st.close(); 
        }
        catch(Exception e)
        {
            System.out.println("Error: save temporal data" + e.getMessage());
        }
        
        try
        {
            con.close();
        }
        catch(Exception e)
        {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
            return; 
        }
    }
    
    public static String read()
    {
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            return br.readLine();
        }
        catch(Exception e)
        { 
            System.out.println("Error en la lectura de datos:\n");
            e.printStackTrace();
            return "";
        }
    }
    
    public static void insertData()
    {
        // Insert data  
        try 
        { 
            //Insert subject
            st.executeUpdate("INSERT INTO subject VALUES ('0', 'Literatura')");  
            st.executeUpdate("INSERT INTO subject VALUES ('1', 'Ciencia')");  
            st.executeUpdate("INSERT INTO subject VALUES ('2', 'Redes')");  
        
            //Insert student
            st.executeUpdate("INSERT INTO student VALUES ('0', 'Juan', 'Garrido', 'Sol, 12', 'Sevilla', '13206', [email protected]', '609555321', '0')");  
            st.executeUpdate("INSERT INTO student VALUES ('1', 'Luis', 'Garrido', 'Flor, 5', 'Melilla', '43712', [email protected]', '615827343', '0')");  
            st.executeUpdate("INSERT INTO student VALUES ('2', 'Teresa', 'Garcia', 'Mata, 18', 'Madrid', '28045', [email protected]', '678123687', '1')");  
            
            //Foreign keys stusub
            st.executeUpdate("INSERT INTO stusub VALUES ('0', '0', '0')");  
            st.executeUpdate("INSERT INTO stusub VALUES ('1', '0', '1')");  
            st.executeUpdate("INSERT INTO stusub VALUES ('2', '1', '2')");  
        }
        catch (Exception e)
        {  
            System.err.println("Warning: error on insert data: " + e.getMessage());   
            e.printStackTrace();
            return; 
        } 
    }
    
    public static void showStudents()
    {
        try 
        { 
            // Mostramos por pantalla todos los alumnos de la tabla  
            res = st.executeQuery("SELECT * FROM student INNER JOIN subject ON student.subject = subject.id");  
            System.out.println("ID\tNombre\tApellido Direccion\tCiudad\tCodigo Postal\t\tEmail\t\tMovil\t\tAsignatura\n" + 
                               "-------------------------------------------------------------------------------------------" + 
                               "--------------------------");  
            while (res.next())
            {  
                System.out.println(res.getInt("id") + "\t" + 
                                   res.getString("name") + "\t" + 
                                   res.getString("lastname") + "\t " + 
                                   res.getString("address") + "\t" + 
                                   res.getString("city") + "\t" + 
                                   res.getString("pcode") + "\t\t" + 
                                   res.getString("email") + "\t" + 
                                   res.getString("mobile") + "\t" + 
                                   res.getString("subject"));
            }
            
            // Free memory
            res.close(); 
        }
        catch (Exception e)
        {  
            System.err.println("Warning: SELECT JOIN student: " + e.getMessage());   
        }
    }
    
    public static void showSubjectByLastName(String lastname)
    {
        try 
        { 
            // Mostramos por pantalla todos los alumnos de la tabla  
            res = st.executeQuery("SELECT * FROM student WHERE lastname = '" + lastname + "'");  
            System.out.println("ID\tNombre\tApellido Direccion\tCiudad\tCodigo Postal\t\tEmail\t\tMovil\t\tAsignatura\n" + 
                               "-------------------------------------------------------------------------------------------" + 
                               "--------------------------");  
            while (res.next())
            {  
                System.out.println(res.getInt("id") + "\t" + 
                                   res.getString("name") + "\t" + 
                                   res.getString("lastname") + "\t " + 
                                   res.getString("address") + "\t" + 
                                   res.getString("city") + "\t" + 
                                   res.getString("pcode") + "\t\t" + 
                                   res.getString("email") + "\t" + 
                                   res.getString("mobile") + "\t" + 
                                   res.getString("subject"));
            }
            
            // Free memory
            res.close(); 
        }
        catch (Exception e)
        {  
            System.err.println("Warning: SELECT lastname student: " + e.getMessage());   
        }
    }
    
    public static void showSubjects()
    {
        try 
        { 
            // Mostramos por pantalla todos las asignaturas de la tabla  
            res = st.executeQuery("SELECT * FROM subject");  
            System.out.println("ID\tNombre\n" + 
                               "--------------------");  
            while (res.next())
            {  
                System.out.println(res.getInt("id") + "\t" + 
                                   res.getString("name")
                                   );
            }
            
            // Free memory
            res.close(); 
        }
        catch (Exception e)
        {  
            System.err.println("Warning: SELECT subject: " + e.getMessage());   
        }
    }
    
    public static void updateSubject(String data)
    {
        // Make a update
        try 
        { 
            st.executeUpdate("UPDATE subject SET name='" + data + "' WHERE id=0");  
        }
        catch (Exception e)
        {  
            System.err.println("Warning: UPDATE subject: " + e.getMessage());   
        } 
    }
}

De la linea 1 a 7 se cargan los archivos necesarios para el funcionamiento del programa.

La linea 9 crea la clase BDprac. En ella tenemos unas variables globales a la clase desde la línea 11 a 14, que serán utilizadas para las posteriores consultas y resultados.

La línea 15 es interesante porque especifica el DBH (Data-Base-Host), es decir, el enlace o ruta hasta nuestra base de datos. En nuestro caso sera un archivo local, y primero invocaremos al controlador jdbc, seguido de hsqldb e indicaremos que es un archivo en la ruta src/ y con el nombre bd. Tambien es posible crear la base de datos en memoria como esta comentado en la linea 16.

En las líneas 18-28 tenemos el main, donde se han encapsulado en una serie de métodos todo el funcionamiento del programa (por resultar más didáctico).

Los métodos estan dispuestos en orden en el codigo asi que paso a comentarlos brevemente.

loadHSQLDB() de la línea 30 a 44, se encarga de inicializar o cargar el controlador JDBC y mostrar un mensaje en caso de fallo.

connectDB() de la línea 46 a 58, se encarga de conectar el controlador HSQLDB a nuestro DBH en la base de datos.

createStatement() de la línea 60 a 71, prepara una consulta a la base de datos.

dropTables() de la línea 73 a 84, hace una limpieza inicial (borra si existen) de las tablas que hayan podido usarse en ejecuciones anteriores del programa (para evitar conflictos con antiguas insercciones).

createTables() de la línea 86 a 128, crea tres tablas, alumnos, asignaturas y la tabla de referencias ajenas alumnos-asignatura.

restoreDB() de la línea 130 a 141 borra los posibles datos que existieran en las tablas anteriores.

menu() de la línea 143 a 231, contiene el uso del programa, la lectura de opciones y filtrado de acciones segun el parámetro elegido.

closeHSQLDB() de la línea 233 a 257, se encarga de cerrar la conexión HSQLDB y finalizar las consultas abiertas. Es ejecutada al finalizar el programa.

read() de la línea 259 a 272, es un método encargado de la lectura de datos de entrada.

insertData() de la línea 274 a 300, inserta los datos iniciales en la tablas del programa a modo de ejemplo.

showStudents() de la línea 302 a 331, muestra todos los alumnos disponibles en la tabla students.

showSubjectByLastName() de la línea 333 a 362, muestra los alumnos que coincidan en apellido con el filtro de apellido recibido por parámetro lastname.

showSubjects() de la línea 364 a 386, lista todas las asignaturas disponibles en la tabla subjects.

updateSubject() de la línea 388 a 399, actualiza el nombre de la asignatura 0 (Literatura) al nombre recibido por parámetro data.

Para que la compilación y la ejecución resulte más sencilla, he preparado un archivo Makefile, que establecerá la ruta de HSQLDB y de nuestro directorio de trabajo (y ademas con clean, tiene una opción de borrado de archivos generados):

JAVA_PATH = src/:/usr/share/java/hsqldb.jar:.
BOLD = \033[1m
END  = \033[0m

all:
    @echo "$(BOLD)>>> Compilando archivos Java... < <<$(END)" javac src/BDprac.java @echo "\n$(BOLD)>>> Ejecutando archivos Java... < <<$(END)"
    java -classpath $(JAVA_PATH) BDprac

clean:
   $(RM) src/*.class src/*~ src/*.script src/*.properties

Ejemplos de uso

El programa carga el controlador y realiza una conexión HSQLDB a un archivo de base de datos creado en tiempo de ejecución (también se puede crear un archivo en memoria, ver línea 16 comentada en el código). Se crean las tablas iniciales (alumno y asignaturas) y una tabla para las claves ajenas. También se procede al borrado y vaciado de datos, por si la aplicación ha sido iniciada anteriormente (a modo de limpieza).

Posteriormente aparecerá un menú con algunas opciones básicas. Si pretendemos hacer alguna operación sin insertar datos previamente, se nos mostrará un mensaje (por ejemplo metiendo la opción 3 al inicio).

Después de insertar los datos, podemos hacer una consulta de todos los alumnos, eligiendo la opción 4.

Si deseamos cambiar el nombre de una asignatura (para el ejemplo siempre la 0, de Literatura), elegiremos la opción 2, e introduciremos el nuevo nombre (en este caso Arte). Y con la opción 5 podremos listar las asignaturas antes y después del cambio.

Con la opción 3, podemos consultar los alumnos por nombre de apellido, por ejemplo, introduciendo “Garrido” se listan los alumnos con apellido Garrido. Y con 0 finalizaremos la ejecución del programa.

Ejemplo de una traza de ejecución

$ make
>>> Compilando archivos Java... < << javac src/BDprac.java >>> Ejecutando archivos Java... < <<
java -classpath src/:/usr/share/java/hsqldb.jar:. BDprac
* Starting...
* Loading HSQLDB driver...
* Creating HSQLDB connection...
* Drop table if exists...
* Creating student table...
* Creating subject table...
* Creating student-subject table...
* Restore the original databases, removing all previous inserting data.
  .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:3
Deben insertarse datos previamente.
    .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:1
Datos correctamente insertados.

    .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:4
ID Nombre  Apellido Direccion  Ciudad  Codigo Postal       Email       Movil       Asignatura
---------------------------------------------------------------------------------------------------------------------
0    Juan    Garrido  Sol, 12    Sevilla 13206       [email protected] 609555321   0
1  Luis    Garrido  Flor, 5    Melilla 43712       [email protected] 615827343   0
2  Teresa  Garcia   Mata, 18   Madrid  28045       [email protected]   678123687   1
   .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:
La opción no es un número.
Opcion incorrecta.

    .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:5
ID Nombre
--------------------
0 Literatura
1 Ciencia
2    Redes
   .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:2
Introduzca el nuevo nombre para la asignatura 'Literatura':Arte
  .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:5
ID Nombre
--------------------
0 Arte
1   Ciencia
2    Redes
   .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:3
Introduzca el apellido a consultar:Garrido
ID   Nombre  Apellido Direccion  Ciudad  Codigo Postal       Email       Movil       Asignatura
---------------------------------------------------------------------------------------------------------------------
0    Juan    Garrido  Sol, 12    Sevilla 13206       [email protected] 609555321   0
1  Luis    Garrido  Flor, 5    Melilla 43712       [email protected] 615827343   0
   .: Menu :.
  0 - Salir
   1 - Insertar alumnos y asignaturas por defecto.
 2 - Modificar el nombre de una asignatura (0 - Literatura).
 3 - Consultar alumnos por apellido.
 4 - Listar todos los alumnos.
   5 - Listar todas las asignaturas.

Introduzca una opción numérica:0

Si lo deseas, puedes descargar el ejemplo completo en un archivo empaquetado y comprimido con Gzip en formato tar.gz:

Descargar: [download id=”7″]

Nota: todos los datos de alumnos de este artículo son ficticios.