|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
[C] Leggere un intero rigo da file
Raga ho scritto questo codice in C per leggere un intero rigo da un file di testo senza sapere a prescindere quanto è lungo....ma ci deve essere qualche errore:
Codice:
int freadline(char **buffer, FILE *stream)
{
// variabili d'appoggio
int indice; // serve per salvare il numero di caratteri letti
char appoggio; // serve a memorizzare il singolo carattere letto
char *temp=(char *)malloc(sizeof(char)); // conterrà tutta la riga
// se è stato realmente aperto un file allora...
if (stream!=NULL)
{
// inizializzo il contatore dei caratteri
indice=0;
// leggo un carattere e lo memorizzo in appoggio
appoggio=fgetc(stream);
// finche il carattere letto non è quello di fine riga o di fine file
while ((appoggio!=EOF) && (appoggio!='\n'))
{
// memorizzo il carattere in temp
temp[indice]=appoggio;
// realloco memoria per temp
realloc(temp,sizeof(char [1]));
// incremento indicie
indice++;
// legggo un carattere e lo memorizzo in appoggio
appoggio=fgetc(stream);
}
temp[indice]='\0';
} else return 0;
*buffer=temp;
return indice;
}
Codice:
int main()
{
char *dest=NULL;
int caratteriletti;
FILE *file;
file=fopen("infile.txt","r");
if (file==NULL)
printf("Errore duranre l'apertura del file!");
else
{
// Legge il primo rigo del file
caratteriletti=freadline(&dest, file);
// Altro codice...
}
system("PAUSE");
return 0;
}
Codice:
caratteriletti=freadline(&dest, file); dove sbaglio?
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Jun 2002
Città: Milano
Messaggi: 959
|
anomalie di che tipo?
facendo così se richiami la funzione nel main ti leggerà sempre la prima riga |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
beh veramente mi legge anche le altre, il problema è che ci deve essere qualche errore poichè se richiamo la funzione una sola volta il
system("PAUSE"); che c'è nel main viene processato correttamente e mi mostra a schermo quello che ha letto, mentre se richiamo la funzione più volte il programma si apre e si chiude rapidamente senza farmi leggere nulla (riesco a vedere l'output solo se eseguo l'eseguibile dal Prompt del DOS)....
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Ciao, ho dato una occhiata al tuo codice (non l'ho provato realmente). Ci sono alcune cose che non vanno:
Quando fai: Codice:
realloc(temp,sizeof(char [1])); Inoltre la realloc ti ritorna un puntatore (void*) perché è possibile che la nuova area sia "spostata". Comunque leggere 1 carattere per volta e riallocare il buffer ad ogni nuovo carattere non è, in effetti, molto efficiente.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
me lo sapresti sistemare?
il fatto è che io ho sempre programmato in TurboPascal e da un paio d'anni in VB6 e col C non ho per niente dimestichezza.....help me ======== EDIT ========== l'ho modificato così e funziona...ma è sicuramente migliorabile...help: Codice:
int freadline(char **buffer, FILE *stream)
{
// variabili d'appoggio
int indice; // serve per salvare il numero di caratteri letti
char appoggio; // serve a memorizzare il singolo carattere letto
char *temp=(char *)malloc(sizeof(char[10])); // conterrà tutta la riga
// se è stato realmente aperto un file allora...
if (stream!=NULL)
{
// inizializzo il contatore dei caratteri
indice=0;
// leggo un carattere e lo memorizzo in appoggio
appoggio=fgetc(stream);
// finche il carattere letto non è quello di fine riga o di fine file
while ((appoggio!=EOF) && (appoggio!='\n'))
{
// realloco memoria per temp
if (indice>=strlen(temp)) realloc(temp,sizeof(char[indice+10]));
// memorizzo il carattere in temp
temp[indice]=appoggio;
// incremento indicie
indice++;
// legggo un carattere e lo memorizzo in appoggio
appoggio=fgetc(stream);
}
temp[indice]='\0';
} else return 0;
*buffer=temp;
//free(temp);
return indice;
}
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC Ultima modifica di leadergl : 13-01-2006 alle 12:33. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Ciao, come al solito posso postare la "mia" soluzione personale.
Se si vuole usare la fgetc (lettura di un singolo carattere per volta): Codice:
#define READLINE_EXTEND 128
char *readline (FILE *f, int *plen)
{
char *row = NULL, *row_t = NULL;
int ch, rowlen = 0, buflen = 0;
while ((ch = fgetc (f)) != EOF)
{
if (rowlen >= buflen)
{
buflen = rowlen+READLINE_EXTEND;
row_t = (char *) realloc (row, buflen);
if (row_t == NULL)
break;
}
row = row_t;
if (ch != '\n')
row[rowlen++] = (char) ch;
else
break;
}
if (row_t != NULL)
{
row[rowlen] = '\0';
if (plen != NULL)
*plen = rowlen;
}
else
{
free (row);
row = NULL;
}
return row;
}
Codice:
#define READLINE_EXTEND 128
char *readline (FILE *f, int *plen)
{
char *row = NULL, *row_t, *p;
int len = 0, pos = 0, rowlen;
do {
len += READLINE_EXTEND;
if ((row_t = (char *) realloc (row, len)) != NULL)
{
row = row_t;
if (fgets (&row[pos], READLINE_EXTEND, f) != NULL)
{
if ((p = strchr (&row[pos], '\n')) != NULL)
{
*p = '\0';
rowlen = p - row;
break;
}
else
pos += READLINE_EXTEND-1;
}
else
row_t = NULL;
}
} while (row_t != NULL);
if (row_t != NULL)
{
if (plen != NULL)
*plen = rowlen;
}
else
{
free (row);
row = NULL;
}
return row;
}
Entrambe ritornano NULL se si raggiunge EOF o se la realloc fallisce.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#7 |
|
Bannato
Iscritto dal: Jan 2006
Messaggi: 27
|
leader,
forse non ti piacera' detto da un "novellino" ma il tuo metoto mi sembra molto complicato e poco efficiente. Personalmente preferisco fissare la massima riga che accetto di leggere e allocare memoria di conseguenza. Questo dei vantaggi: 1. Se la riga che arriva e' maggiore da quella che ho fissato, probabilmente mi trovo davanti ad un file corrotto oppure davanti ad un attacco hacker, quindi e' meglio non leggere tutto e caricarlo in memoria. 2. Non si puo' andare ad allocare memoria solo perche' la riga e' lunga... la gestione degli overflow e' piu' complicata che nel caso di dimensioni massime fisse. 3. Riallocare ogni volta 1 carattere comporta una penalita' enorme a livello di heap, e puo' provocare una frammentazione terribile. In piu' a seconda dell'implementazione potrebbe comportare un copy ad ogni rialloco di carattere. Se pero' vuoi proprio leggere tutta la riga, suggerirei di leggere dal file a blocchi (e' molto piu' efficiente, anche se comporta uno spreco medio di memoria di blocksize/2). Pero' hai il vantaggio di non frammentare il heap. Ad occhio e croce l'algo che scriverei potrebbe essere cosi (e occhio che preserva il \n finale): Codice:
#define BLOCK_SIZE 1024
char *read_long_line( FILE *f ) {
int curread ; // caratteri letti nel blocco
int totread ; // totale caratteri di tutti i blocchi
char *s ; // stringa totale.
char *p ; // stringa blocco.
p = s = malloc( BLOCK_SIZE ) ;
totread = 0 ;
while ( (curread=fgets(p,BLOCK_SIZE-1,f) > 0 ) {
totread += curread ;
p[BLOCK_SIZE-1] = '\0' ; // terminiamo la stringa per facilita'.
if ( curread == BLOCK_SIZE-1 ) { // oops... strigna piu' lunga
s = realloc( s, totread + BLOCK_SIZE ) ;
p = s + totread ; // p ora punta alla fine della s.
}
}
return s ;
}
Ho evitato copia-copia inutile. L'unico copy potrebbe essere dentro la realloc Scusa se ti sembra troppo condensato... sono un maniaco della compattezza del codice e della efficienza. Ciao Ultima modifica di pvpn : 13-01-2006 alle 15:51. |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
ti ringrazio, mi sei stato utilissimo....ora giusto per curiosità cosa c'è di sbagliato in questo?
Codice:
#define string char *
string mid(string origine, int inizio, int fine)
{
int i;
string tmp=(string)malloc(sizeof(fine-inizio)+1);
if (fine>strlen(origine)) fine=strlen(origine);
for (i=inizio;i<=fine;i++)
{
tmp[i]=origine[i];
}
return tmp;
}
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Jun 2002
Città:
Provincia De VaRéSe ~ § ~ Lat.: 45° 51' 7" N Long.: 8° 50' 21" E ~§~ Magica Inter ~ § ~ Detto: A Chi Più Amiamo Meno Dire Sappiamo ~ § ~ ~ § ~ Hobby: Divertimento allo Stato Puro ~ § ~ ~ § ~ You Must Go Out ~ § ~
Messaggi: 8897
|
semplicemente perchè quella che hai dichiarato altro non è che una variabile LOCALE della funzione
~§~ Sempre E Solo Lei ~§~
__________________
Meglio essere protagonisti della propria tragedia che spettatori della propria vita
Si dovrebbe pensare più a far bene che a stare bene: e così si finirebbe anche a star meglio. Non preoccuparti solo di essere migliore dei tuoi contemporanei o dei tuoi predecessori.Cerca solo di essere migliore di te stesso |
|
|
|
|
|
#10 |
|
Bannato
Iscritto dal: Jan 2006
Messaggi: 27
|
Eviterei di definire una stringa un puntatore... si perde il significato e si scorda il puntatore.
comunque... Codice:
string mid(string origine, int inizio, int fine) {
int len = strlen(origine) ;
string s ;
if ( fine-inizio+1 > len ) {
fine = len - 1 ;
s = malloc(fine-inizio+2); // 0-0 e' sempre 1 carattere + 1 per il terminatore
strncpy(s,origine+inizio,fine-inizio+1) ;
s[fine-inizio+1] = '\0';
return s ;
}
|
|
|
|
|
|
#11 | |
|
Bannato
Iscritto dal: Jan 2006
Messaggi: 27
|
Quote:
Personalmente non sono un fan della allocazione dentro le funzioni... si tende a perdere il controllo di quanto allocato e ci si deve sempre ricordare chi alloca e chi non alloca roba sul heap. |
|
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Jun 2002
Città:
Provincia De VaRéSe ~ § ~ Lat.: 45° 51' 7" N Long.: 8° 50' 21" E ~§~ Magica Inter ~ § ~ Detto: A Chi Più Amiamo Meno Dire Sappiamo ~ § ~ ~ § ~ Hobby: Divertimento allo Stato Puro ~ § ~ ~ § ~ You Must Go Out ~ § ~
Messaggi: 8897
|
Quote:
~§~ Sempre E Solo Lei ~§~
__________________
Meglio essere protagonisti della propria tragedia che spettatori della propria vita
Si dovrebbe pensare più a far bene che a stare bene: e così si finirebbe anche a star meglio. Non preoccuparti solo di essere migliore dei tuoi contemporanei o dei tuoi predecessori.Cerca solo di essere migliore di te stesso |
|
|
|
|
|
|
#13 |
|
Bannato
Iscritto dal: Jan 2006
Messaggi: 27
|
Se vuoi sapere in cosa hai sbagliato nel tuo codice originale
Codice:
for (i=inizio;i<=fine;i++)
{
tmp[i]=origine[i];
}
Quindi stai scrivendo in tmp[10] quando dovresti partire da tmp[0].... Ciao. PS: Mazza.... 4 post in 30 minuti... e non mi sono ancora presentato. |
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
leadergl, occhio che:
Codice:
#define string char * Codice:
typedef char* string; --------- #define string char * string s1, s2; --------- e --------- typedef char* string; string s1, s2; --------- Quote:
Inoltre, nel codice in un post sopra (non te l'ho segnalato subito), hai messo: Codice:
sizeof(char[indice+10])
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
perfetto, vi ringrazio
ora posso proseguire col mio cavolo di progetto in C... mi sento un deficiente quando programmo in C ...vabbè....torno al mio albero radicato... ah..non è che avete sotto-mano qualche algoritmo per riempire un albero radicato caricandolo da file?
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC |
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#17 | ||
|
Senior Member
Iscritto dal: May 2003
Messaggi: 1113
|
io lo devo consegnare il 15...cmq il programma è abbastanza avanti nel senso che ho scritto:
1) funzioni gestione lista 2) funzioni gestione albero 3) funzione (con vostre correzioni) per leggere un intero rigo da file 4) funzione (con vostre correzioni) per gestire facilmente la riga letta (in alternativa ho usato la strtok) 5) struttura del file scelta (questa è più semplice da gestire e non ci sono dati ridondanti): Quote:
Quote:
...perchè io ho cominciato a perdermi durante la scrittura del codice....a te viene in mente niente? P.S. A mia disposizione per un rapido utilizzo ho: 1) freadline -> legge una riga intera da file 2) separa -> permette di estrarre da una stringa delle sottostringhe separate da un carattere speciale 3) mid -> permette di estrarre da una stringa una sottostringa dandone inizio e fine credo che queste agevolano non poco il lavoro...
__________________
| Athlon XP Barton 3000+ | CoolerMaster HAC-V81 | ASUS A7N8X DELUXE v2.0 | 2*256 PC3200 + 1*512 PC3200 = 1GB DDR400| ATI Radeon 9250 | HD 80Gb Maxtor SATA | Ali Q-TEC 550W Dual Fan GOLD PFC Ultima modifica di leadergl : 13-01-2006 alle 17:36. |
||
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Mar 2001
Città: Roma
Messaggi: 2532
|
non so se è stato detto,
ma perchè invece della "PAUSE" di sistema non viene chiamata una getch() ? La trovo + efficiente come "pausa".. Poi, tornando allo scopo del codice, perchè non usare un parser a puntatori con la funzione strstr chiamata sull' End of line? vabbè, forse non è proprio da dilettanti, però è abbastanza efficiente.. Mah..solo consigli i miei.. Ciao |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 16:20.



















