PDA

Visualizza la versione completa : [C++] Gestione dei ritorni a capo su diversi sistemi operativi


Hysoka
13-09-2011, 17:35
ciao a tutti,
premetto che ho fatto un programma in C che con linux funziona bene. In pratica legge un file e lo interpreta.
Compilando questo programma con linux, lui gestisce perfettamente i differenti ritorni a capo in base al sistema (\n, \r oppure \n\r).

La cosa non accade usando mingw dato in dotazione con devcpp 4.9.9.2.
Il programma da problemi quando salvo un file con il formato DOS \n\r.
Facendo il debug e leggendo il file di input in questione in formato DOS, ottengo questo risultato:
0x3e25c8 "x -y\ny -x\n-x -z\nz -y\nð_ºî"

Invece, aprendo il file di input e lo codifico per UNIX e MAC, ottengo rispettivamente
0x3e25c8 "x -y\ny -x\n-x -z\nz -y\n"
0x3e25c8 "x -y\ry -x\r-x -z\rz -y\r"

che è il risultato desiderato e il programma funziona bene in entrambi i casi

Il problema sta quindi quando salvo il file di input in dos con \n\r. Ripeto che su linux questo non accade e il file viene letto con successo.

La funzione che si occupa di leggere il file in questione è la seguente:


char * leggiInputFile(FILE* h)
{
char *contenuto;
int size;
//leggo la dimensione del file
//spostando il puntatore alla fine e leggendo il numero di byte
fseek(h,0,SEEK_END);
size = ftell(h);
rewind(h);

contenuto = (char*)malloc(size+1);

if (contenuto==NULL)
{
printf("Cannot read input file: insufficient memory\n");
}

fread(contenuto,1,size,h);
contenuto[size]='\0';

return contenuto;
}

cosa ha di sbagliato su windows questo codice? C'è per caso una diversa implementazione della funzione fread che toglie \n\r e li fa diventare \n? Se è così, allora cos'è quella schifezza che trovo alla fine?

shodan
13-09-2011, 17:52
A parte che è \r\n non \n\r, il file lo apri in modalità binaria o testo? Perché è questo che modifica il comportamento di fread.

Hysoka
13-09-2011, 18:05
Originariamente inviato da shodan
A parte che è \r\n non \n\r, il file lo apri in modalità binaria o testo? Perché è questo che modifica il comportamento di fread.
ricordavo male,
lo apro come file di testo
Adesso ho provato mettendo rb e pare che il problema si sia risolto.
Faccio altre prove e se ci sono altri consigli, li accetto
ma come mai questo comportamento tra i diversi OS, nonostante che dovrebbero essere le stesse funzioni?

shodan
13-09-2011, 18:24
Perché sono diversi OS, appunto. Linux/Unix utilizzano \n come carattere newline; MAC (almeno quelli vecchi, quelli *BSD based non lo so) usano/usavano \r; DOS/Windows \r\n. Questione di gusti pare.

Ne consegue che in Linux/Unix (MAC?) non esiste la concezione tra file di testo e file binario, mentre in Windows si. E la differenza è proprio quel \r in più che sballa i conti.
In pratica in modalità binaria, \r non è "strippato" da fread; in modalità testo si.
Dato che ftell() non fa questa distinzione, lei restituisce la dimensione totale del file, compresi i \r. Ma se fread() toglie i \r, leggi più caratteri di quanti fread ne fornisca. Ecco la spazzatura alla fine.
Per toglierla devi usare il valore di ritorno di fread() come indice dell'array.


int nread = fread(contenuto,1,size,h);
contenuto[nread]='\0';

Hysoka
13-09-2011, 19:41
Originariamente inviato da shodan
Perché sono diversi OS, appunto. Linux/Unix utilizzano \n come carattere newline; MAC (almeno quelli vecchi, quelli *BSD based non lo so) usano/usavano \r; DOS/Windows \r\n. Questione di gusti pare.

Ne consegue che in Linux/Unix (MAC?) non esiste la concezione tra file di testo e file binario, mentre in Windows si. E la differenza è proprio quel \r in più che sballa i conti.
In pratica in modalità binaria, \r non è "strippato" da fread; in modalità testo si.
Dato che ftell() non fa questa distinzione, lei restituisce la dimensione totale del file, compresi i \r. Ma se fread() toglie i \r, leggi più caratteri di quanti fread ne fornisca. Ecco la spazzatura alla fine.
Per toglierla devi usare il valore di ritorno di fread() come indice dell'array.


int nread = fread(contenuto,1,size,h);
contenuto[nread]='\0';


mi piace questa soluzione...
più di quella di mettere rb...
grazie...non ci avevo proprio pensato
edit: grazie per la spiegazione, e che io non programmo mai in C per windows. Ma quando c'è di mezzo l'università, non sai mai cosa usarà il prof

shodan
13-09-2011, 19:50
Originariamente inviato da Hysoka
mi piace questa soluzione...
E' come andrebbe usata fread() a prescindere dall'OS sottostante.

Loading