Newsgroup: it.comp.os.linux.development
Titolo: da QString a unsigned char*

Ciao a tutti,
devo passare a una funzione un parametro sotto forma di unsigned char* ma io 
ho questo dato salvato in una QString. C'č un modo furbo per poter 
convertire il contenuto della QString in un unsigned char*?
-- 
Filippo Santovito

Filippo Santovito wrote:

Ho trovato la risposta e la posto per chiunque avesse lo stesso problema:
ho usato la funzione memmove della quale pasto le prime riche della pagina 
di man.
NAME
       memmove - copy memory area
SYNOPSIS
       #include <string.h>
       void *memmove(void *dest, const void *src, size_t n);
-- 
Filippo Santovito

        memmove - copy memory area
frugando per documetazione di cui ignoravo anche l'esistenza sembra che
QString offra il metodo
const char * QString::ascii () const
Returns an 8-bit ASCII representation of the string.
il metodo
const char * QString::latin1 () const
Returns a Latin-1 representation of the string. The returned value is
undefined if the string contains non-Latin-1 characters. If you want to
convert strings into formats other than Unicode, see the QTextCodec classes.
tra l'altro sembra offrire anche un operatore di cast a const char*
... mi spieghi che abuso di QString con memmove?
ciao
 sbirish

 convertire il contenuto della QString in un unsigned char*?
Così come è posta, la domanda è poco chiara.
Come ha scritto sbirish, la classe QString dispone di alcuni metodi che
restituiscono puntatori ad array di char che contengono rappresentazioni
del contenuto della stringa. Questi metodi restituiscono const char*.
L'assenza del 'const' nel tipo puntatore a cui sei interessato, però,
suggerisce che la funzione in questione debba accedere in scrittura
all'array. Ora, se speri che una funzione possa modificare la
rappresentazione interna della QString, ebbene, te lo puoi scordare. Puoi
invece modificare una *copia* dell'array, e successivamente riassegnare la
copia modificata all'oggetto QString. Per questo basta usare uno dei
metodi citati di sbirish e copiare l'array con memcpy.
Max

  sbirish
perchè come ha ben notato Max M. io devo accedere in scrittura alla stringa 
e cmq in ogni caso non è possibile castare (implicitamente o 
esplicitamente) una const char* in una unsigned char* quindi l'operatore di 
cast fornito dalle QString non poteva essermi d'aiuto, per questo ho dovuto 
ricopiare "forzatamente" il contenuto della QString con memmove.
        QString s = "hello";
        unsigned char* str = new unsigned char[s.length() +1];
        memmove(str,(const char*)s,s.length() +1);
-- 
Filippo Santovito

         memmove(str,(const char*)s,s.length() +1);
... mi sembra un pò innaturale farlo con memmove..
strcpy fa la stessa cosa e lo fa per le stringhe.. ( a dire il vero anche
strdup..
ma poi finisci col mescolare new e malloc e non è carina spesso come cosa )
a dire il vero mi sembra un pò innaturale anche usare il cast a la C...
tanto che lo usi solo per forzare ad usare l'operatore di cast di QString..
( discutibile tra l'altro l'esistenza di quell'operatore.. nella stl si son
scannate
persone pur di non mettere un operatore di cast simile )
strcpy(str,s);
mi sembra più pulito e più leggibile
a dire il vero nel caso questa strcpy ti sia necessaria..
io ti consiglierei di rendere la cosa più leggibile usando uno dei due
metodi ( ansi() o latin1()
se non ricordo male.. )
cmq in linea generale.. s è una QString non una const QString..
perché non modifichi la stringa usando l'interfaccia che ti viene fornita da
quella classe?
anche se fosse una const QString o cmq tu non voglia modificare quella
istanza...
QString temp(s); credo sia più che sufficente..
in sostanza.. per cosa usi quel buffer str e non una QString?
per quanto riguarda il tentativo di castare da const a nonconst...
Sutter diceva di appendere dei cartelloni con scritto "const means const"
Uno sbirish che ha di nuovo un calzino bucato ( ma porc.. )

        memmove(str,(const char*)s,s.length() +1);
Questo e` *pericoloso*. Funziona per caso, solo perche` la class QString
e` fatta in questo modo:
class QString {
        char *buff;
        int size;
        ....
};
In questo caso  l'indirizzo del buffer interno  coincide con l'indirizzo
dell'istanza della classe. Se un  bel giorno cambiasse l'implementazione
(ed e` questo  il bello della programmazione ad  oggetti: posso cambiare
l'implementazione come mi  pare fintanto che l'interfaccia  non cambia e
tutto continua a funzionare) i  tuoi programmi inizieranno a comportarsi
in maniera divertente...
class QString {
        int size;
        char *buff;
        ....
};
Se QString fosse implementata cosi`  non ti funzionerebbe piu` nulla. Il
fatto e`  che il buffer  e` *privato*. Non (sottolineo *non*)  devi fare
pastrugni del genere per cercare  di aggirare i meccanismi di protezione
dei dati. Per te  la parte privata di una classe  non esiste. Quello che
devi usare e` l'intefaccia: i metodi e gli eventuali membri publici.
Esiste una soluzione facile, elegante, ma soprattutto corretta:
QString s("foobar");
char *str = new char[s.lenght() + 1];
strcpy(str, s.ascii());
O se proprio vuoi usare memcpy (non memmove):
memcpy(str, s.ascii(), s.lenght() + 1);
Il tutto senza alcun cast (e non serviva neppure con memmove).
Fai attenzione che in  C ed in C++ il fatto  che qualcosa "funzioni" non
vuol dire che sia giusto.
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
La differenza fra l'intelligenza e la stupidita`?
All'intelligenza c'e` un limite.

in maniera divertente...
credo ti sia sfuggita una cosa... QString offre un operator di cast
const char* che rende un buffer const...
con memmove non sta copiando "un pezzo di s" come credi...
č legalissimo quindi quello che ha scritto.. e continuerą cmq a 
funzionare quando e se cambieranno gli internals di QString...
ciao
 sbirish

 funzionare quando e se cambieranno gli internals di QString...
Basta mettersi d'accordo sul significato di legale.
Se intendi il "codice compila e funziona", puo' darsi che tu abbia
ragione, si intendi il "codice e' corretto" avrei qualche dubbio.
Per inciso (ma qui vado a memoria, chiedo venia anticipatamente
se scazzo) quella soluzione funziona per due motivi:
- la classe e' implementata come ha detto Kronos;
- gcc piazza il puntatore alla tabella dei metodi virtuali in coda al
  pacco di dati della classe.
Non so come e' realmente implementata la classe QString, se non ha metodi
virtuali probabilmente la soluzione funziona anche usando VC++, se la
classe ha metodi virtuali con VC++ non funziona, perche' VC++ piazza
il puntatore alla tabella dei metodi virtuali in cima al pacco di dati
della classe.
Pertanto per mandare a "signorine allegre" il codice potrebbe non
servire nemmeno cambiare la rappresentazione interna della classe,
protrebbe bastare la pretesa di compilarlo con due compilatori
diversi: vatti a trovare perche' un codice perfettamente funzionante
da anni con gcc non funziona con VC++...
C:\>iao Angelo
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Scusa la domanda ingenua, ma cosa starebbe facendo?
Non conosco l'implementazione di QString, ma probabilmente sta dicendo
che il cast verso char * viene sovraccaricato dalla classe QString,
quindi e` equivalente a usare .ascii() o quasi.
Bye.

 Scusa la domanda ingenua, ma cosa starebbe facendo?
Non conosco QString ma se esiste la ridefinizione di un operatore const 
char*, allora il codice e' corretto e funziona fintanto che il codice 
della libreria non fa cazzate...
esempio:
#include <iostream>
#include <cstring>
#include <string>
class data {
private:
	int foo1;
	int foo2;
	int foo3;
	std::string buf;
public:
	data(const std::string& hh) : buf(hh) {}
	operator const char*() {
		return buf.c_str();
	}
};
int main() {
	data d1("good morning");
	int data_len=std::strlen(d1);
	char* new_buffer=new char[data_len+1];
	std::strcpy(new_buffer,d1);
 
	std::cout << new_buffer << std::endl;
	std::cout << static_cast<void*>(new_buffer) << " " << 
static_cast<void*>(&d1) << std::endl;
}
questo codice dovrebbe funzionare sempre a meno di miei errori, infatti 
la chiamata:
std::strcpy(new_buffer,d1);
viene interpretata come:
std::strcpy(new_buffer,d1.operator cons char*());
quindi se il metodo operator cons char*() fa il proprio lavoro, e lo fa 
bene, il codice di sopra non da problemi
byez



si esatto.
centro pieno :)
ciao
 sbirish

C:\>iao Angelo
ciao
 sbirish

 Scusa la domanda ingenua, ma cosa starebbe facendo?
Sta copiando dalla zona di memoria a cui punta il puntatore restituito
dall'operatore di conversione
  QString::operator const char *() const
La zona di memoria potrebbe essere "un pezzo di s", potrebbe essere
esterna a s, allocata per l'occasione, ...   
In ogni caso e` garantito (dalla doc. di Qt) che la zona di memoria
contiene le cose "giuste".
        Mauro

 const char* che rende un buffer const...
Hmm, documentazione vecchia... hai ragione.
Kronos
-- 
Home: 
http://kronoz.cjb.net
K.R.O.N.O.S
Kinetic Replicant Optimized for Nocturnal Observation and Sabotage