Newsgroup: it.comp.lang.c
Titolo: Database in C

Ciao a tutti,
credo di non essere OT se chiedo notizie sull'implementazione di database,
dato che quello che mi interessa e'appunto il modo piu' corretto di
implementarne uno in C. Mi capita spesso infatti di fare confusione con
l'acquisizione di dati da file e con il parsing delle stringhe.
Devo implementare la gestione di un semplice database, semplice nel senso
che dovendo gestire pochi dati immagino di potermi affidare ad un normale
file di testo senza ricorrere a standard.
Ad esempio:
record1.dato1
record1.dato2
record1.dato3
record2.dato1
record2.dato2
record2.dato3
....
Il fatto e' che questo file dovrebbe essere utilizzato (prevalentemente in
lettura)
da piu'di un programmino, e a ciascuno di questi interessa una sola parte
dei dati. Per come ho impostato la struttura, il file me lo devo scorrere
sequenzialmente tutto, leggendolo, per accedere ai dati di volta in volta
significativi.
La domanda (finalmente!) e' questa:
mi suggerite un modo intelligente e meno becero di maneggiare un file di
dati?
grazie anticipatamente
Ivan

dati?
Usa un ambiente di programmazione come il Borland C++ Builder e basa
la gestione dei dati su componenti che interfaccino il BDE (Borland
Database Engine). Ormai la gestione dei database e' integrata in ogni
ambiente di sviluppo. A questo punto, indirizza le tue future domande
su it.comp.programmare.win32.
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
---------------------------------------------

Il mio dubbio era di livello un po' piu' basso (sia qualitativamente che in
termini di programmazione).
Ricordo che proprio tu avevi postato tempo fa il codice di una rubrichetta.
Siccome non l'ho piu' e
vorrei prenderlo ad esempio, potresti postarlo?
Ciao e Grazie

 dati?
Immagino che tu debba affiancare un indice ad albero al file di dati ed
utilizzare quindi fseek() per spostarti rapidamente nel punto del file
che ti interessa leggere.
EMG

Grazie.
Posso pero' chiederti un esempio (ammesso che sia possibile in breve)?
Quello che cerco e' la logica, anche in pseudo-codice.
Ciao e grazie ancora


 Quello che cerco e' la logica, anche in pseudo-codice.
Non è una cosa semplicissima, specialmente la gestione dell'albero.
EMG

vorrei prenderlo ad esempio, potresti postarlo?
scusa il ritardo nella risposta, ti ho riscritto il codice nei ritagli
di tempo :
/****************** 
 * DBMS.C 
 * 09/02/2000
 * ---------------
 * Andrea Laforgia 
 ******************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FALSE   0
#define TRUE    1
#define DBFILE  "rubrica.db"
typedef FILE*  DBFilePtr ;
typedef int    bool ;
/* definisco la struttura del record */
typedef struct {
           bool deleted  ;
           char firstname[15] ;
           char lastname [15] ;
           char address  [20] ;
           char tel      [10] ;
        } record_t ;
void Message( const char * s )
{
     printf( "\n---> %s <--\n", s ) ;
}
bool GotoRecord( DBFilePtr P, long RecIdx )
{
     return fseek( P, RecIdx * sizeof( record_t ), SEEK_SET ) == 0 ;
}
bool OpenDatabase( char *DBName, DBFilePtr *P )
{
     return (( *P = fopen( DBName, "b+" ) ) != NULL ) ;
}
bool CreateDatabase( char *DBName, DBFilePtr *P )
{
     return (( *P = fopen( DBName, "wb+" ) ) != NULL ) ;
}
bool DatabaseExists( char *DBName )
{
     bool RetVal = FALSE ;
     FILE *fp ;
     if ( ( fp = fopen( DBName, "r" ) ) )
     {
        fclose( fp ) ;
        RetVal = TRUE ;
     }
     return RetVal ;
}
bool CloseDatabase( DBFilePtr P )
{
     return ( fclose( P ) != EOF ) ;
}
bool RewindDatabase( DBFilePtr P )
{
     return GotoRecord( P, 0L ) ;
}
bool GetRecord( DBFilePtr P, long RecIdx, record_t *RecBuffPtr )
{
     bool RetVal = FALSE ;
     if ( GotoRecord( P, RecIdx ) &&
          fread( RecBuffPtr, sizeof( record_t ), 1L, P ) > 0 )
        RetVal = TRUE ;
     return RetVal ;
}
bool PostRecord( DBFilePtr P, long RecIdx, record_t *RecBuffPtr )
{
     bool RetVal = FALSE ;
     if ( GotoRecord( P, RecIdx ) &&
          fwrite( RecBuffPtr, sizeof( record_t ), 1L, P ) > 0 )
        RetVal = TRUE ;
     return RetVal ;
}
bool AppendNewRecord( DBFilePtr P, record_t *RecBuffPtr )
{
     bool RetVal = FALSE ;
     if ( fseek( P, 0L, SEEK_END ) == 0 &&
          fwrite( RecBuffPtr, sizeof( record_t ), 1L, P ) > 0 )
     RetVal = TRUE ;
     return RetVal ;
}
bool ReadString( char *s, int max )
{
     bool RetVal = fgets( s, max, stdin ) != NULL ;
     if ( RetVal )
     {
        s[ strlen( s ) - 1] = NULL ;
     }
     return RetVal ;
}
char GetCh( void )
{
     int d, c = getchar() ;
     d = c ;
     while ( ( d != -1 ) && ( d != '\n' ) )
     {
           d = getchar() ;
     }
     return c ;
}
void ShowMainMenu()
{
     printf( "\nEsempio di gestione di database\n\n" ) ;
     printf( "Opzioni :\n\n" ) ;
     printf( "1 - Inserimento record\n" ) ;
     printf( "2 - Visualizzazione record\n" ) ;
     printf( "3 - Modifica record\n" ) ;
     printf( "4 - Cancellazione record\n" ) ;
     printf( "9 - Fine operazioni\n\n" ) ;
     printf( ">" ) ;
}
void ShowRecords( DBFilePtr P )
{
     long RecIdx = 0L ;
     record_t MyRec ;
     printf( "\n" ) ;
     printf( "num canc nome cognome    indirizzo       telefono\n" ) ;
     printf( "---|----|---------------|---------------"\
             "|--------------------|----------|\n" ) ;
     while ( GetRecord( P, RecIdx, &MyRec ) )
     {
         printf( "%3ld|%-4s|%-15s|%-15s|%-20s|%-10s|\n",
                                                 RecIdx,
                                                 MyRec.deleted ? "*":
"",
                                                 MyRec.firstname,
                                                 MyRec.lastname,
                                                 MyRec.address,
                                                 MyRec.tel ) ;
         RecIdx++ ;
     }
     if ( RecIdx == 0L )
        Message( "il database e' vuoto !" ) ;
}
void AskNewRecord( record_t *RecBuffPtr )
{
     RecBuffPtr->deleted = FALSE ;
     printf( "Nome      : " ) ; ReadString( RecBuffPtr->firstname,
                                       sizeof RecBuffPtr->firstname )
;
     printf( "Cognome   : " ) ; ReadString( RecBuffPtr->lastname,
                                       sizeof RecBuffPtr->lastname ) ;
     printf( "Indirizzo : " ) ; ReadString( RecBuffPtr->address,
                                       sizeof RecBuffPtr->address ) ;
     printf( "Telefono  : " ) ; ReadString( RecBuffPtr->tel,
                                  sizeof RecBuffPtr->tel ) ;
}
void InsertNewRecord( DBFilePtr P )
{
     record_t MyRec ;
     AskNewRecord( &MyRec ) ;
     if ( AppendNewRecord( P, &MyRec ) )
        Message( "record inserito con successo !" ) ;
     else
        Message( "errore nell'aggiunta del record !" ) ;
}
void ModifyRecords( DBFilePtr P, bool MustDelete )
{
     record_t MyRec ;
     long RecIdx ;
     char num[10] ;
     ShowRecords( P ) ;
     printf( "inserire l'indice del record :" ) ;
     ReadString( num, 5 ) ;
     RecIdx = atol( num ) ;
     if ( MustDelete &&
          GetRecord( P, RecIdx, &MyRec ) )
     {
        MyRec.deleted = TRUE ;
     }
     else AskNewRecord( &MyRec ) ;
     if ( PostRecord( P, RecIdx, &MyRec ) )
     {
        Message( "record modificato con successo !" ) ;
     }
     else Message( "impossibile modificare il record !" ) ;
}
void DeleteRecords( DBFilePtr P )
{
     ModifyRecords( P, TRUE ) ;
}
int main()
{
    DBFilePtr DataPtr ;
    char scelta ;
    if ( DatabaseExists( DBFILE ) &&
         OpenDatabase( DBFILE, &DataPtr ) )
    {
       Message( "file database aperto con successo !" ) ;
    }
    else
    if ( !CreateDatabase( DBFILE, &DataPtr ) )
    {
       Message( "errore nell'apertura del file database !" ) ;
       exit( 1 ) ;
    }
    else Message( "file database creato e aperto con successo !" ) ;
    do
    {
       ShowMainMenu() ;
       scelta = GetCh() ;
       switch( scelta )
       {
             case '1' : InsertNewRecord( DataPtr ) ; break ;
             case '2' : ShowRecords( DataPtr ) ; break ;
             case '3' : ModifyRecords( DataPtr, FALSE ) ; break ;
             case '4' : DeleteRecords( DataPtr ) ; break ;
       }
    } while ( scelta != '9' ) ;
    if ( !CloseDatabase( DataPtr )  )
    {
       Message( "errore nella chiusura del file database !" ) ;
       exit( 1 ) ;
    }
    return 0 ;
