0

I have a simple program and I'm trying to write a sequence of hex values of byte patterns to a text file in the following format:

arbitrary data representation

3f 42 5c b8 d9 0a // etc...

Here is my program.

int main() {
    char digits[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b };

    std::fstream file;
    file.open("display.txt", std::ios::out);

    // Ones place
    for (int val = 0; val <= 255; val += 1)
        file << std::hex << digits[val % 10] << " ";
    file << std::endl;

    // Tens place
    for (int val = 0; val <= 255; val += 1)
        file << std::hex << digits[(val / 10) % 10] << " ";
    file << std::endl;

    // Hundreds place
    for (int val = 0; val <= 255; val += 1)
        file << std::hex << digits[(val / 100) % 10] << " ";
    file << std::endl;

    // Sign digit
    for (int val = 0; val <= 255; val += 1)
        file << std::hex << 0 << " ";
    file << std::endl;

    // Ones Place Twos Complement
    for (int val = -128; val <= 127; val += 1)
        file << std::hex << digits[abs(val) % 10] << " ";
    file << std::endl;

    // Tens Place Twos Complement
    for (int val = -128; val <= 127; val += 1)
        file << std::hex << digits[abs(val / 10) % 10] << " ";
    file << std::endl;

    // Hundreds Place Twos Complement
    for (int val = -128; val <= 127; val += 1)
        file << std::hex << digits[abs(val / 100) % 10] << " ";
    file << std::endl;

    // Sign Digit Twos Complement
    for (int val = -128; val <= 127; val += 1) {
        if (val < 0)
            file << std::hex << 01;
        else {
            file << std::hex << 00;
        }
        file << " ";
    }
    file << std::endl;

    file.close();

    return 0;
}

However, after I run the program and open my text file, it's showing up as if it's in binary... I'm not sure about what I'm doing wrong, what I'm missing, or overlooking.

Here's what my text file looks like:

⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛਍⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰⁹⁹⁹⁹⁹⁹⁹⁹⁹⁹″″″″″″″″″″⁛⁛⁛⁛⁛⁛⁛⁛⁛⁛          ⁰⁰⁰⁰⁰⁰⁰⁰⁰⁰ⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿ⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰⁹⁹⁹⁹⁹⁹⁹⁹⁹⁹″″″″″″″″″″⁛⁛⁛⁛⁛⁛⁛⁛⁛⁛          ⁰⁰⁰⁰⁰⁰⁰⁰⁰⁰ⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿ⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰⁹⁹⁹⁹⁹⁹⁹⁹⁹⁹″″″″″″″″″″⁛⁛⁛⁛⁛⁛਍⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰਍‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰਍ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾⁻ⁿ⁰ ⁛″⁹‰⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰ⁿ⁻⁾‰⁹″⁛ ⁰਍‰‰‰‰‰‰‰‰‰‰⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻ⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿ⁰⁰⁰⁰⁰⁰⁰⁰⁰⁰          ⁛⁛⁛⁛⁛⁛⁛⁛⁛⁛″″″″″″″″″″⁹⁹⁹⁹⁹⁹⁹⁹⁹⁹‰‰‰‰‰‰‰‰‰‰⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰⁹⁹⁹⁹⁹⁹⁹⁹⁹⁹″″″″″″″″″″⁛⁛⁛⁛⁛⁛⁛⁛⁛⁛          ⁰⁰⁰⁰⁰⁰⁰⁰⁰⁰ⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿ⁻⁻⁻⁻⁻⁻⁻⁻⁻⁻⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰਍‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾⁾‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰਍‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‱‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰਍

It's not even printing new lines from std::endl.

EDIT

I've been doing some testing; and I'm suspecting that it has to do with the array's type in combination with std::hex...

I'm getting this binary dump when using char, unsigned char, std::uint8_t, and std::int8_t however, if I use short, int, unsigned int, std::uint16_t, or std::int16_t it appears to be printing out the hex values...

When using integral types that are not of char type... I am getting this output:

7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 
7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 79 79 79 79 79 79 79 79 79 79 33 33 33 33 33 33 33 33 33 33 5b 5b 5b 5b 5b 5b 5b 5b 5b 5b 5f 5f 5f 5f 5f 5f 5f 5f 5f 5f 70 70 70 70 70 70 70 70 70 70 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7b 7b 7b 7b 7b 7b 7b 7b 7b 7b 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 79 79 79 79 79 79 79 79 79 79 33 33 33 33 33 33 33 33 33 33 5b 5b 5b 5b 5b 5b 5b 5b 5b 5b 5f 5f 5f 5f 5f 5f 5f 5f 5f 5f 70 70 70 70 70 70 70 70 70 70 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7b 7b 7b 7b 7b 7b 7b 7b 7b 7b 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 79 79 79 79 79 79 79 79 79 79 33 33 33 33 33 33 33 33 33 33 5b 5b 5b 5b 5b 5b 
7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 7b 7f 70 5f 5b 33 79 6d 30 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 7f 7b 7e 30 6d 79 33 5b 5f 70 
6d 6d 6d 6d 6d 6d 6d 6d 6d 30 30 30 30 30 30 30 30 30 30 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7b 7b 7b 7b 7b 7b 7b 7b 7b 7b 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 70 70 70 70 70 70 70 70 70 70 5f 5f 5f 5f 5f 5f 5f 5f 5f 5f 5b 5b 5b 5b 5b 5b 5b 5b 5b 5b 33 33 33 33 33 33 33 33 33 33 79 79 79 79 79 79 79 79 79 79 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 30 30 30 30 30 30 30 30 30 30 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 79 79 79 79 79 79 79 79 79 79 33 33 33 33 33 33 33 33 33 33 5b 5b 5b 5b 5b 5b 5b 5b 5b 5b 5f 5f 5f 5f 5f 5f 5f 5f 5f 5f 70 70 70 70 70 70 70 70 70 70 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7b 7b 7b 7b 7b 7b 7b 7b 7b 7b 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 6d 6d 6d 6d 6d 6d 6d 6d 
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 7e 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

I think this might solve my own problem, but I would still like to know why I was getting the output for using char types with std::hex...

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • "Character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<<." https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt – JohnFilleau Mar 07 '20 at 06:01
  • 1
    https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2 "After constructing and checking the sentry object, inserts the character ch." So calling `<<` on a `char` or `unsigned char` just outputs the `char` to the stream. The `basefield` (which `std::hex` modifies) is not consulted at all. – JohnFilleau Mar 07 '20 at 06:03
  • If you WANT to use the integer-like `ostream& <<` overload for types of `char` or `unsigned char`, you need to call it like `file.operator<<('c')` – JohnFilleau Mar 07 '20 at 06:03
  • @John that appears to make sense. Sometimes, it's the simple things that you forget about or overlook. I was shaking my head for almost a half hour on this one for something simple... Then it dawned on me to try the same program with different types... – Francis Cugler Mar 07 '20 at 06:04
  • 1
    I'm still scratching my own head as to why you get those non-ascii characters in the output. 0x7e is a `~`. First character should be a `~`. – JohnFilleau Mar 07 '20 at 06:05
  • Nah, it's not that important. I was going to use `char` because it is one byte in size... but I'm not over concerned with memory foot print. It's not an issue if I have to use `short` or `uint16_t`... as long as I get the correct values for output. – Francis Cugler Mar 07 '20 at 06:05
  • I think the method that gets the intent across the best would be to have the datatype be a `uint8_t[]`, and explicitly `static_cast(value)` in each `<<` operation. – JohnFilleau Mar 07 '20 at 06:07
  • I'm following along with Ben Eater's videos on building an 8 Bit breadboard computer. I'm at the point where he is using an Arduino to write byte sequences to an EEPROM for the byte codes to operate a array of four 7 Segment displays. I was taking his code from his github written in C and converting it to a simple C++ program to generate the same output in a simple text file. Then I can use that text file to populate a ROM module in Logisim. – Francis Cugler Mar 07 '20 at 06:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/209200/discussion-between-francis-cugler-and-john). – Francis Cugler Mar 07 '20 at 06:08
  • There is no such thing as a hexadecimal value. There are just values, and they are all ultimately binary. Hexadecimal is a *notation.* – user207421 Mar 07 '20 at 06:14
  • @John you just need `+` to print the char as int. `file << +digits[val % 10]`. It's pretty much [the only practical usage of the unary + operator](https://stackoverflow.com/a/14365849/995714) – phuclv Mar 07 '20 at 06:22
  • duplicates: [Why “cout” works weird for “unsigned char”?](https://stackoverflow.com/q/21374773/995714), [Why std::cout << char + int prints int value?](https://stackoverflow.com/q/40785687/995714), [std::cout deal with uint8_t as a character](https://stackoverflow.com/q/39145753/995714)... – phuclv Mar 07 '20 at 06:24
  • I had completely forgotten about `std::cout << char` and integer promotion. The simplest solution is adding the `+` operator before each of the `char []` in the output streams. – Francis Cugler Mar 07 '20 at 06:31

2 Answers2

1

This is a bug in Notepad.

The core of the problem is that your text file is getting misinterpreted by Notepad as UTF-16 instead of as ascii.

enter image description here

enter image description here

Notepad has an algorithm that attempts to infer what type of encoding a file uses. The actual Windows API it invokes is called, IsTextUnicode. That API basically checks for a byte-ordering-mark (BOM) header. In the absence of a BOM, it reads the first few hundred bytes of text and does some inference and heuristics to detect if the file is ascii, utf-8, or unicode. It's essentially guessing.

In you case, the first byte of the file is 0x7E or ~. If I delete that in a hex editor and save it back, Notepad shows the correct file encoding and looks like this.
enter image description here

Something about that initial byte sequence of upper ascii characters throws the algorithm off.

So the correct fix would be to insert a Byte Order Mark into your text stream so Notepad won't try to infer the encoding based on heuristics.

file.open("display.txt", std::ios::out);

const char* utf7_bom = "+/v8";
file << utf7_bom;

That little 4-byte sequence tells text decoders, which most editors will recognize, that "this file is ascii". You can read more about BOM tokens here: https://en.wikipedia.org/wiki/Byte_order_mark

selbie
  • 100,020
  • 15
  • 103
  • 173
  • Didn't think about passing it to a stringstream first then push it into the file stream for writing... This is better than the comment suggestion of using an `explicit cast`... For my general purposes it can be an int 64 haha... All I care about is getting the correct hex values in the text file! – Francis Cugler Mar 07 '20 at 06:16
  • Actually, I completely revised my answer to indicate that this is a bug in Notepad, not your code per se. You can still do the stringstream trick, but I suspect it will yield the same issue. – selbie Mar 07 '20 at 06:34
  • Maybe, but I still think the overall issue pertains to how C++ treats `char` types with output streams. For example if I have: `char c = 'a'; std::cout << c;` It will print out `a` to the console or text file... now if you want the integer version of `a` all you have to do is use integer promotion. `std::cout << +c;` and you are done! Now you will have the actual integer value on the character encoding type, either it be ascii, utf-8, etc... – Francis Cugler Mar 07 '20 at 06:39
  • In truth I don't think it has anything to do directly with the `stream` types such as `iostream` and `fstream`. I think this is part of the inner workings of the `<<()` and `>>()` operators that work on stream objects. – Francis Cugler Mar 07 '20 at 06:42
  • However, what you have suggested about the Byte Order mark and how text editors look for them in the header of the file upon opening, is very useful and a good piece of information to be aware of! – Francis Cugler Mar 07 '20 at 06:43
0

I had completely forgotten about the + operator for integer promotion of basic char types. The simplest, easiest and cleanest of all fixes in my opinion is to adjust my code to look like this:

int main() {

    char char digits[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b };

    std::fstream file;
    file.open( "display.txt, std::ios::out );

    for (int val = 0; val <= 255; val += 1)
        file << std::hex << +digits[val % 10] << " ";
    file << std::endl;

    // do the same for the rest of outputs to file...

    return 0;
}

All I did here was add the + before each of the chararrays`.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59