9

I have an ugly code for this stuff (create a c char pointer and copy the QString in it) but maybe ... exist in QT an elegant way ...

actual code :

QString maquina is a method parameter.

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

just for information I need a REAL char* not a simple const char* so this code not work :

idMaquina.toLatin1().data();

I can't use http://developer.qt.nokia.com/faq/answer/how_can_i_convert_a_qstring_to_char_and_vice_versa

user833970
  • 2,729
  • 3
  • 26
  • 41
  • "I can't use link" -- why is that link not usable? You need to be clearer. Explain not only the problem with your direct plan (get a `char*` from a `QString`), but what led you to think you needed that. – Yakk - Adam Nevraumont Jul 30 '13 at 12:47
  • Yakk, i can´t use convert like explain in the link because it's a conversion beetween a QString and a char* (without posibility to overwrite the char*).i need a char* with posible overwrite, i hope a QString function for this... thx for your comment. – Gilles Grandguillaume Jul 30 '13 at 22:06
  • I still don't know why you cannot use the linked solution. Is the problem that the sample code uses `const char*` and not `char*`? `.data()` returns a `char*`. In addition, what do you hope to do with the writable `char*`? – Yakk - Adam Nevraumont Jul 30 '13 at 22:08
  • because my code call a c library and the response is empty when use a const char* or when use a .data() directly like the example of the link.i can't change the code of the library c (internal to the system of the client....) – Gilles Grandguillaume Jul 30 '13 at 22:15
  • and what does the C library do with the `char*`? Simply "getting a `char*`" won't answer your problem. Are you hoping to get data *out* of the C function? Does it have any way to know how *long* the data it is going to give you is? Please provide the signature of the function you are trying to call. – Yakk - Adam Nevraumont Jul 30 '13 at 23:01
  • sorry Yakk i not was very clear my question in reality it was just a problem of local variable ... sorry for your time. – Gilles Grandguillaume Aug 01 '13 at 23:56
  • possible duplicate of [Converting QString to char\*](http://stackoverflow.com/questions/5505221/converting-qstring-to-char) – bdesham Jun 02 '15 at 21:21

7 Answers7

37

This is simple:

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

You can also use toLatin1 or toUtf8 instead of toLocal8Bit. Note that neither of them can be queued with data call. And toStdString().c_str() is also invalid. This is because any QByteArray or std::string produced in such a way is temporary and will be destroyed immediately destroying char buffer with it. You need to store QByteArray in a local variable while you're using the buffer.

Also note that Qt provides QByteArray class to deal with char arrays. Generally there is no need to use char*, you can do almost anything with QByteArray.

Pavel Strakhov
  • 39,123
  • 5
  • 88
  • 127
  • I need to deal with a char* because i use a c library (requirement client ...), seem to not work with QByteArray.but i have noted than i can use a local QByteArray in my method. – Gilles Grandguillaume Jul 30 '13 at 22:12
  • you are right Riateche! i need always use a local QByteArray ! sorry im noob in c++ it's my first project ..... – Gilles Grandguillaume Aug 01 '13 at 23:52
  • So I am clear... The non-const pointer is writeable, and it changes the value of the data stored in the `QString` and `QVector`. Is that correct? (In C++ we simply take the address of the first element of a string or vector for the non-const pointer). – jww Dec 21 '19 at 20:39
1

I think the solution depends on the type of the characters to be converted, and whether a C-style function with "char *" type arguments needs to be integrated/called.

  1. If a C-style function needs to be integrated/called, do not use toStdString() followed by c_str(), as the return value type is "const char *" which is not suitable for a C-style function.
  2. Use toLatin1() followed by data() for ASCII characters.
  3. Use toLocal8Bit() or toUtf8() followed by data() for other UTF8 characters than ASCII ones.

If several solutions can be used for your specific case, their efficiency levels may be slightly different, which I have not tested.

The following test program shows how to use these 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();
}

The above code has been tested using Qt 5.4 for Linux.

A second subject involved in this question is whether we can chain functions together during this 2-step conversion process:

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

I think this depends on "AnotherClass" and on the type of characters to be converted. Based on some documentation on QString, QByteArray and std::string, it appears that it is safe to write:

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

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

But the following lines should be avoided:

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

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

jonathanzh
  • 1,346
  • 15
  • 21
1

I use this in my code all the time

char * toCharP(QString in)
{
    QByteArray a; a.append(in);
    return a.data();
}
  • 5
    As stated in the docs, the pointer returned by data() remains valid as long as the byte array isn't reallocated or destroyed. Your QByteArray instance goes out of scope as soon as the function returns. – jpnurmi Jul 09 '16 at 18:48
  • 2
    This is a dangerous solution. QByteArray a; is local to the function toCharP – Nikhil Augustine Jul 15 '21 at 13:25
0

QString::toLatin1().data() gives you a const char* because it gives you its internal buffer. The reason it's const is because you're not supposed to modify it.

So if you want to modify it, you have to copy that data to some other buffer... such as that one you just allocated using new().

inetknght
  • 4,300
  • 1
  • 26
  • 52
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
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

QByteArray contains a non const version of data(). See: http://qt-project.org/doc/qt-5.0/qtcore/qbytearray.html#data

fjardon
  • 7,921
  • 22
  • 31
-1

Sometimes, there's just no way to keep your code at top beauty. Deal with it. You might wrap it in a little helper function, taking QString in parameter and returning char*, if you really want.

Xirdus
  • 2,997
  • 6
  • 28
  • 36