Procesar tabla de socios

Una vez más, añadiremos los identificadores para las nuevas opciones de menú en "menus.h":

#define NUEVOSOCIO          26
#define EDITARSOCIO         27
#define BORRARSOCIO         28
#define CONSULTASOCIO       29

También añadiremos las nuevas opciones de menú para los socios en "menus.cpp", y borraremos la tabla de menú usando la sentencia "DROP TABLE menu;" desde la consola de SQLite:

    {4, "-", "---MENU SOCIOS---",0,TITULO},
    {4, "1", "Nuevo", 0, NUEVOSOCIO},
    {4, "2", "Editar", 0, EDITARSOCIO},
    {4, "3", "Borrar", 0, BORRARSOCIO},
    {4, "4", "Consultar", 0, CONSULTASOCIO},
    {4, "0", "Salir <", 1, ABRIRMENU},

Volvemos a modificar el fichero "main.cpp", para añadir el fichero incluído "socio.h" y el proceso de las nuevas opciones de menú:

#include "socio.h"
...
            case NUEVOSOCIO:
               NuevoSocio(db);
               break;
            case EDITARSOCIO:
               EditarSocio(db);
               break;
            case BORRARSOCIO:
               BorrarSocio(db);
               break;
            case CONSULTASOCIO:
               BuscarSocio(db);
               break;

Finalmente, añadiremos dos ficheros más al proyecto, uno con los prototipos de funciones y otro con la implementación para el tratamiento de la tabla de socios:

/*
 * Aplicación de ejemplo de uso de SQLite en C++
 * EjemploSQLite
 * Salvador Pozo, Con Clase (www.conclase.net)
 * Abril de 2012
 * Fichero: socio.h
 * fichero de cabecera para manupular datos de socios
 */

#ifndef __SOCIO_H__
#define __SOCIO_H__

#include <sqlite/sqlite3.h>

void NuevoSocio(sqlite3 *);
int ListaSocios(sqlite3 *);
void EditarSocio(sqlite3 *);
void BorrarSocio(sqlite3 *);
void BuscarSocio(sqlite3 *);
#endif
/*
 * Aplicación de ejemplo de uso de SQLite en C++
 * EjemploSQLite
 * Salvador Pozo, Con Clase (www.conclase.net)
 * Abril de 2012
 * Fichero: socio.cpp
 * fichero de implementación para manipular datos de socios
 */

#include <iostream>
#include <iomanip>
#include "socio.h"

using namespace std;

void NuevoSocio(sqlite3 *db) {
    char nombre[64];
    char direccion[128];
    char telefono[32];
    char categoria[2];
    sqlite3_stmt *ppStmt;
    int rc;
    char consulta[1024];
    bool existe, ignorar=false;
    char nombre2[64];
    int clave;
    char resp[2];

    for(int i= 0; i < 24; i++) cout << endl;
    cout << "A continuacion se pedira el nombre, direccion, telefono y cateforia del socio." << endl;

    cin.ignore();
    cout << "Nombre: ";
    cin.getline(nombre, 64);
    cout << "Direccion: ";
    cin.getline(direccion, 128);
    cout << "Telefono: ";
    cin.getline(telefono, 32);
    cout << "Categoria (A-F): ";
    cin.getline(categoria, 2);

    // Verificar si el nombre existe ya:
    sprintf(consulta, "SELECT clavesocio,socio FROM socio WHERE socio LIKE '%s';", nombre);
    rc = sqlite3_prepare_v2(db, consulta, -1, &ppStmt, NULL);
    existe=false;
    if( rc!=SQLITE_OK ){
        cout << "Error: " << sqlite3_errmsg(db) << endl;
    } else {
        if(SQLITE_ROW == sqlite3_step(ppStmt)) {
            existe = true;
            clave = sqlite3_column_int(ppStmt, 0);
            strncpy(nombre2, (const char*)sqlite3_column_text(ppStmt, 1), 64);
            nombre2[63]=0;
        }
        sqlite3_finalize(ppStmt);
    }

    if(!existe) {
        sprintf(consulta, "INSERT INTO socio(socio,direccion,telefono,categoria) VALUES('%s','%s','%s','%c');",
                nombre, direccion, telefono, categoria[0]);
    } else {
        cout << "Ya existe un socio con el nombre " << nombre2 << " (s)obrescribir, insert(a)r o (i)gnorar: " << endl;
        cin >> resp;
        switch(resp[0]) {
            case 's':
                sprintf(consulta, "UPDATE socio SET autor='%s',direccion='%s',telefono='%s',categoria='%c' WHERE claveautor=%d;",
                        nombre, direccion, telefono, categoria[0], clave);
                break;
            case 'a':
                sprintf(consulta, "INSERT INTO socio(socio,direccion,telefono,categoria) VALUES('%s','%s','%s','%c');",
                        nombre, direccion, telefono, categoria[0]);
                break;
            case 'i':
            default:
                ignorar=true;
        }
    }
    if(!ignorar) {
        if(SQLITE_OK != sqlite3_exec(db, consulta, 0, 0, 0)) {
            cout << "Error: " << sqlite3_errmsg(db) << endl;
        }
        else cout << "Socio insertado" << endl;
    }
    cin.ignore();
}

int ListaSocios(sqlite3 *db) {
    sqlite3_stmt *ppStmt;
    int rc;
    char consulta[1024];
    int desplazamiento=0;
    char resp[10];
    bool salir=false;
    bool ultima;
    int fila=0;
    int i;

    // Mostrar una lista, teniendo en cuenta que puede haber más de las que caben en una pantalla.
    do {
        cout << "Elegir socio" << endl << endl;
        sprintf(consulta, "SELECT clavesocio,socio FROM socio ORDER BY socio LIMIT 20 OFFSET %d;", desplazamiento);
        rc = sqlite3_prepare_v2(db, consulta, -1, &ppStmt, NULL);
        if( rc!=SQLITE_OK ){
            cout << "Error: " << sqlite3_errmsg(db) << endl;
        } else {
            i = 0;
            while(SQLITE_ROW == sqlite3_step(ppStmt)) {
                cout << sqlite3_column_int(ppStmt, 0) << ") " <<
                    sqlite3_column_text(ppStmt, 1) << endl;
                i++;
            }
            sqlite3_finalize(ppStmt);
        }
        ultima = (i < 20);
        while(i < 20) { cout << endl; i++; }
        cout << "\n" << "(n) editar, (s)ig pagina, (a)nt pagina, (x)salir" << endl;
        cin >> resp;
        switch(resp[0]) {
            case 's':
                if(!ultima) desplazamiento+=20;
                break;
            case 'a':
                if(desplazamiento > 0) desplazamiento-=20;
                break;
            case 'x':
                salir=true;
                break;
            default:
                if(isdigit(resp[0])) {
                    fila = atoi(resp);
                    salir=true;
                }
                break;
        }
    } while(!salir);

    return fila;
}

void EditarSocio(sqlite3 *db) {
    sqlite3_stmt *ppStmt;
    int rc;
    char consulta[1024];
    char nombre[64];
    char direccion[128];
    char telefono[32];
    char categoria[2];
    int i;
    int fila;
    bool salir=true;

    fila = ListaSocios(db);

    // Editar:
    for(i = 0; i < 22; i++) cout << endl;
    sprintf(consulta, "SELECT socio,direccion,telefono,categoria FROM socio WHERE clavesocio='%d';", fila);
    rc = sqlite3_prepare_v2(db, consulta, -1, &ppStmt, NULL);
    if( rc!=SQLITE_OK ){
        cout << "Error: " << sqlite3_errmsg(db) << endl;
    } else {
        i = 0;
        if(SQLITE_ROW == sqlite3_step(ppStmt)) {
            cout << "Nombre:    " << sqlite3_column_text(ppStmt, 0) << endl;
            cout << "Direccion: " << sqlite3_column_text(ppStmt, 1) << endl;
            cout << "Telefono:  " << sqlite3_column_text(ppStmt, 2) << endl;
            cout << "Categoria: " << sqlite3_column_text(ppStmt, 3) << endl;
            cout << "Dejar en blanco los campos que no se quieren modifiar" << endl;
            salir=false;
        }
        sqlite3_finalize(ppStmt);
    }
    if(!salir){
        cin.ignore();
        cout << "Nombre: ";
        cin.getline(nombre, 64);
        cout << "Direccion: ";
        cin.getline(direccion, 128);
        cout << "Telefono: ";
        cin.getline(telefono, 32);
        cout << "Categoria: ";
        cin.getline(categoria, 2);
        if(strlen(nombre)>0) {
            sprintf(consulta, "UPDATE socio SET socio='%s' WHERE clavesocio=%d;", nombre, fila);
            if(SQLITE_OK != sqlite3_exec(db, consulta, 0, 0, 0)) {
                cout << "Error: " << sqlite3_errmsg(db) << endl;
            }
        }
        if(strlen(direccion)>0) {
            sprintf(consulta, "UPDATE socio SET direccion='%s' WHERE clavesocio=%d;", direccion, fila);
            if(SQLITE_OK != sqlite3_exec(db, consulta, 0, 0, 0)) {
                cout << "Error: " << sqlite3_errmsg(db) << endl;
            }
        }
        if(strlen(telefono)>0) {
            sprintf(consulta, "UPDATE socio SET telefono='%s' WHERE clavesocio=%d;", telefono, fila);
            if(SQLITE_OK != sqlite3_exec(db, consulta, 0, 0, 0)) {
                cout << "Error: " << sqlite3_errmsg(db) << endl;
            }
        }
        if(strlen(categoria)>0) {
            sprintf(consulta, "UPDATE socio SET categoria='%c' WHERE clavesocio=%d;", categoria[0], fila);
            if(SQLITE_OK != sqlite3_exec(db, consulta, 0, 0, 0)) {
                cout << "Error: " << sqlite3_errmsg(db) << endl;
            }
        }
        cout << "Socio modificado" << endl;
        cin.ignore();
    }
}

void BorrarSocio(sqlite3 *db) {
    sqlite3_stmt *ppStmt;
    int rc;
    char consulta[1024];
    int fila;
    char resp[2];
    int i;
    bool salir=true;

    fila = ListaSocios(db);
    cout << "Borrar: " << fila << endl;

    for(i = 0; i < 22; i++) cout << endl;
    sprintf(consulta, "SELECT socio,direccion,telefono,categoria FROM socio WHERE clavesocio='%d';", fila);
    rc = sqlite3_prepare_v2(db, consulta, -1, &ppStmt, NULL);
    if( rc!=SQLITE_OK ){
        cout << "Error: " << sqlite3_errmsg(db) << endl;
    } else {
        i = 0;
        if(SQLITE_ROW == sqlite3_step(ppStmt)) {
            cout << "Nombre:    " << sqlite3_column_text(ppStmt, 0) << endl;
            cout << "Direccion: " << sqlite3_column_text(ppStmt, 1) << endl;
            cout << "Telefono:  " << sqlite3_column_text(ppStmt, 2) << endl;
            cout << "Categoria: " << sqlite3_column_text(ppStmt, 3) << endl;
            salir=false;
        }
        sqlite3_finalize(ppStmt);
    }
    if(!salir){
        cin.ignore();
        cout << "Borrar este registro? (s/n)" << endl;
        cin >> resp;
        if(resp[0] == 's' || resp[0] == 'S') {
            sprintf(consulta, "DELETE FROM socio WHERE clavesocio=%d;", fila);
            if(SQLITE_OK != sqlite3_exec(db, consulta, 0, 0, 0)) {
                cout << "Error: " << sqlite3_errmsg(db) << endl;
            }
        }
    }
    cout << "Socio borrado" << endl;
    cin.ignore();
}

void BuscarSocio(sqlite3 *db) {
    sqlite3_stmt *ppStmt;
    int rc;
    char consulta[1024];
    char nombre[64];
    char direccion[128];
    char telefono[32];
    char categoria[2];
    int i;

    for(i = 0; i < 22; i++) cout << endl;
    // Búsqueda de Socios por nombre, direccion, telefono o categoria:
    cout << "Introducir cadenas de busqueda, _ para comodin de caracter, % para comodin de cadena" << endl;
    cout << "Dejar en blanco para ignorar el campo en la busqueda" << endl;
    cin.ignore();
    cout << "Nombre: ";
    cin.getline(nombre, 64);
    cout << "Direccion: ";
    cin.getline(direccion, 128);
    cout << "Telefono: ";
    cin.getline(telefono, 32);
    cout << "Categoria: ";
    cin.getline(categoria, 2);

    if(strlen(nombre) == 0) strcpy(nombre, "%");
    if(strlen(direccion) == 0) strcpy(direccion, "%");
    if(strlen(telefono) == 0) strcpy(telefono, "%");
    if(strlen(categoria) == 0) strcpy(categoria, "%");
    sprintf(consulta, "SELECT socio,direccion,telefono,categoria FROM socio "
            "WHERE socio LIKE '%s' AND direccion LIKE '%s' AND telefono LIKE '%s' AND categoria LIKE '%c';",
            nombre, direccion, telefono, categoria[0]);
    rc = sqlite3_prepare_v2(db, consulta, -1, &ppStmt, NULL);
    if( rc!=SQLITE_OK ){
        cout << "Error: " << sqlite3_errmsg(db) << endl;
    } else {
        i = 0;
        while(SQLITE_ROW == sqlite3_step(ppStmt)) {
            cout.setf(ios::left);
            cout.width(64);
            cout << sqlite3_column_text(ppStmt, 0) << endl;
            cout.width(128);
            cout << sqlite3_column_text(ppStmt, 1) << endl;
            cout.width(32);
            cout << sqlite3_column_text(ppStmt, 2) << " ";
            cout.width(32);
            cout << "Cat: " << sqlite3_column_text(ppStmt, 3) << endl;
            i += 3;
            if((i >= 22)) {
                cout << "Pulsa return";
                cin.ignore();
                cin.get();
            }
        }
        sqlite3_finalize(ppStmt);
    }
    cin.ignore();
    cin.get();
}