#include <QCoreApplication>
#include <QByteArray>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray dataReceivedFromSerialPort;
dataReceivedFromSerialPort.push_back(0x0A);
dataReceivedFromSerialPort.push_back(0x0B);
dataReceivedFromSerialPort.push_back(0x0C);
dataReceivedFromSerialPort.push_back(0x0D);
dataReceivedFromSerialPort.push_back(0x0E);
dataReceivedFromSerialPort.push_back(0x0F);
dataReceivedFromSerialPort.push_back(0x07);
dataReceivedFromSerialPort.push_back(0x02);
dataReceivedFromSerialPort.push_back(0x01);
dataReceivedFromSerialPort.push_back(0x02);
qDebug() << "tostr: " << dataReceivedFromSerialPort.toStdString().c_str();
return a.exec();
}
The above does not print any value. It doesn't print anything beyond "tostr: ". If I store 0x0A in uchar and then push it in qByteArray then this problem disappears.
What can I do print it in its current form?
Because the bytes you give are, in many encodings, various control characters (newlines, carriage returns, etc.). Going through std::string and char* means the bytes will be sent as they are to the terminal, and thus displayed that way (either not at all, or as various types of whitespace).
You can try to instead do one of these, depending on what you want:
qDebug() << dataFromSerialPort; // prints "\n\x0B\f\r\x0E\x0F\x07\x02\x01\x02"
qDebug() << QString::fromLatin1(dataFromSerialPort); // prints "\n\u000B\f\r\u000E\u000F\u0007\u0002\u0001\u0002"
qDebug() << dataFromSerialPort.toHex(); // "0a0b0c0d0e0f07020102"
qDebug() << qPrintable(dataFromSerialPort); // same as toStdString().c_str(), but IMO more readable.
These print the bytes in various escape sequences (QString uses unicode, that's why you see \u instead of \x there), as a readable hexadecimal representation as well "as is".
QDebug does special formatting for many known types, like QString and QByteArray, that is why the first three examples above print with quotes and write out the escape sequences (it's for debugging after all). qPrintable, which works very similar to toStdString().c_str() returns a char*, which QDebug does not format in any special way, which is why you get whitespace as the output (this is the same behaviour as std::cout and friends).
Related
In a Qt 5.7 Console Application:
#include <QCoreApplication>
#include <QtDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString s = "MDJ\nTest.\n";
qDebug() << "MDJ\nTest.\n";
qDebug() << s;
/* Prints:
MDJ
Test.
MDJ\nTest.\n
*/
return a.exec();
}
i.e. the \n works as expected in a direct debug print, but is treated as just two plain characters when debug printing a (supposedly identical content) variable.
I'm encountering similar problems in Qt 5.7 Widget Applications as well.
I've searched the documentation, stackoverflow, and Qt Centre and I've been unable to discover what I'm doing wrong.
Could somebody please point me to a solution for this?
The docs give you hints:
<< QString()
Normally, QDebug prints the string inside quotes and transforms non-printable characters to their Unicode values (\u1234).
To print non-printable characters without transformation, enable the noquote() functionality. Note that some QDebug backends might not be 8-bit clean.
vs.
<< const char*
Writes the '\0'-terminated string, s, to the stream and returns a reference to the stream. The string is never quoted nor transformed to the output, but note that some QDebug backends might not be 8-bit clean.
Solution: qDebug().noquote() << "some\nspecial\nchars\n\tincluded"
I'm trying to print ASCII characters, but in the output I only see a little box. For example, ASCII 179 is a | character, but it doesn't print. Instead, it prints:
My code:
int main(int argc, char** argv) {
int a[] {179,180,191,192,193,194,195,196,197,217,218,32};
char b = a[2];
std::cout << b;
return 0;
}
How can I resolve this problem?
Note, when I use this code, the output prints the characters correctly:
std::cout << "┐"
But if I use the ASCII character, it prints a box instead.
Edit: To add... even when I output the characters to Notepad, I get the same result.
The problem seems to be an encoding issue. NetBeans by default, is not printing data with UTF-8 encoding.
Take a look at this tutorial to change NetBeans' default encoding.
I was trying to read a plain text file. In my case, I need to read line per line, and process that information. I know the C++ has wstuffs for reading wchars. I tried the following:
#include <fstream>
#include <iostream>
int main() {
std::wfstream file("file"); // aaaàaaa
std::wstring str;
std::getline(file, str);
std::wcout << str << std::endl; // aaa
}
But as you can see, it did not read a full line. It stops when reads "à", which is non-ASCII. How can I fix it?
You will need to understand some basic concepts of encodings. I recommend reading this article: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets. Basically you can't assume every byte is a letter and that every letter fits in a char. Also, the system must know how to extract letters from the sequence of bytes you have on the file.
Let's assume your file is encoded in UTF-8, this is likely given that you are on Linux. I'll assume your terminal also supports it. If you directly read using a std::string, with chars, you will have everything working. Look:
// olá
#include <iostream>
#include <fstream>
int main() {
std::fstream file("test.cpp");
std::string str;
std::getline(file, str);
std::cout << str << std::endl;
}
The output is what you expect, but this is not really correct. Look at what is going on: The file is encoded in utf-8. This means the first line is this byte sequence:
/ / o l á
47 47 32 111 108 195 161
Note that á is encoded with two bytes. If you ask the size of the string (str.size()), you will indeed get the wrong value: 7. This happens because the string thinks every byte is a char. When you send it to std::cout, the string will be given to the terminal to print. And the magical part: The terminal works with utf-8 by default. So it just assumes the string is utf-8 and correctly prints 6 chars.
You see that it works, but it is not really right. Try to make any string operation on the data and you may break the utf-8 encoding and will never be able to print it again!
Let's go for wstrings. They store each letter with a wchar_t that, on Linux, has 4 bytes. This is enough to hold any possible unicode character. But it will not work directly because C++ by default uses the "C" locale. A locale is a specification of how to deal with various aspects of the system, like "how to print a date" or "how to format a currency value" or even "how to decode text". The last factor is important and the default "C" encoding says: "Assume everything is ASCII". When it is reading the file and tries to decode a non-ASCII byte, it just fails silently.
The correction is simple: Use a UTF-8 locale. Look:
// olá
#include <iostream>
#include <fstream>
#include <locale>
int main() {
std::ios::sync_with_stdio(false);
std::locale loc("en_US.UTF-8"); // You can also use "" for the default system locale
std::wcout.imbue(loc); // Use it for output
std::wfstream file("test.cpp");
file.imbue(loc); // Use it for file input
std::wstring str;
std::getline(file, str); // str.size() will be 6
std::wcout << str << std::endl;
}
You may be asking what std::ios::sync_with_stdio(false); means. It is required because by default C++ streams are kept in sync with C streams. This is good because enables you to use both cout and printf on the same program. We have to disable it because C streams will break the utf-8 encoding and will produce garbage on the output.
Consider the following code snippet, compiled as a Console Application on MS Visual Studio 2010/2012 and executed on Win7:
#include "stdafx.h"
#include <iostream>
#include <string>
const std::wstring test = L"hello\xf021test!";
int _tmain(int argc, _TCHAR* argv[])
{
std::wcout << test << std::endl;
std::wcout << L"This doesn't print either" << std::endl;
return 0;
}
The first wcout statement outputs "hello" (instead of something like "hello?test!")
The second wcout statement outputs nothing.
It's as if 0xf021 (and other?) Unicode characters cause wcout to fail.
This particular Unicode character, 0xf021 (encoded as UTF-16), is part of the "Private Use Area" in the Basic Multilingual Plane. I've noticed that Windows Console applications do not have extensive support for Unicode characters, but typically each character is at least represented by a default character (e.g. "?"), even if there is no support for rendering a particular glyph.
What is causing the wcout stream to choke? Is there a way to reset it after it enters this state?
wcout, or to be precise, a wfilebuf instance it uses internally, converts wide characters to narrow characters, then writes those to the file (in your case, to stdout). The conversion is performed by the codecvt facet in the stream's locale; by default, that just does wctomb_s, converting to the system default ANSI codepage, aka CP_ACP.
Apparently, character '\xf021' is not representable in the default codepage configured on your system. So the conversion fails, and failbit is set in the stream. Once failbit is set, all subsequent calls fail immediately.
I do not know of any way to get wcout to successfully print arbitrary Unicode characters to console. wprintf works though, with a little tweak:
#include <fcntl.h>
#include <io.h>
#include <string>
const std::wstring test = L"hello\xf021test!";
int _tmain(int argc, _TCHAR* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(test.c_str());
return 0;
}
Setting the mode for stdout to _O_U16TEXT will allow you to write Unicode characters to the wcout stream as well as wprintf. (See Conventional wisdom is retarded, aka What the ##%&* is _O_U16TEXT?) This is the right way to make this work.
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L"hello\xf021test!" << std::endl;
std::wcout << L"\x043a\x043e\x0448\x043a\x0430 \x65e5\x672c\x56fd" << std::endl;
std::wcout << L"Now this prints!" << std::endl;
It shouldn't be necessary anymore but you can reset a stream that has entered an error state by calling clear:
if (std::wcout.fail())
{
std::wcout.clear();
}
How print format string passed as argument ?
example.cpp:
#include <iostream>
int main(int ac, char* av[])
{
printf(av[1],"anything");
return 0;
}
try:
example.exe "print this\non newline"
output is:
print this\non newline
instead I want:
print this
on newline
No, do not do that! That is a very severe vulnerability. You should never accept format strings as input. If you would like to print a newline whenever you see a "\n", a better approach would be:
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[])
{
if ( argc != 2 ){
std::cerr << "Exactly one parameter required!" << std::endl;
return 1;
}
int idx = 0;
const char* str = argv[1];
while ( str[idx] != '\0' ){
if ( (str[idx]=='\\') && (str[idx+1]=='n') ){
std::cout << std::endl;
idx+=2;
}else{
std::cout << str[idx];
idx++;
}
}
return 0;
}
Or, if you are including the Boost C++ Libraries in your project, you can use the boost::replace_all function to replace instances of "\\n" with "\n", as suggested by Pukku.
At least if I understand correctly, you question is really about converting the "\n" escape sequence into a new-line character. That happens at compile time, so if (for example) you enter the "\n" on the command line, it gets printed out as "\n" instead of being converted to a new-line character.
I wrote some code years ago to convert escape sequences when you want it done. Please don't pass it as the first argument to printf though. If you want to print a string entered by the user, use fputs, or the "%s" conversion format:
int main(int argc, char **argv) {
if (argc > 1)
printf("%s", translate(argv[1]));
return 0;
}
You can't do that because \n and the like are parsed by the C compiler. In the generated code, the actual numerical value is written.
What this means is that your input string will have to actually contain the character value 13 (or 10 or both) to be considered a new line because the C functions do not know how to handle these special characters since the C compiler does it for them.
Alternatively you can just replace every instance of \\n with \n in your string before sending it to printf.
passing user arguments directly to printf causes a exploit called "String format attack"
See Wikipedia and Much more details
There's no way to automatically have the string contain a newline. You'll have to do some kind of string replace on your own before you use the parameter.
It is only the compiler that converts \n etc to the actual ASCII character when it finds that sequence in a string.
If you want to do it for a string that you get from somewhere, you need to manipulate the string directly and replace the string "\n" with a CR/LF etc. etc.
If you do that, don't forget that "\\" becomes '\' too.
Please never ever use char* buffers in C++, there is a nice std::string class that's safer and more elegant.
I know the answer but is this thread is active ?
btw
you can try
example.exe "print this$(echo -e "\n ")on newline".
I tried and executed
Regards,
Shahid nx