我有一个丑陋的代码(创建一个c字符指针并复制其中的QString),但可能。。。以优雅的方式存在于QT。。。
实际代码:
QString maquina is a method parameter.
char *c_maquina = new char[maquina.length() + 1];
strcpy(c_maquina, maquina.toStdString().c_str());
仅供参考,我需要一个REAL字符*而不是一个简单的常量字符*,所以这个代码不起作用:
idMaquina.toLatin1().data();
我不能用http://developer.qt.nokia.com/faq/answer/how_can_i_convert_a_qstring_to_char_and_vice_versa
这很简单:
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
几乎可以做任何事情。
我认为解决方案取决于要转换的字符的类型,以及是否需要集成/调用具有"char*"类型参数的C样式函数。
- 如果需要集成/调用C样式函数,请不要使用toStdString()和C_str(),因为返回值类型为"const-char*",这不适合C样式函数
- 对于ASCII字符,使用toLatin1(),后跟data()
- 对于ASCII字符以外的其他UTF8字符,请使用toLocal8Bit()或toUtf8(),后跟data()
如果有几种解决方案可以用于您的特定情况,它们的效率水平可能略有不同,这是我没有测试过的。
以下测试程序展示了如何使用这些解决方案:
#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();
}
上面的代码已经使用Linux版的Qt 5.4进行了测试。
这个问题涉及的第二个主题是,在这个两步转换过程中,我们是否可以将函数链接在一起:
<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 !
我一直在代码中使用
char * toCharP(QString in)
{
QByteArray a; a.append(in);
return a.data();
}
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包含data()
的非常量版本。请参阅:http://qt-project.org/doc/qt-5.0/qtcore/qbytearray.html#data
有时候,没有办法让代码保持最佳状态。处理它。如果你真的想的话,你可以用一个小的helper函数来包装它,在参数中使用QString并返回char*。