printf to show QString - c++

I'm debugging a program using QString.
I added printf to show contents of QString but it only shows 1st letter.
Code is as below. fprintf is what I added.
QString profilePath = mltPath;
fprintf(stderr, "profilePath: %s\n", profilePath.data());
Output is
profilePath: /

profilePath.data() is a QChar* which is a 16 bit unicode character. https://doc.qt.io/qt-5/qchar.html
One solution to convert to a const char* is to this is to use qPrintable(profilePath) to convert the QString to const char*
QString profilePath = mltPath;
fprintf(stderr, "profilePath: %s\n", qPrintable(profilePath));
The documentation for const char * qPrintable(const QString& str) is here: https://doc.qt.io/qt-5/qtglobal.html#qPrintable

Just use QString::toUtf8(), e.g.
fprintf(stderr, "profilePath: %s\n", profilePath.toUtf8());
You shouldn't use printf as it is mostly used in C (or well should be).
Since you are working with Qt, why not use QDebug?
Then all you have to do is call: qDebug() << "profilePath:" << profilePath;
If you use QDebug, you also gain the advantage of categorized logging.

It seems you can use the toLocal8Bit() method to convert it to a QByteArray with your local encoding on your system (documentation).
So you would want this in your code:
QString profilePath = mltPath;
fprintf(stderr, "profilePath: %s\n", profilePath.toLocal8Bit().constData());

Related

How to send string in utf-8 to irc server?

I have an irc bot written in c++ with the use of Qt library. I store console text input in std::string , and then i'm using QSocket to post it on irc chat. But the problem is im want to use special signs (polish letters), which dont appear properly on chat. What is the problem?
The way i use QSocketis:
void Socket::poster(const QByteArray send)
{
mSocket->write(send);
mSocket->flush();
mSocket->reset();
}
QByteArray i create from std::string and std::cin
he code's long so i only post the parts crucial for the specific functonality which fails
Socket class (which is the main class in the program, providing data to other classes):
#############################################################
protected:
QSslSocket *mSocket;
--------------------
connect(mSocket, SIGNAL(readyRead()),
this, SLOT(readyReady())
--------------------
//console input:
QThread *thread = new QThread;
consoleInput = new ConsoleInput();
consoleInput->startConsole(thread, mSocket);
consoleInput->moveToThread(thread);
thread->start();
-------------------
void Socket::readyReady()
{
QString data;
data2 = data;
mSocket->ReadOnly;
while(mSocket->canReadLine())
{
data = mSocket->readLine();
}
mSocket->reset();
}
---------------------
void Socket::poster(const QByteArray send) //sending to irc from many classes news, console itd
{
mSocket->write(send);
mSocket->flush();
mSocket->reset();
}
-------------------
ConsoleInput class (which takes console input, which is later sent to irc chat):
###############################
void ConsoleInput::run()
{
std::cout << "!ConsoleInput::run()" << "\n";
while(1){
std::string input;
std::getline(std::cin, input);
determineOption(input);
if(input[0] != '/' || input[0] != '\\')
postInput(input);
input.clear();
}
}
----------------------------------
void ConsoleInput::postInput(std::string &input)
{
if(input[0]=='/')
return; //this prevents bot poting "/command" to channel
std::string lineToPost;
std::cout << "!lineToPost - input " << input << "\n";
ColourManipulation c;
lineToPost = "PRIVMSG #grunge " + c.addColours(input) + "\r\n";
emit mySignal(QByteArray::fromStdString(lineToPost)); // problem
}
Make sure std::cin/cout can accept & show non-ascii characters
Check the code can accept & show non-ascii characters:
std::string input;
std::getline(std::cin, input);
std::cout << input;
If you don't have problems with non-ascii characters in console itself
You need:
Know in which encoding the data originally comes from console to std::string &input.
std::string type per se uses no encoding -- it will return the bytes
you put in it -
What encoding does std::string.c_str() use?.
Import the bytes into QString using necessary encoding convertion
Export the resulting QString to UTF-8 encoded QByteArray (QByteArray itself is just an array of bytes too).
Write the QByteArray to a socket.
You can write something like the following:
/*
From doc: QTextCodec::codecForLocale()
Returns a pointer to the codec most suitable for this locale.
The codec will be retrieved from ICU where that backend is in use,
otherwise it may be obtained from an OS-specific API.
In the latter case, the codec's name may be "System".
*/
QTextCodec *codec = QTextCodec::codecForLocale(); // In most cases, it is not UTF-8
// Or set the encoding explicitly:
//QTextCodec *codec = QTextCodec::codecForName("Shift-JIS"); // put your input encoding here
QTextDecoder *decoder = codec->makeDecoder();
QByteArray chunk = QByteArray::fromStdString(input);
QString string = decoder->toUnicode(chunk);
delete decoder;
emit mySignal(string.toUtf8());
Be note that you can avoid std::string and use QString only:
QString is more comfortable to use, and, once received the data correctly, it always stores data in the same known format internally, despite of std::string, which has no idea what data it stores.
How to read from console to QString directly:
QTextStream in(stdin);
in.setCodec(<your console codec>);
QString input = in.readLine();
See QTextCodec and QTextStream.
Read also The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

How to get datas send by Protobuf with a QTcpSocket [duplicate]

This question already has answers here:
Correct way to losslessly convert to and from std::string and QByteArray
(3 answers)
Closed 3 years ago.
I'm new on protobuf and QTcpServer/Socket and I want to read my .proto data send by my client, but when i'm reading the data, the QString done is empty
For now, I just want to send a message that say "hello" when my client is connected. The QByteArray returning by QTcpSocket::readAll is NOT empty, but the QString created with the bytes is empty.
Here is my .proto ultra basic one :
syntax = "proto3";
package protobuf;
message Message
{
string content = 2;
}
write functions :
// When i'm connecting to the server i create a PlayerManager and i call this function with message = "hello"
void Server::sendMessageToPlayer(const PlayerManager& playerManager, const QString& message)
{
auto messageProto = new protobuf::Message;
messageProto->set_content(message.toStdString());
playerManager.socketManager()->sendData(*messageProto);
}
// I serialize the protobuf
template <typename protobufType>
void sendData(const protobufType& protobuf)
{
std::string dataToSend;
if (!protobuf.SerializeToString(&dataToSend))
{
// This never pass -> the protobuf is well serialize
qDebug() << "The protobuf send cannot be serialized, please, make sure that you used protobufs correctly";
}
// Before i write it
write(dataToSend);
}
void SocketManager::write(const std::string& data)
{
// I tried this but it's not working either
// QTextCodec* codec = QTextCodec::codecForName("CP1251");
// QString codecData = codec->toUnicode(data.c_str());
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_10);
out << data.c_str();
_tcpSocket->write(block);
qDebug() << block;
}
read functions :
void SocketManager::read()
{
QByteArray bytes = _tcpSocket->readAll();
qDebug() << bytes;
// Doesn't work either
// QTextCodec* codec = QTextCodec::codecForName("CP1251");
// QString data = codec->toUnicode(bytes);
QString data(bytes);
qDebug() << data;
emitMessageType(data.toStdString());
}
void SocketManager::emitMessageType(const std::string& data)
{
// Protobufs can parse an empty string (and so, emit signal), to avoid that, the function will tell you if data
// are empty, then return
if (data.empty())
{
qDebug() << "Datas are empty";
return;
}
protobuf::Message message;
if (message.ParseFromString(data))
{
emit messageProtoReceived(message);
return;
}
qDebug() << "The data send cannot be translate, please, make sure that you used protobufs correctly";
}
So, I would like that my client receive "hello" when he is connected but my debug are :
Server side :
"\x00\x00\x00\b\x12\x05hello\x00"
Client side
"\x00\x00\x00\b\x12\x05hello\x00"
""
Datas are empty
When I use QTextCodec (commented lines of the code) the debug are :
Server side :
"\x00\x00\x00\x0E\x00\x12\x00\x05\x00h\x00""e\x00l\x00l\x00o"
Client side
"\x00\x00\x00\x0E\x00\x12\x00\x05\x00h\x00""e\x00l\x00l\x00o"
"\u0000\u0000\u0000\u000E\u0000\u0012\u0000\u0005\u0000h\u0000e\u0000l\u0000l\u0000o"
The data send cannot be translate, please, make sure that you used protobufs correctly
So the QByteArea is parse, but protobuf don't succeed to parse the given string.
Thanks for reading, I hope youc ould help me
Not sure if it's the case but the documentation says that the default constructor of a QString that takes a QByteArray:
The given byte array is converted to Unicode using fromUtf8(). Stops copying at the first 0 character, otherwise copies the entire byte array.
So probably, you are having some troubles whit the conversion.
As alternative, you can try ParseFromArray method, instead of converting a QByteArray into a std::string.
const auto byteArray = _tcpSocket->readAll();
protobuf::Message message;
if (!message.ParseFromArray(byteArray.data(), byteArray.size())) {
qDebug() << "Failed to parse person.pb.";
}
out << data.c_str() inside SocketManager::write might discard at first \0. Try converting to QByteArray as described at Correct way to losslessly convert to and from std::string and QByteArray to ensure the whole string is sent.

how to call avformat_alloc_output_context2 in ffmpeg 2.6.3?

I'm developing an c/c++ app that uses ffmpeg to play audio/video.Now i want to enhance the application to allow the users to extract audio from video and save it. I followed this https://ffmpeg.org/doxygen/trunk/muxing_8c-source.html for the saving part but now the problem is with avformat_alloc_output_context2(). I'm getting an error: "undefined reference to `avformat_alloc_output_context2'
". Does anyone know about the proper way to call 'avformat_alloc_output_context2' in ffmpeg version 2.6.3
Remember to include
extern "C"
{
#include "libavformat/avformat.h"
}
After that you can just call
* #param *ctx is set to the created format context, or to NULL in
* case of failure
* #param oformat format to use for allocating the context, if NULL
* format_name and filename are used instead
* #param format_name the name of output format to use for allocating the
* context, if NULL filename is used instead
* #param filename the name of the filename to use for allocating the
* context, may be NULL
* #return >= 0 in case of success, a negative AVERROR code in case of
* failure
*/
int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename);
For example:
static const char* output_formats[] = { NULL, "mp3", "ogg", "wav" };
AVFormatContext* formatCtx = NULL;
QString outputFileName = "insert here your output file name";
avformat_alloc_output_context2(&formatCtx, NULL, output_formats[1], outputFileName.toStdString().c_str());
if(formatCtx == NULL)
{
//allocation have failed
}
Also git grep avformat_alloc_output_context2 in the in-source examples under doc/examples. A few matches:
https://github.com/FFmpeg/FFmpeg/blob/n3.0/doc/examples/remuxing.c#L79
https://github.com/FFmpeg/FFmpeg/blob/n3.0/doc/examples/muxing.c#L569
You can then see exactly how they are built with:
make V=1 examples
on the top-level. The build works on Ubuntu 15.10, so then you can compare it to your build and see what is wrong.

Call HPDF_SaveToFile() with japanese filename

Im trying to save one pdf in path that contains japanese username. In this case, HPDF_SaveToFile is doing crash my app on windows. Any options to compile or other thing? Any idea to support Unicode filenames with libhaur? I not want to create pdf with japanese encode, I want to write pdf with japanese filename.
A solution in Qt. If you use C++, you can use fstream/ofstream(::write). If you use C, you can use fwrite.
QFile file(path);
if (file.open(QIODevice::WriteOnly))
{
HPDF_SaveToStream(m_pdf);
/* get the data from the stream and write it to file. */
for (;;)
{
HPDF_BYTE buf[4096];
HPDF_UINT32 siz = 4096;
HPDF_STATUS ret = HPDF_ReadFromStream(m_pdf, buf, &siz);
if (siz == 0)
{
break;
}
if (-1 == file.write(reinterpret_cast<const char *>(buf), siz))
{
qDebug() << "Write PDF error";
break;
}
}
}
HPDF_Free(m_pdf);
Refrence: Libharu Usage examples

QFile::open fails with unicode filename

I want to open a file with QFile::Open where my file name is unicode:
QString fname(QFile::decodeName("D:/أحدالأنشطة.txt"));
QFile qFile(fname);
bool b=qFile.open(QIODevice::ReadOnly);
if(b)
{
FILE* filedesc = fdopen(qFile.handle(), "rb");
if(filedesc!=NULL)
{
char* nb=(char*)malloc(2*sizeof(char));
qDebug()<<"opened ";
size_t size=fread(nb,sizeof(char),2,filedesc);
fclose(filedesc);
qDebug()<<"filedesc closed size "<<size<<"nb "<<QString::fromAscii(nb,2);
nb=NULL;
free(nb);
}else qDebug()<<"filedesc failed error"<<strerror(errno);
}else
qDebug()<<"qFile failed error"<<strerror(errno);
It failed and I get:
qFile failed error No error
any help will be appreciated.
If the data is in WCHAR array than just use QString filename((QChar*) yourWcharData);
If your source file is UTF-8 encoded, then you might be able to do this:
QString fname(QString::fromUtf8("D:/أحدالأنشطة.txt"));
If it's UTF-16, then:
QString fname(QString::fromUtf16("D:/أحدالأنشطة.txt"));
If the source file is neither UTF-8 not UTF-16, try this instead:
QString fname(QString::fromLocal8Bit("D:/أحدالأنشطة.txt"));
If that also doesn't work, then you need to find out the character set your editor is using.