QString to char * konwersja

99

Próbowałem przekonwertować QString na typ char * za pomocą następujących metod, ale wydaje się, że nie działają.

//QLineEdit *line=new QLineEdit();{just to describe what is line here}

QString temp=line->text();
char *str=(char *)malloc(10);
QByteArray ba=temp.toLatin1();
strcpy(str,ba.data());

Czy możesz wyjaśnić możliwą wadę tej metody lub podać alternatywną metodę?

mawia
źródło
Twój przykład działa dobrze dla mnie, gdzie jest problem?
Viesturs
3
Przepraszam za mój angielski, ale dlaczego takie podejście nie jest właściwe? QString s("some"); printf(reinterpret_cast<char *>(s.data()));
bartolo-otrit

Odpowiedzi:

118

Cóż, Qt FAQ mówi:

int main(int argc, char **argv)
{
 QApplication app(argc, argv);
  QString str1 = "Test";
  QByteArray ba = str1.toLocal8Bit();
  const char *c_str2 = ba.data();
  printf("str2: %s", c_str2);
  return app.exec();
}

Więc może masz inne problemy. Jak dokładnie to nie działa?

Eli Bendersky
źródło
11
const char*i char*nie są tego samego typu.
Wyścigi lekkości na orbicie
3
@LightnessRacesinOrbit: pisanie do zawartości QString bez jego wiedzy jest okropnym pomysłem, stąd oczywiście const char*to, co naprawdę można uzyskać. Użytkownik może skopiować dane do buforu z możliwością zapisu.
Eli Bendersky
1
Całkowicie się zgadzam. Jednak pytanie o char*nie char const*, a Twoja odpowiedź po prostu ignoruje ten fakt bez wzmianki.
Wyścigi lekkości na orbicie
4
@LightnessRacesinOrbit: czasami najlepszą odpowiedzią jest zdemaskowanie pytania. Innymi słowy, aby zwrócić uwagę, że nie jest to pytanie o właściwą rzecz. Ta odpowiedź została zaakceptowana przez plakat z pytaniami, więc przypuszczam, że trafiła w swój cel
Eli Bendersky
2
wygląda na to, że FAQ został zaktualizowany do użycia toLocal8Bit()?
Larry
53

Może

my_qstring.toStdString().c_str();

lub bezpieczniej, jak podkreśla Federico:

std::string str = my_qstring.toStdString();
const char* p = str.c_str();

To dalekie od optymalnego, ale wystarczy.

davidnr
źródło
3
Spowoduje to zepsucie znaków Unicode. Rozwiązanie przyjazne dla Unicode: stackoverflow.com/a/4644922/238387
jlstrecker
21
Ta metoda jest bardzo niebezpieczna i nie należy jej używać: toStdString()zwróć nowy std::stringobiekt, a następnie const char *uzyskany zostanie wskaźnik do danych wewnętrznych . Jednak obiekt ciągu znaków jest natychmiast niszczony po tej instrukcji, więc wskaźnik wyniku prawdopodobnie nie ma prawidłowego adresu, jeśli zostanie użyty w kolejnej instrukcji.
RicoRico
@RicoRico To nie jest metoda, toStdString()która jest niebezpieczna; to użycie surowych wskaźników. A dokładniej, użycie surowych wskaźników z obiektów, których zakresy nie są dobrze zrozumiałe.
notlesh
W szczególności tymczasowe C ++ zwykle żyją do końca instrukcji, która je tworzy. Zatem pierwsza forma odpowiedzi jest w porządku, jeśli jest używana w linii w wywołaniu funkcji (zakładając, że funkcja nie przechowuje wskaźnika do przyszłego użytku), ale nie jest w porządku, jeśli jest przypisana do zmiennej.
plugwash
46

Najłatwiejszym sposobem konwersji QString na char * jest qPrintable (const QString & str) , czyli makro rozwijające się do str.toLocal8Bit().constData().

Robert
źródło
Dlaczego nie jest to bardziej popularna odpowiedź? Właśnie dowiedziałem się o tym przez przypadek, grzebując w źródle Qt i właśnie to robią.
Phlucious
6
@Phlucious, ponieważ: 1) qPrintablezwraca const char*nie char*, str.toLocal8Bit().data()powróci char*. 2) Wskaźnik do const char*staje się nieważny, gdy tylko trafisz na średnik w instrukcji, w której qPrintablezostał użyty. Więc const char* c_ptr = s.toLocal8Bit().constData();nie ma sensu.
WindyFields
1
@Phlucious thanks you are life saver :) te wszystkie najczęściej głosowane odpowiedzi są błędne, Pytanie dotyczy
chara
Czy na qPrintablewyjściu jest gwarantowane zakończenie zerowe?
Giovanni Cerretani
@WindyFields - zgodnie z ostrzeżeniem w qPrintable()opisie: "Wskaźnik znaku będzie nieprawidłowy po instrukcji, w której użyto qPrintable ()."
Jeremy
6

Odpowiedź Davida działa dobrze, jeśli używasz jej tylko do wyprowadzania do pliku lub wyświetlania na ekranie, ale jeśli funkcja lub biblioteka wymaga znaku * do analizy, ta metoda działa najlepiej:

// copy QString to char*
QString filename = "C:\dev\file.xml";
char* cstr;
string fname = filename.toStdString();
cstr = new char [fname.size()+1];
strcpy( cstr, fname.c_str() );

// function that requires a char* parameter
parseXML(cstr);
Alex
źródło
4

EDYTOWANO

w ten sposób też działa

QString str ("Something");

char* ch = str.toStdString().C_str();
Shanks
źródło
To wygląda na inną konwersję ( std::stringQString), a nie to, o co się prosi.
Toby Speight
3

Twój ciąg może zawierać znaki inne niż Latin1, co prowadzi do niezdefiniowanych danych. To zależy od tego, co masz na myśli, mówiąc „to nie wydaje się działać”.

gregseth
źródło
2

poprawne rozwiązanie wyglądałoby tak

   QString k;
   k = "CRAZYYYQT";
   char ab[16];
   sprintf(ab,"%s",(const char *)((QByteArray)(k.toLatin1()).data()) );
   sprintf(ab,"%s",(const char *)((QByteArray)(k.toStdString()).data()));  
   sprintf(ab,"%s",(const char *)k.toStdString().c_str()  );
   qDebug()<<"--->"<<ab<<"<---";
sam
źródło
Zapomnij o rzucaniu w stylu C.
kyb
2

Jeśli twój ciąg zawiera znaki spoza ASCII - lepiej zrobić to w ten sposób: s.toUtf8().data()(lub s->toUtf8().data())

AlexDarkVoid
źródło
0

Jest to realny sposób na użycie std :: vector jako kontenera pośredniego:

QString dataSrc("FooBar");
QString databa = dataSrc.toUtf8();
std::vector<char> data(databa.begin(), databa.end());
char* pDataChar = data.data();
TCH
źródło
0

Qt zapewnia najprostsze API

const char *qPrintable(const QString &str)
const char *qUtf8Printable(const QString &str)

Jeśli chcesz, aby wskaźnik danych nie był stały, użyj

str.toLocal8Bit().data()
str.toUtf8().data()
user2042397
źródło