0

Sorry for my bad English. I need to build app which converts hex to rgb. I have file U1.txt with content inside:

2 3
008000
FF0000
FFFFFF
FFFF00
FF0000
FFFF00

And my codeblocks app:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    int a;
    int b;
    string color;

    ifstream data("U1.txt");
    ofstream result("U1result.txt");

    data >> a;
    data >> b;

    for (int i = 0; i < a * b; i++) {
        data >> color;
        cout << color[0] * 16 + color[1] << endl;
    }

    data.close();
    result.close();

    return 0;
}

This gives me 816. But it should be 0. I think color[0] is not an integer, but a char and it multiplies by ASCII number.. I've tried many ways with atoi, c_str() and it not working. P.S do not suggest stoi(), because I need to do this homework with older C++. Thanks in advance and have a good day ;)

Dewagg
  • 145
  • 10
  • 1
    I think you're looking for [`std::hex`](https://en.cppreference.com/w/cpp/io/manip/hex) – Mgetz Apr 03 '19 at 14:55
  • @Mgetz Thank you! But anyway I need to do this in my way :( – Dewagg Apr 03 '19 at 14:56
  • Possible duplicate of [Convert char to int in C and C++](https://stackoverflow.com/questions/5029840/convert-char-to-int-in-c-and-c) – JaMiT Apr 03 '19 at 15:24
  • While I appreciate you accepting my answer, you really should wait a while. Once a question has an accepted answer many people don't bother to read it, so you might miss out on additional information or perhaps an even better answer. Give it a day or so. – Pete Becker Apr 03 '19 at 15:32

3 Answers3

2

You can directly store the hexadecimal values in an int with std::hex.

int b;
ifstream data("U1.txt");
data >> std::hex >> b;
MrPromethee
  • 721
  • 9
  • 18
0

Since those encodings use 24 bits, you have to start out with an integer type that holds at least 24 bits. And for this kind of packing and unpacking, it really ought to be unsigned, so you don't get tangled up in sign bits. That means using std::uint_least32_t, which is the smallest unsigned type that can hold at least 32 bits. (Yes, 24 would fit better, but there is no least24 type; 32 is the best you can do).

If your compiler doesn't provide those fixed-width types (std::uint_least32_t), you can use unsigned long. It's required to be at least 32 bits wide. It could be larger, and the reason for using std::uint_least32_t is that your compiler might have, for example, a 32-bit integer, in which case unsigned int would be 32 bits wide. But you can't count on that, so either use the fixed-width type or use unsigned long to ensure that you have enough bits.

Since the character inputs are encoded in hexadecimal, you need to tell the input system to interpret them as hex values. So:

std::uint_least32_t value;
data >> std::hex >> value;

Now you've got the value in the low 24 bits of value. You need to pick out the individual R, G, and B parts of that value. That's straightforward. To get the low 8 bits, just mask out the higher ones:

std::cout << (value & 0xFF) << '\n';

To get the next 8 bits, shift and mask:

std::cout << ((value >> 8) & 0xFF) << '\n';

And, naturally, to get the upper 8 bits, shift and mask:

std::cout << ((value >> 16) & 0xFF) << '\n';
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
-1

A rather unelegant but also working answer is to subtract all your chars by 48 as thats where numbers start in ASCII. This is also the reason why you get 816 as:

48*16+48 = 816
NewEyes
  • 407
  • 4
  • 15
  • Exactly what I'm looking for! Thanks, good answer but still be looking for more "elegant" :) – Dewagg Apr 03 '19 at 15:01
  • 2
    NO, NO, NO! That **seems** to work because 48 is the ASCII code for `'0'` and you're only looking at the character `'0'`. Try it for `'F'`. (Note that, in general, you can subtract `'0'` from any of the characters `'0'..'9' and get the value that the character represents; the C and C++ language definitions require this to work. They do not impose any other requirements on the values involved in character encodings). – Pete Becker Apr 03 '19 at 15:05
  • I am a bit confused about your comment, I honestly believed 'int x = (int)character - 48' and 'int x = character - '0'' were interchangable… Will try this out as soon as I get a chance to. – NewEyes Apr 03 '19 at 15:22
  • 1
    @NewEyes -- they'll do the same thing on a system that uses ASCII, which is almost certainly true for yours. Some systems use a different encoding, and `'0'` is not 48 (read about [EBCDIC](http://www.astrodigital.org/digital/ebcdic.html)). More important, subtracting `'0'` **won't convert** a character like `'F'` to the value that it represents. – Pete Becker Apr 03 '19 at 15:36
  • Did some research, turns out you are right! Thanks for enlighting me – NewEyes Apr 03 '19 at 17:12