QString转char*转换

126

我尝试通过以下方法将一个QString转换为char*类型,但它们似乎都无法工作。

//QLineEdit *line=new QLineEdit();{just to describe what is line here}

QString temp=line->text();
char *str=(char *)malloc(10);
QByteArray ba=temp.toLatin1();
strcpy(str,ba.data());

能否详细说明这个方法可能存在的缺陷,或者提供一种替代方法?


你的示例对我来说没问题,问题出在哪里? - Viesturs
3
抱歉我的英文不好,但为什么使用这种方法是不正确的呢?QString s("some"); printf(reinterpret_cast<char *>(s.data())); - bartolo-otrit
10个回答

143

好的,Qt FAQ上说:

int main(int argc, char **argv)
{
 QApplication app(argc, argv);
  QString str1 = "Test";
  QByteArray ba = str1.toLocal8Bit();
  const char *c_str2 = ba.data();
  printf("str2: %s", c_str2);
  return app.exec();
}

那么也许你有其他问题。这个问题具体表现为什么?


12
const char*char* 不是同一种类型。 - Lightness Races in Orbit
6
@LightnessRacesinOrbit:在不告知 QString 的情况下修改其内容是一个糟糕的主意,因此当然只能获取 const char*。用户可以将数据复制到可写缓冲区中。 - Eli Bendersky
2
我完全同意。然而,问题是关于 char* 而不是 char const*,你的回答却完全忽视了这一点而没有提到。 - Lightness Races in Orbit
6
有时候最好的答案是取消问题。换句话说,指出这并不是正确的问题。这个回答被提问者接受了,所以我想它达到了目的。 - Eli Bendersky
2
似乎FAQ已更新为使用toLocal8Bit() - Larry
显示剩余6条评论

72
也许是这样的:

my_qstring.toStdString().c_str();

或者更安全的方式,如Federico所指出的:

std::string str = my_qstring.toStdString();
const char* p = str.c_str();

虽然远非最优,但可以完成工作。


3
这会破坏Unicode字符。一个支持Unicode的解决方案:https://dev59.com/BW855IYBdhLWcg3wp2R0#4644922 - jlstrecker
23
这种方法非常危险,不应该使用:toStdString()会返回一个新的std::string对象,然后获取内部数据的指针 const char *。但是,在此语句之后,字符串对象立即被销毁,因此如果您在后续语句中使用结果指针,则该指针可能没有有效地址。 - ocirocir
1
@RicoRico,危险的不是toStdString()方法,而是使用裸指针。更具体地说,是从作用域不明确的对象中使用裸指针。 - notlesh
2
具体来说,C++ 临时对象通常会一直存在到创建它们的语句结束。因此,在函数调用中内联使用第一种形式是可以的(假设该函数不会将指针存储以供将来使用),但如果将其分配给变量,则不可以。 - plugwash
正如@plugwash所说,f(qstr.toStdString().c_str())从临时生命周期的角度来看是可以的(在f结束之前扩展)。但是,a.b的求值顺序仅从C++17开始保证为ab之前。我猜大多数实现实际上已经是这样工作了,但严格来说,在C++17之前可能是未定义行为。 - ricab

69

1
为什么这不是更受欢迎的答案?我是在浏览Qt源代码时偶然发现了这个方法,而他们正是这样做的。 - Phlucious
6
@Phlucious, еҺҹеӣ еҰӮдёӢпјҡ
  1. qPrintable иҝ”еӣһзҡ„жҳҜ const char* иҖҢдёҚжҳҜ char*пјҢиҖҢ str.toLocal8Bit().data() иҝ”еӣһзҡ„жҳҜ char*гҖӮ
  2. жҢҮеҗ‘ const char* зҡ„жҢҮй’ҲеңЁдҪҝз”Ё qPrintable зҡ„иҜӯеҸҘдёӯйҒҮеҲ°еҲҶеҸ·ж—¶е°ұдјҡеӨұж•ҲгҖӮжүҖд»Ҙ const char* c_ptr = s.toLocal8Bit().constData(); жҳҜжІЎжңүж„Ҹд№үзҡ„гҖӮ
- WindyFields
1
@Phlucious 谢谢你,你是救星 :) 所有得票最高的答案都是错的,问题是关于 char 的,而他们返回的是 const char*。 - user889030
qPrintable 的输出是否保证以零结尾? - Giovanni Cerretani
@WindyFields - 如qPrintable()描述中所警告的那样:“在使用qPrintable()的语句之后,char指针将无效。” - Jeremy

10

编辑

这种方法也可以起作用

QString str ("Something");

char* ch = str.toStdString().c_str();

那看起来像是一种不同的转换(std::stringQString),而不是所要求的。 - Toby Speight

8

如果您只需要将内容输出到文件或显示在屏幕上,那么David的答案是可行的。但是,如果一个函数或库需要char*进行解析,那么以下方法最好:

// copy QString to char*
QString filename = "C:\dev\file.xml";
char* cstr;
string fname = filename.toStdString();
cstr = new char [fname.size()+1];
strcpy( cstr, fname.c_str() );

// function that requires a char* parameter
parseXML(cstr);

5

Qt提供了最简单的API

const char *qPrintable(const QString &str)
const char *qUtf8Printable(const QString &str)

如果您想使用非常量数据指针,请使用:
str.toLocal8Bit().data()
str.toUtf8().data()

4

您的字符串可能包含非Latin1字符,这会导致数据未定义。这取决于您所说的“它似乎不起作用”的含义。


4
如果你的字符串包含非ASCII字符,最好这样做:s.toUtf8().data()(或s->toUtf8().data())。

2
正确的解决方案应该是这样的。
   QString k;
   k = "CRAZYYYQT";
   char ab[16];
   sprintf(ab,"%s",(const char *)((QByteArray)(k.toLatin1()).data()) );
   sprintf(ab,"%s",(const char *)((QByteArray)(k.toStdString()).data()));  
   sprintf(ab,"%s",(const char *)k.toStdString().c_str()  );
   qDebug()<<"--->"<<ab<<"<---";

忘记使用C风格的强制类型转换。 - kyb

1

使用std::vector作为中间容器是一种可行的方法:

QString dataSrc("FooBar");
QString databa = dataSrc.toUtf8();
std::vector<char> data(databa.begin(), databa.end());
char* pDataChar = data.data();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接