6

I find myself often using variables that contain a very small range of numbers (typically from 1 to 10) and would like to minimize the amount of memory I use by using the char data type instead of int or even short. I would like to cin values to my char variables without having cin converting it to it's ASCII equivalent and without working with single quotes. Ie, the following:

cout<< "Pick from 1 to 10.";

char selection;

cin>> selection;

if (selection == 1) return 1;

etc...

Is there a common way of doing this? Again, I don't want to use single quotes.

Thanks

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
user2303321
  • 297
  • 2
  • 11
  • 5
    You're worried about saving about 3 bytes of memory for a local variable in a program that's performing console I/O? – Michael Burr Apr 22 '13 at 06:58
  • I think you can't. you have to subtract it with '0'. no way you can avoid this with cin>>char – someone_ smiley Apr 22 '13 at 07:00
  • 1
    The code for conversion from `char` to actual `int` will take at least 2 bytes, that I can guarantee you. And more likely it will take 5 bytes. – Joker_vD Apr 22 '13 at 07:06

5 Answers5

5

You can create a little utility function:

struct CharReader {
  char &c;
  CharReader(char &c) : c(c) {}
};

CharReader asNumber(char &c) {
  return CharReader(c);
}

template <typename T, typename Traits>
std::basic_istream<T, Traits>& operator>> (std::basic_istream<T, Traits> &str, const CharReader &c) {
  short i;
  str >> i;
  c.c = static_cast<char>(i);
  return str;
}

You can the use it like this:

char selection;
std::cin >> asNumber(selection);
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 1
    It is troublesome. I find it very very disputable to 'approve of this'. Anyways, +1 for effort. Perhaps it will teach OP/others about applying a modicum of ingenuity to solve problems. – sehe Apr 22 '13 at 07:12
  • Will it save those three precious bytes the OP wrote about? Hm, I wonder if C++ compilers can optimize object construction away. – Joker_vD Apr 22 '13 at 07:33
  • @Joker_vD Yes, they can optimize it away. Anyway, they way I understood the OP's concern was that they have data structure containing such `char`s and want to load into them, and that the local-variable `char` was just an example. Of course, if the original goal was actually to save 3 bytes on stack for a local var, the above is pointless (as is anything else, BTW). – Angew is no longer proud of SO Apr 22 '13 at 07:36
3

There is no point in saving three bytes (or zero, because it's likely the compiler will align the stack anyway...) and complicating your code to read a number. Just do it normally and put your memory-saving efforts where it matters (if you don't know where it matters, it probably doesn't matter).

int selection;
if(!(cin >> selection) || selection < 0 || selection > 10) {
    // hmmm do something about it; perhaps scold the user.
}
place_where_it_is_getting_stored = selection;
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • Amazing how you would be the first to post a correct/useful answer on such a trivial subject :) Let's just suppose the wording had people on the wrong foot o.O – sehe Apr 22 '13 at 07:06
1
char selection;
cin >> selection;
selection -= '0';
RandyGaul
  • 1,915
  • 14
  • 21
0

Angew's answer presents an interesting and useful idiom:

  • A variable that cannot be directly modified by the program in a desirable way.
  • Creating a utility class that holds a reference to the variable.
  • Modifying the variable via the reference held in a temporary instance of that class.

This works because the program has an handle to the variable via the reference and hence, modify the variable. When the reference is destroyed along with the temporary instance of the class, the variable that is referred to is not affected.

Here is another example of this idiom.

For the current question, the idiom could be implemented in this way also, which is somewhat simpler to follow:

struct CharWidthNum {
  char &c;
  CharWidthNum(char &c) : c(c) {}
};

// Note: the temporary instance of CharWidthNum can be passed as an rvalue
// reference or as a const reference. It is the variable to which the reference
// variable refers to that is getting modified.
template <typename T, typename Traits>
std::basic_istream<T, Traits> &operator>>(std::basic_istream<T, Traits> &str,
                                          CharWidthNum &&c) {
  short i;
  str >> i;
  c.c = i; // static_cast<char> is not necessary when assigning an
           // integer type to char.
  return str;
}

In the program,

char selection;
std::cin>>CharWidthNum(selection);

We are directly creating a temporary instance of the utility struct, instead of using a utility function that returns a copy of that struct.

Hari
  • 1,561
  • 4
  • 17
  • 26
-1

maybe you should try

if (selection - '0' == 1) return 1;

this is the easiest way under your circumstances

Kingsley Chen
  • 276
  • 4
  • 12