Newsgroup: it.comp.lang.c
Titolo: Cancellare stringhe da files?

Salve, ho un problema urgente, spero che qualcuno
possa aiutarmi a risolverlo (non ci dormo la notte!!!).
Dispongo di un file contenente 5000 righe, ognuna con
32 caratteri alfanumerici (ovviamente + il carattere per
andare a capo). Queste righe sono dell passwords e,
una volta usate devono essere cancellate.
Il mio problema č: se devo cancellare, ad esempio, la riga n. 34,
come posso fare? (in C x DOS).
Ho pensato di creare un file di swap dove scrivere tutte le
passwords rimanenti (ovvero le 5000 meno la n.34), per
poi sovrascrivere il file originale ma non mi pare molto veloce
e affidabile, considerando che l'applicazione deve girare come CGI
su un server Web. Penso poi che non sia conveniente allocare
della memoria.
Vi ringrazio anticipatamente x il tempo che mi avete dedicato
(anche solo a leggere). Alla prossima, Piero

 e affidabile,
Allora potresti semplicemente scrivere tutti spazi bianchi sopra la
password da cancellare e magari marcarla con un carattere speciale che
indichi "spazio disponibile".
EMG

indichi "spazio disponibile".
E' un'idea. Se la lunghezza di ogni record e' fissa si puo' fare a
meno di riscrivere tutto il file. Basta posizionarsi con fseek() e
riscriverlo.
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
---------------------------------------------


Il fatto č che devo eliminare anche la riga, cioč se devo
cancellare la password n.34 da un file che contiene 5000
righe, dopo la cancellazione le righe dovranno essere
4999!!!
Grazie x l'interessamento, se ti viene qualcosa in mente
rispondi pure. Piero

4999!!!
Se il requisito di compattare il file nasce dall'esigenza di riciclare
gli indici (cioe', per esmpio, usare ancora la password 34 - che prima
della cancellazione era la 35) puoi:
- Cancella la riga come ti e' stato suggerito e usa una tabella di
indici di appoggio, svincolando la posizione della possword n dalla
riga n del file. Dovrai compattare solo la tabella che potra' essere,
a scelta:
1. in memoria: applicabile solo se usi FastCGI (e ti puoi permettere
di allocare 5000*sizeof(indice) bytes, comunque meglio di 5000*32).
Allo startup crei la tabella e allo shutdown magari compatti il file.
2. in un file di appoggio (o in testa al file delle password): lenta
ma sempre meglio che riscrivere l'intero file delle password. Puoi
srivere un programma di manutenzione per compattare le password e
rigenerare gli indici. Potresi anche usare piu' di un livello di
indici.
- Oppure usare una lista di cancellazione (in memoria permanente,
richiede sempre FastCGI) da scorrere per "aggiustare" ogni volta
l'indice della password richiesta (aggiungi uno al numero della
password per ogni cancellazione con indice < indice_nuova_richiesta).
Questo metodo degrada (sia come memoria usata che come performance) al
crescere delle cancellazioni ma potresi comapattare il file ogni N
cancellazioni (N grande a piacere: oltre un certo valore conviene il
punto 1 del caso precedente).
Se non puoi usare FastCGI ma puoi scrive la CGI come Win32 Console
Application (e quindi puoi usare le API di Windows), puoi usare un
processo di appoggio (sempre attivo) che mantenga allocata una zona di
memoria condivisa a cui agganciarti ad ogni esecuzione.
Saluti, Alberto.

 4999!!!
Oltre alla cancellazione logica (in contrapposizione a quella fisica da
te, a quanto pare, richiesta) non so che altro consigliarti.
EMG


grazie lo stesso... Piero

possa aiutarmi a risolverlo (non ci dormo la notte!!!).
Allora, i suggerimenti che ti do' sono presenti nei due moduli :
cgifill.c : riempie un file di testo di 5000 password "vive".
cgidel.c  : fa morire 91 password (da 10 a 100) e compatta il file.
---- cgifill.c :
#include <stdio.h>
int main()
{
    FILE *fp = fopen( "passwd.txt", "wt" ) ;
    int i ;
    if ( fp )
    {
       for ( i = 0 ; i < 5000 ; i++ )
       {
           fputs( "+01234567890123456789012345678901\n", fp ) ;
           /*      ^ carattere che indica la "vita" della riga */
       }
       fclose( fp ) ;
    }
    return 0 ;
}
---- cgidel.c :
#include <stdio.h>
#define FSEEK_OK    0
const char template[] = "?01234567890123456789012345678901" ;
const long size       = sizeof( template )   + 2       - 1  ;
                        /* siamo in DOS quindi ^ CR+LF ^ ma escludendo
\0 */
void del_pwd_at_pos( FILE *fp, long pos )
{
     if ( fseek( fp, pos * size, SEEK_SET ) == FSEEK_OK )
     {
        fputc( '-', fp ) ;
        /* cambiamo il flag della linea da '+' in '-' */
     }
}
void compact_database( FILE *fp, const char *new_name )
{
    FILE *new_fp = fopen( new_name, "wt" ) ;
    char s[100] ;
    if  ( new_fp )
    {
        while ( fgets( s, sizeof s, fp ) )
        {
              if ( s[0] != '-' )
              {
                 fputs( s, new_fp ) ;
              }
        }
        fclose( new_fp ) ;
    }
}
int main()
{
    FILE *fp = fopen( "passwd.txt", "rb+" ) ;
    long i ;
    if ( fp )
    {
       puts( "cancellazione delle passwords da 10 a 100..." ) ;
       for ( i = 10 ; i <= 100 ; i++ )
       {
           del_pwd_at_pos( fp, i - 1 ) ;
       }
       fclose( fp ) ;
       puts( "compattazione del database in corso..." ) ;
       if ( fp = fopen( "passwd.txt", "rt" ) )
       {
          compact_database( fp, "_passwd.txt" ) ;
          /* da eseguire periodicamente o nei momenti
             di inattivita' del sistema */
          fclose( fp ) ;
       }
    }
    return 0 ;


 cgidel.c  : fa morire 91 password (da 10 a 100) e compatta il file.
Grazie mille, ti ho mandato una e-mail, leggila (se hai tempo)