Chuyển đổi QString sang char *


94

Tôi đã cố gắng chuyển đổi QString thành kiểu char * bằng các phương pháp sau, nhưng chúng dường như không hoạt động.

//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());

Bạn có thể giải thích lỗ hổng có thể có với phương pháp này hoặc đưa ra một phương pháp thay thế?


Ví dụ của bạn hoạt động tốt cho tôi, vấn đề là ở đâu?
Viesturs

3
Xin lỗi vì tiếng Anh của tôi nhưng tại sao sử dụng cách tiếp cận như vậy là không đúng? QString s("some"); printf(reinterpret_cast<char *>(s.data()));
Bartolo-otrit

Câu trả lời:


114

Chà, Câu hỏi thường gặp Qt nói:

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

Vì vậy, có lẽ bạn đang gặp vấn đề khác. Làm thế nào chính xác là điều này không hoạt động?


11
const char*char*không cùng loại.
Lightness Races ở Orbit

3
@LightnessRacesinOrbit: ghi vào nội dung của QString mà không biết là một ý tưởng kinh khủng, do đó tất nhiên const char*là thứ thực sự có thể lấy được. Người dùng có thể tự do sao chép dữ liệu vào bộ đệm có thể ghi.
Eli Bendersky,

1
Tôi hoàn toàn đồng ý. Tuy nhiên, câu hỏi được hỏi về char*, không char const*, và câu trả lời của bạn chỉ đơn giản là bỏ qua thực tế đó mà không đề cập đến.
Các cuộc đua ánh sáng trong quỹ đạo vào

4
@LightnessRacesinOrbit: đôi khi câu trả lời tốt nhất là trả lời câu hỏi. Nói cách khác, để chỉ ra rằng nó không yêu cầu điều đúng đắn. Câu trả lời này đã được chấp nhận bởi các poster câu hỏi, vì vậy tôi cho rằng nó đạt được mục tiêu của mình
Eli Bendersky

2
Có vẻ như Câu hỏi thường gặp đã được cập nhật để sử dụng toLocal8Bit()?
Larry

52

Có lẽ

my_qstring.toStdString().c_str();

hoặc an toàn hơn, như Federico chỉ ra:

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

Nó không phải là tối ưu, nhưng sẽ làm việc.


3
Điều này sẽ làm rối các ký tự Unicode. Một Unicode thân thiện với giải pháp: stackoverflow.com/a/4644922/238387
jlstrecker

21
Phương pháp này rất nguy hiểm và không nên sử dụng: toStdString()trả về một std::stringđối tượng mới và sau đó con trỏ đến dữ liệu nội bộ const char *được lấy. Tuy nhiên, đối tượng chuỗi bị hủy ngay lập tức sau câu lệnh này, vì vậy con trỏ kết quả có thể không có địa chỉ hợp lệ nếu bạn sử dụng nó trong một câu lệnh tiếp theo.
RicoRico

@RicoRico Đây không phải là phương pháp toStdString()nguy hiểm; đó là việc sử dụng các con trỏ thô. Hoặc, cụ thể hơn, việc sử dụng các con trỏ thô từ các đối tượng mà phạm vi của chúng không được hiểu rõ.
notlesh

Cụ thể, các lệnh tạm thời trong C ++ thường tồn tại cho đến khi kết thúc câu lệnh tạo ra chúng. Vì vậy, dạng đầu tiên trong câu trả lời là ok nếu nó được sử dụng trong dòng trong một lệnh gọi hàm (giả sử hàm không lưu trữ con trỏ để sử dụng trong tương lai) nhưng sẽ không ổn nếu nó được gán cho một biến.
plugwash

46

Cách dễ nhất để chuyển đổi QString thành char *qPrintable (const QString & str) , là một macro mở rộng tới str.toLocal8Bit().constData().


Tại sao đây không phải là một câu trả lời phổ biến hơn? Tôi chỉ biết về điều này một cách tình cờ khi xem xét nguồn Qt, và đó chính xác là những gì họ làm.
Phlucious

6
@Phlucious, bởi vì: 1) qPrintabletrả về const char*không char*, str.toLocal8Bit().data()lợi nhuận char*. 2) Con trỏ để const char*trở nên không hợp lệ ngay sau khi bạn nhấn vào dấu chấm phẩy trong câu lệnh qPrintableđược sử dụng. Vì vậy, const char* c_ptr = s.toLocal8Bit().constData();không có bất kỳ ý nghĩa.
WindyFields 14/09/17

1
@Phlucious nhờ bạn chính là cuộc sống tiết kiệm :) những bài đầu câu trả lời bình chọn là sai, Câu hỏi là về char và họ đang quay trở lại const char *
user889030

Được qPrintableđầu ra đảm bảo được không chấm dứt?
Giovanni Cerretani

@WindyFields - Như đã cảnh báo trong phần qPrintable()mô tả: "Con trỏ char sẽ không hợp lệ sau câu lệnh mà qPrintable () được sử dụng."
Jeremy

6

Câu trả lời của David hoạt động tốt nếu bạn chỉ sử dụng nó để xuất ra tệp hoặc hiển thị trên màn hình, nhưng nếu một hàm hoặc thư viện yêu cầu ký tự * để phân tích cú pháp, thì phương pháp này hoạt động tốt nhất:

// 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);

4

ĐÃ CHỈNH SỬA

cách này cũng hoạt động

QString str ("Something");

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

Đó trông giống như một chuyển đổi khác ( std::stringQString), không phải là những gì được yêu cầu.
Toby Speight

3

Chuỗi của bạn có thể chứa các ký tự không phải Latin1, dẫn đến dữ liệu không xác định. Nó phụ thuộc vào những gì bạn có nghĩa là "nó dường như không hoạt động".


2

Giải pháp đúng Sẽ như thế này

   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<<"<---";

Quên sử dụng C.-style casting.
kyb

2

Nếu chuỗi của bạn chứa các ký tự không phải ASCII - tốt hơn nên làm theo cách này: s.toUtf8().data()(hoặc s->toUtf8().data())


0

Đó là một cách khả thi để sử dụng std :: vector làm vùng chứa trung gian:

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

0

Qt cung cấp API đơn giản nhất

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

Nếu bạn muốn sử dụng con trỏ dữ liệu không phải hằng số

str.toLocal8Bit().data() or str.toUtf8().data()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.