Чистый способ преобразования QString в char * (не const char*)

у меня есть уродливый код для этого материала (создайте указатель c char и скопируйте в него QString), но, возможно ... существует в QT элегантный способ ...

код :

QString maquina is a method parameter.

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

просто для информации мне нужен реальный char* не простой const char* так что этот код не работает:

idMaquina.toLatin1().data();

Я не могу использовать http://developer.qt.nokia.com/faq/answer/how_can_i_convert_a_qstring_to_char_and_vice_versa

7 ответов


это просто:

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

вы также можете использовать toLatin1 или toUtf8 вместо toLocal8Bit. Обратите внимание, что ни один из них не может быть поставлен в очередь с data звонок. И toStdString().c_str() также является недействительным. Это потому, что любой QByteArray или std::string произведенный таким образом временный и будет уничтожен немедленно уничтожая буфер char с ним. Вам нужно хранить QByteArray в локальной переменной во время использования буфера.

Также обратите внимание, что Qt предоставляет QByteArray класс для работы с char массивы. Как правило, нет необходимости использовать char*, вы можете сделать почти все с QByteArray.


Я думаю, что решение зависит от типа символов, которые будут преобразованы, и нужно ли интегрировать/вызывать функцию C-стиля с аргументами типа "char*".

  1. если функция c-стиля должна быть интегрирована / вызвана, не используйте toStdString (), за которым следует c_str (), так как тип возвращаемого значения-"const char*", который не подходит для функции C-стиля.
  2. используйте toLatin1 (), а затем data () для символов ASCII.
  3. используйте toLocal8Bit() или toUtf8 (), за которым следуют data() для других символов UTF8, чем ASCII.

если для вашего конкретного случая можно использовать несколько решений, их уровни эффективности могут немного отличаться, что я не тестировал.

следующая тестовая программа показывает, как использовать эти решения:

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

приведенный выше код был протестирован с использованием Qt 5.4 для Linux.

второй вопрос, связанный с этим вопросом, - Можем ли мы связывать функции вместе во время этого 2-шагового процесса преобразования:

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

Я думаю, что это зависит от" AnotherClass " и от типа символов, которые будут преобразованы. Основываясь на некоторой документации по QString, QByteArray и std:: string, кажется, что безопасно писать:

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

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

но следует избегать следующих строк:

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

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


QString:: toLatin1().data () дает вам const char*, потому что он дает вам свой внутренний буфер. Причина, по которой это const, заключается в том, что вы не должны его изменять.

поэтому, если вы хотите изменить его, вам нужно скопировать эти данные в какой-то другой буфер... например, тот, который вы только что выделили с помощью new ().


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

QByteArray содержит не const версию data(). Видеть: http://qt-project.org/doc/qt-5.0/qtcore/qbytearray.html#data


Я использую это в мой код

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

иногда просто нет способа сохранить ваш код в верхней красоте. Справиться с этим. Вы можете обернуть его в небольшую вспомогательную функцию, взяв QString в параметре и вернув char*, если вы действительно хотите.