Why "cout" works weird for "unsigned char"? - c++

I have the following code:
cvtColor (image, image, CV_BGRA2RGB);
Vec3b bottomRGB;
bottomRGB=image.at<Vec3b>(821,1232);
When I display bottomRGB[0], it displays a value greater than 255. What is the reason for this?

As you have commented, the reason is that you use cout to print its content directly. Here I will try to explain to you why this will not work.
cout << bottomRGB[0] << endl;
Why "cout" works weird for "unsigned char"?
It will not work because here bottomRGB[0] is a unsigned char (with value 218), cout actually will print some garbage value (or nothing) as it is just a non-printable ASCII character which is getting printed anyway. Note that ASCII character corresponding to 218 is non-printable. Check out here for the ASCII table.
P.S. You can check whether bottomRGB[0] is printable or not using isprint() as:
cout << isprint(bottomRGB[0]) << endl; // will print garbage value or nothing
It will print 0 (or false) indicating the character is non-printable
For your example, to make it work, you need to type cast it first before cout:
cout << (int) bottomRGB[0] << endl; // correctly printed (218 for your example)

Related

How to print out ≠ to terminal using g++?

I want to print ≠ in the terminal. I tried
cout << '\u2248' << endl;
cout << '\U00002248' << endl;
cout << '≠' << endl;
which gives
14846344
14846344
14846368
I tried replacing the single quotes with double
Ôëê
Ôëê
Ôëá
How can it be done? I'm curious what the explanation for the output I'm getting is? I'm running Netbeans 9 but have tested directly from command line with g++ too. I think this should be possible because echo ≠ produces the correct output in the Windows command prompt.
So, in C++, like in plain C, by default we can work just with ASCII characters.
Char variables contains just 8 bits(1 byte) to store values so maximum - 2^8=256 different symbols can be coded by one char variable.
Single quotes (like 'a') are storing char variables so inside of them can be placed just ASCII-character. Your character is not a part of ASCII table and we need to change the encoding.
For just print(not store/process) your character, you should use another encoding such as UTF-8. You can do it programmatically:
std::setlocale(LC_ALL, /*some system-specific locale name, probably */ "en_US.UTF-8");
std::cout << "\u2260" << std::endl;
Or via command line options to g++ (such as -finput-charset=UTF-16).
As you can see, I'm using double quotes to print non-ASCII symbols to console.

How can I read accented characters in C++ and use them with isalnum?

I am programming in French and, because of that, I need to use accented characters. I can output them by using
#include <locale> and setlocale(LC_ALL, ""), but there seems to be a problem when I read accented characters. Here is simple example I made to show the problem :
#include <locale>
#include <iostream>
using namespace std;
const string SymbolsAllowed = "+-*/%";
int main()
{
setlocale(LC_ALL, ""); // makes accents printable
// Traduction : Please write a string with accented characters
// 'é' is shown correctly :
cout << "Veuillez écrire du texte accentué : ";
string accentedString;
getline(cin, accentedString);
// Accented char are not shown correctly :
cout << "Accented string written : " << accentedString << endl;
for (unsigned int i = 0; i < accentedString.length(); ++i)
{
char currentChar = accentedString.at(i);
// The program crashes while testing if currentChar is alphanumeric.
// (error image below) :
if (!isalnum(currentChar) && !strchr(SymbolsAllowed.c_str(), currentChar))
{
cout << endl << "Character not allowed : " << currentChar << endl;
system("pause");
return 1;
}
}
cout << endl << "No unauthorized characters were written." << endl;
system("pause");
return 0;
}
Here is an output example before the program crashes :
Veuillez écrire du texte accentué : éèàìù
Accented string written : ʾS.?—
I noticed the debugger from Visual Studio shows that I have written something different than what it outputs :
[0] -126 '‚' char
[1] -118 'Š' char
[2] -123 '…' char
[3] -115 '' char
[4] -105 '—' char
The error shown seems to tell that only characters between -1 and 255 can be used but, according to the ASCII table the value of the accented characters I used in the example above do not exceed this limit.
Here is a picture of the error dialog that pops up : Error message: Expression: c >= -1 && c <= 255
Can someone please tell me what I am doing wrong or give me a solution for this? Thank you in advance. :)
char is a signed type on your system (indeed, on many systems) so its range of values is -128 to 127. Characters whose codes are between 128 and 255 look like negative numbers if they are stored in a char, and that is actually what your debugger is telling you:
[0] -126 '‚' char
That's -126, not 126. In other words, 130 or 0x8C.
isalnum and friends take an int as an argument, which (as the error message indicates) is constrained to the values EOF (-1 on your system) and the range 0-255. -126 is not in this range. Hence the error. You could cast to unsigned char, or (probably better, if it works on Windows), use the two-argument std::isalnum in <locale>
For reasons which totally escape me, Windows seems to be providing console input in CP-437 but processing output in CP-1252. The high half of those two code pages is completely different. So when you type é, it gets sent to your program as 130 (0xC2) from CP-437, but when you send that same character back to the console, it gets printed according to CP-1252 as an (low) open single quote ‚ (which looks a lot like a comma, but isn't). So that's not going to work. You need to get input and output to be on the same code page.
I don't know a lot about Windows, but you can probably find some useful information in the MS docs. That page includes links to Windows-specific functions which set the input and output code pages.
Intriguingly, the accented characters in the source code of your program appear to be CP-1252, since they print correctly. If you decide to move away from code page 1252 -- for example, by adopting Unicode -- you'll have to fix your source code as well.
With the is* and to* functions, you really need to cast the input to unsigned char before passing it to the function:
if (!isalnum((unsigned char)currentChar) && !strchr(SymbolsAllowed.c_str(), currentChar)) {
While you're at it, I'd advise against using strchr as well, and switch to something like this:
std::string SymbolsAllowed = "+-*/%";
if (... && SymbolsAllowed.find(currentChar) == std::string::npos)
While you're at it, you should probably forget that you ever even heard of the exit function. You should never use it in C++. In the case here (exiting from main) you should just return. Otherwise, throw an exception (and if you want to exit the program, catch the exception in main and return from there).
If I were writing this, I'd do the job somewhat differently in general though. std::string already has a function to do most of what your loop is trying to accomplish, so I'd set up symbolsAllowed to include all the symbols you want to allow, then just do a search for anything it doesn't contain:
// Add all the authorized characters to the string:
for (unsigned char a = 0; a < std::numeric_limits<unsigned char>::max(); a++)
if (isalnum(a) || isspace(a)) // you probably want to allow spaces?
symbolsAllowed += a;
// ...
auto pos = accentedString.find_first_not_of(symbolsAllowed);
if (pos != std::string::npos) {
std::cout << "Character not allowed: " << accentedString[pos];
return 1;
}

Space vs null character

In C++, when we need to print a single space, we may do the following:
cout << ' ';
Or we can even use a converted ASCII code for space:
cout << static_cast<char>(32); //ASCII code 32 maps to a single space
I realized that, printing a null character will also cause a single space to be printed.
cout << static_cast<char>(0); //ASCII code 0 maps to a null character
So my question is: Is it universal to all C++ compilers that when I print static_cast<char>(0), it will always appear as a single space in the display?
If it is universal, does it applies to text files when I use file output stream?
No, it will be a zero(0) character in every compiler. Seems that the font you use renders zero characters as a space. For example, in the old times, DOS had a different image (an almost filled rectangle) for zero characters.
Anyway, you really should not output zero characters instead of spaces!
As for the text file part: open the outputted file using a hex editor to see the actual bits written. You will see the difference there!
On my computer, this code
#include <iostream>
int main() {
std::cout << "Hello" << static_cast<char>(0) << "world\n";
}
outputs this:
Helloworld
So no, it clearly doesn’t work.

Using '\n' instead of endl affects output, why?

So I made an uninitialized array in C++ and tried printing the last element to see what the output would be. Every element in an uninitialized array should have the value of 0 (right?), but the output I got was something else. This is what the main function looked like:
int main() {
int i[5];
cout << i[4] << '\n';
}
Running this outputs 1606416656 (same number every time) with a line break. However, changing '\n' to endl changes the output to 0 with a line break.
Why is that?
Also, trying to print i[3] instead of i[4] correctly outputs 0 even with '\n'. Why?
I did some research and read somewhere that '\n' doesn't "flush the buffer" while endl does. What does this "flushing the stream" actually mean, and is this what's affecting the output?
Every element in an uninitialized array should have the value of 0 (right?)
No, they have an indeterminate value. Using the values gives undefined behaviour, which is why you get unpredictable output.
What does this "flushing the stream" actually mean, and is this what's affecting the output?
When you write to the stream, the output is stored in a memory buffer, and not necessarily sent to the final destination (the console, or a file, or whatever) straight away; this can give a large performance benefit, but can also mean that you don't see the final output when you want to. Flushing the stream pushes the data you've written to the final destination.
Your assumption that an newly created array on the stack is initialized with zero does not hold. Therefore your output is random. Changing the program reorders the memory layout and so you see different results.
int main() {
int i[5];
for (int k = 0; k < 5; ++k)
i[k] = 0;
cout << i[4] << '\n';
}
should give you always the expected result regardless of using '\n' or endl
Your array remains uninitalized. Whatever value you get is coincidental. std::endl puts newline character and flushes the output stream buffer. That is the difference of std::endl manipulator and printing just a newline character.

Datas from a char array well displayed while iterating to display byte by byte but not otherwise

I have a problem that I don't understand in C++:
I got a unsigned char* as a result from a method call. if I iterate the char* to display the datas everything is fine, but when I just print the datas there are not the same values displayed.
Here is my code sample:
unsigned char returning[32];
for(int i=0;i<32;i++){
returning[i] = result[i];
std::cout << returning[i];//return the good values
}
std::cout << "\n";
std::cout << returning << "\n";
//the first one are the good values, and then there are wrong
Someone could explain me this strange behavior?
tl;dr:
unsigned char returning[33];
returning[32] = '\0';
fixed.
Explanation:
The first loop will print every value in "returning". The second piece of code will only return the values until it hits a value which is zero. And then it stops, because a zero in a char array is interpreted as an end of line character.
Alternatively, if the there is no zero in "returning" anywhere, the second piece of code will continue to write random values until it does hit a zero.
First of all in returning array, you are just assigning values till 31st index which is wrong. Last byte of that should be null terminated \0.
std::cout << returning[i] This statement will read the ASCII value from that particular and it will print the corresponding character.
std::cout << returning But this statement will keep on reading bytes till it reaches \0. In your case returning array is not NULL terminated. So in this buffer overflow will happen and it will print first 32 byte proper characters and then it will start printing some other characters(may be not readable formal also). If \0 never comes in the further bytes then it will surely tries to go beyond that segment at that time application will crash.