การแปลง QString เป็นถ่าน *


99

ฉันพยายามแปลง 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

คำตอบ:


118

ดีQt คำถามที่พบบ่อยพูดว่า:

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

บางทีคุณอาจมีปัญหาอื่น ๆ วิธีนี้ไม่ได้ผล?


11
const char*และchar*ไม่ใช่ประเภทเดียวกัน
Lightness Races ใน Orbit

3
@LightnessRacesinOrbit: การเขียนถึงเนื้อหาของ QString โดยไม่รู้ตัวเป็นความคิดที่น่ากลัวดังนั้นแน่นอนว่าconst char*เป็นสิ่งที่ได้ ผู้ใช้มีอิสระในการคัดลอกข้อมูลไปยังบัฟเฟอร์ที่เขียนได้
Eli Bendersky

1
ฉันเห็นด้วยอย่างยิ่ง อย่างไรก็ตามคำถามที่ถามchar*ไม่ใช่char const*และคำตอบของคุณก็เพิกเฉยต่อข้อเท็จจริงนั้นโดยไม่ต้องพูดถึง
Lightness Races ใน Orbit

4
@LightnessRacesinOrbit: บางครั้งคำตอบที่ดีที่สุดคือการเปิดคำถาม กล่าวอีกนัยหนึ่งเพื่อชี้ให้เห็นว่ามันไม่ได้ขอสิ่งที่ถูกต้อง คำตอบนี้ได้รับการยอมรับจากผู้โพสต์คำถามดังนั้นฉันคิดว่ามันบรรลุเป้าหมาย
Eli Bendersky

2
ดูเหมือนว่า FAQ ได้รับการอัปเดตเพื่อใช้งานtoLocal8Bit()?
Larry

53

อาจจะ

my_qstring.toStdString().c_str();

หรือปลอดภัยกว่าตามที่ Federico ชี้ให้เห็น:

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

มันห่างไกลจากความเหมาะสม แต่จะทำงาน


3
สิ่งนี้จะทำให้อักขระ Unicode เลอะ โซลูชันที่เป็นมิตรกับ Unicode: stackoverflow.com/a/4644922/238387
jlstrecker

21
วิธีนี้เป็นวิธีที่อันตรายมากและไม่ควรนำมาใช้: toStdString()กลับมาใหม่std::stringวัตถุแล้วชี้ไปยังข้อมูลภายในที่const char *จะได้รับ อย่างไรก็ตามอ็อบเจ็กต์สตริงจะถูกทำลายทันทีหลังจากคำสั่งนี้ดังนั้นตัวชี้ผลลัพธ์อาจไม่มีแอดเดรสที่ถูกต้องหากคุณใช้ในคำสั่งที่ตามมา
RicoRico

@RicoRico ไม่ใช่วิธีการtoStdString()ที่อันตราย เป็นการใช้ตัวชี้ดิบ หรือโดยเฉพาะอย่างยิ่งการใช้ตัวชี้ดิบจากวัตถุที่ขอบเขตไม่เข้าใจดี
notlesh

โดยเฉพาะจังหวะไลบรารีของ C ++ โดยปกติจะอยู่จนถึงจุดสิ้นสุดของคำสั่งที่สร้างขึ้น ดังนั้นรูปแบบแรกในคำตอบก็ใช้ได้ถ้าใช้แบบอินไลน์ในการเรียกใช้ฟังก์ชัน (สมมติว่าฟังก์ชันไม่ได้เก็บตัวชี้ไว้เพื่อใช้ในอนาคต) แต่จะไม่เป็นไรหากกำหนดให้กับตัวแปร
plugwash

46

วิธีที่ง่ายที่สุดในการแปลงQStringเป็นchar *คือqPrintable (const QString & str)ซึ่งเป็นมาโครที่ขยายเป็นstr.toLocal8Bit().constData()ไฟล์.


เหตุใดจึงไม่เป็นคำตอบยอดนิยม ฉันเพิ่งเรียนรู้เรื่องนี้โดยบังเอิญในขณะที่จิ้มหาแหล่งที่มาของ 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 ขอบคุณที่ช่วยชีวิต :) คำตอบที่ได้รับการโหวตสูงสุดเหล่านี้ผิดคำถามเกี่ยวกับถ่านและพวกเขากำลังส่งคืน const char *
user889030

มีการqPrintableรับประกันว่าเอาต์พุตเป็นศูนย์หรือไม่
Giovanni Cerretani

@WindyFields - ตามคำเตือนในqPrintable()คำอธิบาย: "ตัวชี้ถ่านจะไม่ถูกต้องหลังจากคำสั่งที่ใช้ qPrintable ()"
Jeremy

6

คำตอบของ David ใช้งานได้ดีหากคุณใช้เพียงเพื่อส่งออกไปยังไฟล์หรือแสดงบนหน้าจอ แต่ถ้าฟังก์ชันหรือไลบรารีต้องการถ่าน * สำหรับการแยกวิเคราะห์วิธีนี้จะได้ผลดีที่สุด:

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

แก้ไข

วิธีนี้ก็ใช้ได้เช่นกัน

QString str ("Something");

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

ดูเหมือนว่าจะเป็นการแปลงที่แตกต่างกัน ( std::stringQString) ไม่ใช่สิ่งที่ขอ
Toby Speight

3

สตริงของคุณอาจมีอักขระที่ไม่ใช่ Latin1 ซึ่งนำไปสู่ข้อมูลที่ไม่ได้กำหนด มันขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "มันดูเหมือนจะไม่ทำงาน"


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

ลืมใช้หล่อแบบซี
kyb

2

หากสตริงของคุณมีอักขระที่ไม่ใช่ ASCII คุณควรทำเช่นนี้: s.toUtf8().data()(หรือs->toUtf8().data())


0

เป็นวิธีที่ใช้งานได้ในการใช้ std :: vector เป็นคอนเทนเนอร์ระดับกลาง:

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

0

Qt ให้ API ที่ง่ายที่สุด

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

หากคุณต้องการใช้ตัวชี้ข้อมูลที่ไม่ใช่ const

str.toLocal8Bit().data()
str.toUtf8().data()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.