PDA

View Full Version : [C++] problemi a riconoscere caratteri ASCII


anyanka
26-03-2009, 18:01
Salve ragazzi, avrei bisogno che mi aiutaste a capire da dove deriva il mio problema:
ho un programmino, creato su win, funzionante, che scrive in un file caratteri che corrispondono a codici (ASCII, unsigned char) che rappresentano altre stringhe.
Dovrebbe funzionare anche su linux perchè non uso nessuna funzione specifica per windows (credo!) invece anzichè scrivere i valori che mi aspetto, ne scrive altri [ad esempio dovrebbe scrivere 1 (codice ascii in decimale) e mi ritrovo un 156].... da cosa può dipendere?
Il codice è questo:



const unsigned char FLAG_BYTE = '\xFF' ;
const unsigned char END_OF_VALUES = '\xFE' ;
typedef struct {
string valore;
int num_occorrenze ;
unsigned char codice ;
} VALORI ;

typedef struct {
char * stringa ;
int dim ;
unsigned char flag ; // serve per differenziare un valore che è stato codificato da uno scritto così com'è,

} DATI_OUT ;

............
DATI_OUT contenuto_attributo = recupero_codice_attr(atts[i]) ;
output.write(contenuto_attributo.stringa, contenuto_attributo.dim) ;
output.write((char *)&contenuto_attributo.flag, sizeof(char));




DATI_OUT recupero_codice_attr(string val) {
DATI_OUT dati ;
VALORI valore_corrente ;
if(val.length() >= CARATTERI) {
valore_corrente = ricerca_valore(val) ;
if( valore_corrente.codice != FLAG_BYTE ) {
// new_output << "sizeof(valore_corrente.codice) = " << sizeof(valore_corrente.codice) << " " ;
dati.stringa = (char *)&valore_corrente.codice ;
// oss: nella conversione da unsigned char a char * il dato diventa da 1 a 3 caratteri....(???)
dati.dim = sizeof(valore_corrente.codice) ;
dati.flag = FLAG_BYTE ; // i valori che hanno flag = FLAG_BYTE sono stati codificati

}
else {
dati.stringa = (char *)val.c_str() ;
dati.dim = val.length() ;
dati.flag = END_OF_VALUES ; // ivalori che hanno flag = END_OF_VALUES non sono stati codificati
}
} else {
dati.stringa = (char *)val.c_str() ;
dati.dim = val.length() ;
dati.flag = END_OF_VALUES ;
}

return dati ;
}


mancano parecchie parti.. ma questo dovrebbe bastare...

BrutPitt
26-03-2009, 18:33
Ma leggi anche da un file i valori?

Hai considerato il fatto che, nei file ASCII, Windows/Dos hanno un CR (carriage return) in piu' nella "andata a capo" rispetto a Unix?

E questo passaggio lo giudico un po' dubbio (o almeno non si evince l'uso che ne fai):

dati.stringa = (char *)&valore_corrente.codice ;

Cioe' associ l'indirizzo di un carattere (char) a un array di carrattei (char *)... e sintatticamente e' corretto... ma poi che fai, lo utilizzi come stringa?
(senza che sia null terminated)

anyanka
26-03-2009, 18:56
Allora approfondisco la spiegazione:
ho un vector di strutture che contiene coppie (stringa, codice)
questo codice è un unsigned char che va da 1 a 255.
la funzione recupero_codice fa questo:
- cerca la stringa nel vector
- legge il codice
- se il codice è != 255 passa alla struttura risultante dati i valori del codice stesso come stringa (cioè l'istruzione che hai evidenziato) , la lunghezza (dim) ovviamente sarà 1 e il flag byte che serve in un'altra fase...
- se il codice è 255 passa direttamente la stringa, dim = alla sua lunghezza e il flag è diverso.
Il cast a char * mi serve per andare a scrivere direttamente il valore nella funzione write(char *, len)
l'output è un file binario, non di testo, quindi non dovrei avere problemi di a capo o simili...
il problema sta proprio nel valore del carattere che su linux viene scritto nel file che in alcuni casi non capisco da dove provenga.

cionci
26-03-2009, 19:03
dati.stringa = (char *)val.c_str();

Questo non è corretto perché val può cambiare senza che tu te ne renda conto la posizione in cui è allocato il buffer che contiene i caratteri.
In quel caso devi fare un'allocazione dinamica:

dati.stringa = new char[val.size() + 1];
strcpy(dati.stringa, val.c_str());

Ovviamente dopo quella struttura dati deve essere deallocata.
Che funzioni anche senza può anche essere, ma non è corretto.

anyanka
26-03-2009, 19:18
Avevo appena fatto questa modifica:


DATI_OUT recupero_codice_attr(string val) {
DATI_OUT dati ;
VALORI valore_corrente ;
if(val.length() >= CARATTERI) {
valore_corrente = ricerca_valore(val) ;
if( valore_corrente.codice != FLAG_BYTE ) {
// new_output << "sizeof(valore_corrente.codice) = " << sizeof(valore_corrente.codice) << " " ;
dati.stringa = new char ;
dati.stringa = (char *)&valore_corrente.codice ;
// oss: nella conversione da unsigned char a char * il dato diventa da 1 a 3 caratteri....(???)
dati.dim = sizeof(valore_corrente.codice) ;
dati.flag = FLAG_BYTE ; // i valori che hanno flag = FLAG_BYTE sono stati codificati

}
else {
dati.dim = val.length() ;
dati.stringa = new char[dati.dim] ;
dati.stringa = (char *)val.c_str() ;
dati.flag = END_OF_VALUES ; // ivalori che hanno flag = END_OF_VALUES non sono stati codificati
}
} else {
dati.dim = val.length() ;
dati.stringa = new char[dati.dim] ;
dati.stringa = (char *)val.c_str() ;
dati.flag = END_OF_VALUES ;
}
new_output << *dati.stringa << "- " << dati.dim << " -" << dati.flag << "\n" ;
return dati ;
}


Va un po' meglio ma ha ancora un comportamento anomalo... ora provo con strcpy...
Grazie a tutti!

cionci
26-03-2009, 19:23
dati.stringa = new char[dati.dim] ;
dati.stringa = (char *)val.c_str() ;

Questo è errato proprio dal punto di vista concettuale. Hai un memory leak perché il puntatore alla memoria allocata dinamicamente viene perso. Non dovrebbe assolutamente funzionare meglio, ma al massimo uguale a prima.

anyanka
26-03-2009, 19:34
hai ragione.. era uguale...con strcpy sembra funzionare....
ma com'è che su win non mi dava problemi? :confused: nè in compilazione nè nel risultato...

cmq in generale per trasformare una stringa in un char * devo usare sempre strcpy?

cionci
26-03-2009, 19:38
Dipende dall'uso che ne devi fare...se la devi copiare e ci devi lavorare sopra sì.
Se la devi usare direttamente in forma costante no. Non a caso c_str ritorna un const char *.

Su Win non ti dava problemi probabilmente per una diversa implementazione interna della string.

anyanka
26-03-2009, 19:44
Fosse per me farei tutto con le stringhe ma ci sono alcune funzioni che richiedono i puntatori a char (come la write ad es.) e mi costringono a fare il cambio.. ecco perché avevo fatto quel pastrocchio prima :stordita:
comunque grazie mille!