2013-07-29 16 views
7

Mam brzydki kod dla tych rzeczy (utwórz ac char pointer i skopiuj w nim QString), ale może ... istnieje w QT an elegancki sposób ...Czysty sposób przekonwertować QString na char * (nie const char * !!!!)

rzeczywisty kod:

QString maquina is a method parameter. 

char *c_maquina = new char[maquina.length() + 1]; 
strcpy(c_maquina, maquina.toStdString().c_str()); 

tylko dla informacji, że potrzebujemy prawdziwego char * nie jest prostym const char *, więc nie ten kod działa:

idMaquina.toLatin1().data(); 

mogę” t użyj http://developer.qt.nokia.com/faq/answer/how_can_i_convert_a_qstring_to_char_and_vice_versa

+0

"Nie mogę użyć łącza" - dlaczego ten link nie nadaje się do użytku? Musisz być jaśniejszy. Wyjaśnij nie tylko problem z twoim bezpośrednim planem (uzyskaj 'char *' od 'QString'), ale co skłoniło cię do myślenia, że ​​tego potrzebujesz. – Yakk

+0

Yakk, nie mogę użyć przekonwertować jak wyjaśnić w linku, ponieważ jest konwersją między QString i char * (bez możliwości nadpisania znaku *). Potrzebuję char * z możliwym nadpisaniem, mam nadzieję, funkcja QString dla to ... proszę o komentarz. –

+0

Nadal nie wiem, dlaczego nie można użyć połączonego rozwiązania. Czy problem polega na tym, że kod przykładowy używa "const char *", a nie "char *"? '.data()' zwraca 'char *'. Ponadto, co masz nadzieję zrobić z zapisywalnym 'char *'? – Yakk

Odpowiedz

26

To proste:

QByteArray array = string.toLocal8Bit(); 
char* buffer = array.data(); 

Można również użyć toLatin1 lub toUtf8 zamiast toLocal8Bit. Pamiętaj, że żadna z nich nie może być ustawiona w kolejce z połączeniem data. I toStdString().c_str() jest również nieprawidłowy. Jest tak dlatego, że każdy wyprodukowany w ten sposób QByteArray lub std::string jest tymczasowy i zostanie zniszczony, natychmiast niszcząc z nim bufor znaków. Podczas korzystania z bufora musisz przechowywać QByteArray w zmiennej lokalnej.

Należy również zauważyć, że Qt zapewnia klasę QByteArray do obsługi tablic char. Zasadniczo nie ma potrzeby używania char*, prawie wszystko można zrobić przy pomocy QByteArray.

+0

Potrzebuję do czynienia z char *, ponieważ używam biblioteki c (klienta wymagań ...), wydaje się nie działać z QByteArray.But zauważyłem niż mogę użyć lokalnego QByteArray w mojej metodzie. –

+0

masz rację! potrzebuję zawsze używać lokalnego QByteArray! sorry im noob in C++ to mój pierwszy projekt ..... –

-1

Czasami nie ma sposobu, aby zachować kod na najwyższym poziomie. Sobie z tym poradzić. Możesz go zawinąć w małą funkcję pomocniczą, biorąc QString w parametrze i zwracając char *, jeśli naprawdę chcesz.

0

QString :: toLatin1(). Data() daje const char *, ponieważ daje wewnętrzny bufor. Powodem, dla którego jest const, jest fakt, że nie powinno się go modyfikować.

Więc jeśli chcesz go zmodyfikować, musisz skopiować te dane do innego bufora ... takiego jak ten, który właśnie przydzieliłeś przy użyciu new().

0
std::vector<char> result; 
result.reserve(qstr.length()+1); // +1 might not be needed, not sure how QString counts 
result.insert(result.end(), qstr.begin(), qstr.end()); 
char* ptr = result.data(); // while retval exists, retval.data() is a char* pointing to a buffer 
+0

'std :: wektor '? To dziwny sposób na wyrażenie 'std :: string'. –

+1

Skomplikowany i nie-Qt sposób robienia tego. –

+0

@nikosc. '' String' jest ciągiem 'char' ze znaczeniem (poprzez cechy char). Wektor '' jest buforiem porcji o rozmiarze "char" bez żadnego znaczenia. Op oszukiwał bufora, o ile mogłem powiedzieć. – Yakk

1

Myślę, że rozwiązanie zależy od typu konwertowanych znaków i od tego, czy funkcja typu C z argumentami typu "char *" musi zostać zintegrowana/wywołana.

  1. Jeżeli funkcja stylu C musi być włączone/wywoływanego, nie stosować toStdString(), a następnie (c_str), a typ wartość jest równa „char *”, co nie jest korzystne dla C- funkcja stylu.
  2. Użyj doLatin1(), a następnie danych() dla znaków ASCII.
  3. Używaj dlaLocal8Bit() lub toUtf8(), a następnie danych() dla innych znaków UTF8 niż ASCII.

Jeśli w konkretnym przypadku można zastosować kilka rozwiązań, ich poziomy wydajności mogą się nieznacznie różnić, czego nie przetestowałem.

następujący program testowy pokazuje, jak korzystać z tych rozwiązań:

#include <QCoreApplication> 
#include <QDebug> 

// This is a C-style test function which needs an argument of type "char *": 
void my_c_func(char * my_c_str) 
{ 
    printf(" my_c_str[%s]\n", my_c_str); 
} 

// This is a program which tests the conversion from "QString" to "char *": 
int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    // Case 1: ASCII characters 
    // ======================== 

    QString qString1 = "French"; 
    qDebug().nospace().noquote() << "qString1[" << qString1 << "]"; // qString1[French] 

    // Solution 1.1: to Latin1 QByteArray, followed by data() in 2 steps: 
    QByteArray latin1BAString1 = qString1.toLatin1(); 
    char * latin1_c_str1 = latin1BAString1.data(); 
    qDebug().nospace().noquote() << "latin1_c_str1[" << latin1_c_str1 << "]"; // latin1_c_str1[French] 
    my_c_func(latin1_c_str1); 

    // Solution 1.2: to local 8-bit QByteArray, followed by data() in 2 steps: 
    QByteArray local8bitBAString1 = qString1.toLocal8Bit(); 
    char * local8bit_c_str1 = local8bitBAString1.data(); 
    qDebug().nospace().noquote() << "local8bit_c_str1[" << local8bit_c_str1 << "]"; // local8bit_c_str1[French] 
    my_c_func(local8bit_c_str1); 

    // Solution 1.3: to UTF8 QByteArray, followed by data() in 2 steps: 
    QByteArray utf8BAString1 = qString1.toUtf8(); 
    char * utf8_c_str1 = utf8BAString1.data(); 
    qDebug().nospace().noquote() << "utf8_c_str1[" << utf8_c_str1 << "]"; // utf8_c_str1[French] 
    my_c_func(utf8_c_str1); 

    // !!! Try: Solution 1.4: to std::string , followed by c_str() in 2 steps: 
    std::string stdString1 = qString1.toStdString(); 
    const char * stdstring_c_str1 = stdString1.c_str(); // "const" must be used ! 
    qDebug().nospace().noquote() << "stdstring_c_str1[" << stdstring_c_str1 << "]"; // stdstring_c_str1[French] 
    // invalid conversion from 'const char*' to 'char*': ---> NOT GOOD for use by a C-style function !!! 
    // my_c_func(stdstring_c_str1); 

    qDebug() << ""; 

    // Case 2: Non-ASCII characters 
    // ============================ 

    QString qString2 = "français"; 
    qDebug().nospace().noquote() << "qString2[" << qString2 << "]"; // qString2[français] 

    // !!! Try: Solution 2.1: to Latin1 QByteArray, followed by data() in 2 steps: 
    QByteArray latin1BAString2 = qString2.toLatin1(); 
    char * latin1_c_str2 = latin1BAString2.data(); 
    qDebug().nospace().noquote() << "latin1_c_str2[" << latin1_c_str2 << "]"; // latin1_c_str2[fran?ais] ---> NOT GOOD for non-ASCII characters !!! 
    my_c_func(latin1_c_str2); 

    // Solution 2.2: to Local 8-bit QByteArray, followed by data() in 2 steps: 
    QByteArray local8bitBAString2 = qString2.toLocal8Bit(); 
    char * local8bit_c_str2 = local8bitBAString2.data(); 
    qDebug().nospace().noquote() << "local8bit_c_str2[" << local8bit_c_str2 << "]"; // local8bit_c_str2[français] 
    my_c_func(local8bit_c_str2); 

    // Solution 2.3: to UTF8 QByteArray, followed by data() in 2 steps: 
    QByteArray utf8BAString2 = qString2.toUtf8(); 
    char * utf8_c_str2 = utf8BAString2.data(); 
    qDebug().nospace().noquote() << "utf8_c_str2[" << utf8_c_str2 << "]"; // utf8_c_str2[français] 
    my_c_func(utf8_c_str2); 

    // !!! Try: Solution 2.4: to std::string, followed by c_str() in 2 steps: 
    std::string stdString2 = qString2.toStdString(); 
    const char * stdstring_c_str2 = stdString2.c_str(); // "const" must be used ! 
    qDebug().nospace().noquote() << "stdstring_c_str2[" << stdstring_c_str2 << "]"; // stdstring_c_str2[français] 
    // invalid conversion from 'const char*' to 'char*': ---> NOT GOOD for use by a C-style function !!! 
    // my_c_func(stdstring_c_str2); 

    return a.exec(); 
} 

Powyższy kod został przetestowany przy użyciu Qt 5.4 for Linux.

Drugim przedmiotem zaangażowany w tej kwestii jest to, czy możemy funkcje łańcuchowe razem podczas tego 2-etapowego procesu konwersji:

<myQString>.to<AnotherClass>().<getCPointer>(); // OK or not?

myślę, że to zależy od „AnotherClass” oraz od rodzaju znaków do być przekonwertowanym. Na podstawie jakiejś dokumentacji QString, QByteArray i std :: string, wydaje się, że jest to bezpieczne, aby napisać:

<myQString>.toStdString().c_str(); // OK.

<myQString>.toUtf8().data(); // Should be OK as QString is Unicode string.

Ale należy unikać następujące linie:

<myQString>.toLocal8Bit().data(); // May crash if the converted QByteArray object is undefined !

<myQString>.toLatin1().data(); // May crash if the converted QByteArray object is undefined !

0

I u se to w moim kodzie cały czas

char * toCharP(QString in) 
{ 
    QByteArray a; a.append(in); 
    return a.data(); 
} 
+1

Jak stwierdzono w dokumentach, wskaźnik zwrócony przez dane() pozostaje ważny tak długo, jak długo tablica bajtów nie jest ponownie przydzielana lub niszczona. Twoja instancja QByteArray wykracza poza zakres, gdy tylko funkcja zwróci. – jpnurmi

Powiązane problemy