web-dev-qa-db-fra.com

Manière propre de convertir QString en char * (non const char * !!!!)

J'ai un code moche pour ce genre de choses (créer un pointeur de char c et y copier la chaîne QString), mais peut-être ... existe-t-il dans QT de manière élégante ...

code actuel:

QString maquina is a method parameter.

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

juste pour information, j'ai besoin d'un vrai caractère * et non d'un simple caractère constant *, donc ce code ne fonctionne pas:

idMaquina.toLatin1().data();

Je ne peux pas utiliser http://developer.qt.nokia.com/faq/answer/how_can_i_convert_a_qstring_to_char_and_vice_versa

7

C'est simple:

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

Vous pouvez également utiliser toLatin1 ou toUtf8 au lieu de toLocal8Bit. Notez qu'aucun d'entre eux ne peut être mis en file d'attente avec l'appel data. Et toStdString().c_str() est également invalide. En effet, toute QByteArray ou std::string produite de cette manière est temporaire et sera détruite immédiatement en détruisant le tampon de char avec ce dernier. Vous devez stocker QByteArray dans une variable locale lorsque vous utilisez le tampon.

Notez également que Qt fournit la classe QByteArray pour traiter les tableaux de caractères. En règle générale, il n'est pas nécessaire d'utiliser char*, vous pouvez presque tout faire avec QByteArray.

28
Pavel Strakhov

Je pense que la solution dépend du type de caractères à convertir et de la question de savoir si une fonction de style C avec des arguments de type "char *" doit être intégrée/appelée.

  1. Si une fonction de style C doit être intégrée/appelée, n'utilisez pas toStdString () suivie de c_str (), car le type de valeur de retour est "const char *", ce qui ne convient pas à une fonction de style C.
  2. Utilisez toLatin1 () suivi de data () pour ASCII caractères.
  3. Utilisez toLocal8Bit () ou toUtf8 () suivi de data () pour les caractères UTF8 autres que ASCII.

Si plusieurs solutions peuvent être utilisées pour votre cas spécifique, leur efficacité peut être légèrement différente, ce que je n’ai pas testé.

Le programme de test suivant montre comment utiliser ces solutions:

#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();
}

Le code ci-dessus a été testé avec Qt 5.4 pour Linux.

Un deuxième sujet abordé dans cette question est de savoir si nous pouvons chaîner des fonctions ensemble au cours de ce processus de conversion en deux étapes:

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

Je pense que cela dépend de "AnotherClass" et du type de caractères à convertir. Basé sur de la documentation sur QString, QByteArray et std :: string, il apparaît qu’il est sécuritaire d’écrire:

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

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

Mais les lignes suivantes doivent être évitées:

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

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

1
jonathanzh

Je l'utilise tout le temps dans mon code

char * toCharP(QString in)
{
    QByteArray a; a.append(in);
    return a.data();
}
0
Jacob Ramey
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

QString :: toLatin1 (). Data () vous donne un caractère constant * car il vous donne son tampon interne. C'est parce que vous n'êtes pas censé le modifier.

Donc, si vous voulez le modifier, vous devez copier ces données dans un autre tampon ... comme celui que vous venez d'allouer avec new ().

0
inetknght

QByteArray contient une version non constante de data(). Voir: http://qt-project.org/doc/qt-5.0/qtcore/qbytearray.html#data

0
fjardon