C++ Printing special ascii characters to the Windows console - c++

After 2 hours of searching and trying various methods, I'm pulling my hair out trying to print special ascii characters to the console! (C++)
typedef unsigned char UCHAR;
int main()
{
UCHAR c = '¥';
cout << c;
return 0;
}
Why does this code print Ñ (209) instead of ¥ (165)???
I've tried:
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
but neither seems to do anything, no matter which values I pass to it.
Someone else suggested that the console's font needed to be changed through the registry. But that's ridiculous. I don't want my end users to have to start changing registry values simply to run my program...
the really odd thing is that if I print all the ascii characters to a file (using ofstream), they show up correctly both in notepad, and the visual studio editor (2012 professional).
ofstream file("ASCII.txt");;
if (file.is_open())
{
UCHAR c = 0;
for (int i = 0; i < 256; i++)
{
c++;
file << c << "\t|\t" << (int)c << endl;
}
}
file.close();
Any help is much appreciated.
Thanks!

Welcome to the pain of encoding :(
#include <iostream>
#include <windows>
int main() {
SetConsoleCP(437);
SetConsoleOutputCP(437);
std::cout << (char)157 << "\n";
}
Generates:
The problem is that your source file is not in CP437 and therefore the character has a different value than the one you are trying to print (as you noted, in your source value is is 165 which is a different character in CP437).
https://en.wikipedia.org/wiki/Code_page_437

Related

How to load projects with encoding in Visual Studio 2022

I have to print some ASCII characters (extended version, code page 437) in console application as an exercise. Now, instead of writing cout << char(196) << char(196) << char(196);, I'd like to write cout << "───" to make a line. I have found that I can save files with the correct encoding by clicking "Save as" and choosing "save with encoding" (in this example - OER United States - Codepage 437). After doing that, the following code compiles and runs without any problems:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << "\n *** Multiplication Table ***\n\n";
for (int i = 1; i < 11; i++)
{
if (i == 2) cout << "────┼────────────────────────────────────\n";
for (int j = 1; j < 11; j++)
{
if (j == 2) cout << "│";
cout << setw(4) << i * j;
}
cout << "\n";
}
}
However, when I close Visual Studio and reopen the project, suddenly all special ASCII characters are changed. For example, this bit "────┼────────────────────────────────────\n"; becomes "ÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n"; in the code editor. However, the program still runs correctly and displays ────┼────────────────────────────────────.
If I try to save the project with encoding again, I am warned that there are characters that I cannot save with selected encoding and asked to use Unicode instead, which then messes up the characters again and also stops the program from showing the correct characters.
Question: How do I make Visual Studio 2022 use the correct encoding when opening projects?

Print (and store) high ASCII character (╔) in C++ in console

I'm making a small program in C++ and I would like to have this character stored in a variable: ╔. However, I can only do it in a string, and if I use the ' notation it just shows this: �.
Is there anything I can do?
BTW, I use:
Linux (Mint)
Visual Studio Code (integrated terminal)
The console shows the characters correctly if I use the " notation, so probably it's not a problem with the console itself.
You can use the hex notation:
char border = '\xcd';
Small program:
#include <iostream>
using std::cout;
using std::cin;
int main()
{
cout << "border: \xcd\n";
const char corner = '\xc9';
cout << "Upper left corner: " << corner << "\n";
cout << "Paused. Press ENTER to continue.\n";
cin.ignore(100000, '\n');
return 0;
}
There are many charts that show an extending ASCII encoding. Use the hexadecimal value for the character that you need.
Here's a chart from Wikipedia about DOS extended ASCII table.

Why do I obtain this strange character?

Why does my C++ program create the strange character shown below in the pictures? The picture on the left with the black background is from the terminal. The picture on the right with the white background is from the output file. Before, it was a "\v" now it changes to some sort of astrological symbol or symbol to denote males. 0_o This makes no sense to me. What am I missing? How can I have my program output just a backslash v?
Please see my code below:
// SplitActivitiesFoo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
string s = "foo:bar-this-is-more_text#\venus \"some more text here to read.\"";
vector<string> first_part;
fstream outfile;
outfile.open("out.foobar");
for (int i = 0; i < s.size(); ++i){
cout << "s[" << i << "]: " << s[i] << endl;
outfile << s[i] << endl;
}
return 0;
}
Also, assume that I do not want to modify my string 's' in this case. I want to be able to parse each character of the string and work around the strange character somehow.This is because in the actual program the string will be read in from a file and parsed then sent to another function. I guess I could figure out a way to programmatically add backslashes...
How can I have my program output just a backslash v?
If you want a backslash, then you need to escape it: "#\\venus".
This is required because a backslash denotes that the next character should be interpreted as something special (note that you were already using this when you wanted double-quotes). So the compiler has no way of knowing you actually wanted a backslash unless you tell it.
A literal backslash character therefore has the syntax \\. This is the case in both string literals ("\\") and character literals ('\\').
Why does my C++ program create the strange character shown below in the picture?
Your string contains the \v control character (vertical tab), and the way it's displayed is dependent on your terminal and font. It looks like your terminal is using symbols from the traditional MSDOS code page.
I found an image for you here, which shows exactly that symbol for the vertical tab (vt) entry at value 11 (0x0b):
Also, assume that I do not want to modify my string 's' in this case. I want to be able to parse each character of the string and work around the strange character somehow.
Well, I just saw you add the above part to your question. Now you're in difficult territory. Because your string literal does not actually contain the character v or any backslashes. It only appears that way in code. As already said, the compiler has interpreted those characters and substituted them for you.
If you insist on printing v instead of a vertical tab for some crazy reason that is hopefully not related to an XY Problem, then you can construct a lookup-table for every character and then replace undesirables with something else:
char lookup[256];
std::iota( lookup, lookup + 256, 0 ); // Using iota from <numeric>
lookup['\v'] = 'v';
for (int i = 0; i < s.size(); ++i)
{
cout << "s[" << i << "]: " << lookup[s[i]] << endl;
outfile << lookup[s[i]] << endl;
}
Now, this won't print the backslashes. To undo the string further check out std::iscntrl. It's locale-dependent, but you could utilise it. Or just something naive like:
const char *lookup[256] = { 0 };
s['\f'] = "\\f";
s['\n'] = "\\n";
s['\r'] = "\\r";
s['\t'] = "\\t";
s['\v'] = "\\v";
s['\"'] = "\\\"";
// Maybe add other controls such as 0x0E => "\\x0e" ...
for (int i = 0; i < s.size(); ++i)
{
const char * x = lookup[s[i]];
if( x ) {
cout << "s[" << i << "]: " << x << endl;
outfile << x << endl;
} else {
cout << "s[" << i << "]: " << s[i] << endl;
outfile << s[i] << endl;
}
}
Be aware there is no way to correctly reconstruct the escaped string as it originally appeared in code, because there are multiple ways to escape characters. Including ordinary characters.
Most likely the terminal that you are using cannot decipher the vertical space code "\v", thus printing something else. On my terminal it prints:
foo:bar-this-is-more_text#
enus "some more text here to read."
To print the "\v" change or code to:
String s = "foo:bar-this-is-more_text#\\venus \"some more text here to read.\"";
What am I missing? How can I have my program output just a backslash v?
You are escaping the letter v. To print backslash and v, escape the backslash.
That is, print double backslash and a v.
\\v

Trying to output everything inside an exe file

I'm trying to output the plaintext contents of this .exe file. It's got plaintext stuff in it like "Changing the code in this way will not affect the quality of the resulting optimized code." all the stuff microsoft puts into .exe files. When I run the following code I get the output of M Z E followed by a heart and a diamond. What am I doing wrong?
ifstream file;
char inputCharacter;
file.open("test.exe", ios::binary);
while ((inputCharacter = file.get()) != EOF)
{
cout << inputCharacter << "\n";
}
file.close();
I would use something like std::isprint to make sure the character is printable and not some weird control code before printing it.
Something like this:
#include <cctype>
#include <fstream>
#include <iostream>
int main()
{
std::ifstream file("test.exe", std::ios::binary);
char c;
while(file.get(c)) // don't loop on EOF
{
if(std::isprint(c)) // check if is printable
std::cout << c;
}
}
You have opened the stream in binary, which is good for the intended purpose. However you print every binary data as it is: some of thes characters are not printable, giving weird output.
Potential solutions:
If you want to print the content of an exe, you'll get more non-printable chars than printable ones. So one approach could be to print the hex value instead:
while ( file.get(inputCharacter ) )
{
cout << setw(2) << setfill('0') << hex << (int)(inputCharacter&0xff) << "\n";
}
Or you could use the debugger approach of displaying the hex value, and then display the char if it's printable or '.' if not:
while (file.get(inputCharacter)) {
cout << setw(2) << setfill('0') << hex << (int)(inputCharacter&0xff)<<" ";
if (isprint(inputCharacter & 0xff))
cout << inputCharacter << "\n";
else cout << ".\n";
}
Well, for the sake of ergonomy, if the exe file contains any real exe, you'd better opt for displaying several chars on each line ;-)
Binary file is a collection of bytes. Byte has a range of values 0..255. Printable characters that can be safely "printed" form a much narrower range. Assuming most basic ASCII encoding
32..63
64..95
96..126
plus, maybe, some higher than 128, if your codepage has them
see ascii table.
Every character that falls out of that range may, at least:
print out as invisible
print out as some weird trash
be in fact a control character that will change settings of your terminal
Some terminals support "end of text" character and will simply stop printing any text afterwards. Maybe you hit that.
I'd say, if you are interested only in text, then print only that printables and ignore others. Or, if you want everything, then maybe write them out in hex form instead?
This worked:
ifstream file;
char inputCharacter;
string Result;
file.open("test.exe", ios::binary);
while (file.get(inputCharacter))
{
if ((inputCharacter > 31) && (inputCharacter < 127))
Result += inputCharacter;
}
cout << Result << endl;
cout << "These are the ascii characters in the exe file" << endl;
file.close();

C++ Confusion. Reading Integer From Text File. Convert to ASCII

I am learning C++ for the first time. I have no previous programming background.
In the book I have I saw this example.
#include <iostream>
using::cout;
using::endl;
int main()
{
int x = 5;
char y = char(x);
cout << x << endl;
cout << y << endl;
return 0;
}
The example makes sense: print an integer and the ASCII representation of it.
Now, I created a text file with these values.
48
49
50
51
55
56
75
I am writing a program to read this text file -- "theFile.txt" -- and want to convert these numbers to the ASCII value.
Here is the code I wrote.
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
using std::ifstream;
int main()
{
ifstream thestream;
thestream.open("theFile.txt");
char thecharacter;
while (thestream.get(thecharacter))
{
int theinteger = int(thecharacter);
char thechar = char(theinteger);
cout << theinteger << "\t" << thechar << endl;
}
system ("PAUSE");
return 0;
}
This is my understanding about the second program shown.
The compiler does not know the exact data type that is contained in "theFile.txt". As a result, I need to specify it so I choose to read the data as a char.
I read the each digit in the file as a char and converted it to an integer value and stored it in "theinteger".
Since I have an integer in "theinteger" I want to print it out as a character but char thechar = char(theinteger); does not work as intended.
What am I doing incorrect?
You are reading char by char, but you really (I think) want to read each sequence of digits as an integer. Change your loop to:
int theinteger;
while (thestream >> theinteger )
{
char thechar = char(theinteger);
cout << thechar << endl;
}
+1 For a very nicely formatted & expressed first question, BTW!
You are reading one char at a time from the file. Hence, if your file contains:
2424
You will first read the char "2" from the file, convert it to an int, and then back to a char, which will print "2" on cout. Next round will print "4", and so on.
If you want to read the numbers as full numbers, you need to do something like:
int theinteger;
thestream >> theinteger;
cout << char(theinteger) << endl;