3

I'm try to get input from a user using a templated function. I want to be able to input int, doubles, floats, and strings. So here's the code I have so far:

template<class DataType>
void getInput(string prompt, DataType& inputVar)
{
      cout << prompt;
      cin >> inputVar;
}

int main()
{
      string s;
      int i;
      float f;
      double d;

      getInput("String: ", s);
      getInput("Int: ", i);
      getInput("Float: ", f);
      getInput("Double: ", d);

      cout << s << ' ' << i << ' ' << f << ' ' << d << endl;
      return 0;
}

The basic types all work, but the problem I have lies with inputting strings. I'd like to be able to input more than one word, but to the fact that I'm using cin I can't. So is it possible input multi-word strings as well the basic types in a manner similar to what I'm doing?

iammilind
  • 68,093
  • 33
  • 169
  • 336
John
  • 31
  • 1
  • 2

4 Answers4

2

I think you want to use getline anyway, as you don't want to leave stuff in your input buffer after each prompt. To change the behaviour only for strings, though, you can use a template specialisation. After your template function:

template<>
void getInput(string prompt, string& inputVar)
{
    cout << prompt;
    getline(cin, inputVar);
}
Zeppe
  • 205
  • 2
  • 4
  • Deleted my answer in favour of this one. – johnsyweb Sep 17 '11 at 07:09
  • That did the trick. Now, what's the difference in how C++ handles template specialization vs function overloading? – John Sep 17 '11 at 07:14
  • 1
    @Jonhsyweb, it's a good practice to choose [overloading over specialization](http://stackoverflow.com/questions/7108033/template-specialization-vs-function-overloading). – iammilind Sep 17 '11 at 07:25
2

Overload the function for string (or do template specialization).

void getInput(string prompt, string& inputVar) // <--- overloaded for 'string'
{
    cout << prompt;
    getline(cin, inputVar);  //<-- special treatment for 'string' using getline()
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
1

I believe you will need to special-case strings. cin will get just one word, and you'll need to get the whole line using getline(). See this page for reference. You can then manipulate the line as you see fit: split it, parse it, whatnot.

Unfortunately that clobbers the entire line, and if you have something like "one two three 123 3.1415", then the entire line will be consumed.

Also see the example here for a better way to decide between numbers/strings/words/floats. But that does not utilise templates to the full.

evgeny
  • 2,564
  • 17
  • 27
0

The way this is written you could get some probably unexpected results. For example, you could have a session that goes like this:

String: Foo 12            3.14159  1.5 <enter>
Int: Float: Double: Foo 12 3.14159 1.5

I know you just gave an example, but this is almost certainly not what you want to do. cin will never register any input until enter is pressed, so you probably want to go line by line anyway, using getline. Otherwise things will get funky like above.

Even if you had access to each keypress, you probably couldn't accomplish this inline like it seems you want to.

Keith Layne
  • 3,688
  • 1
  • 24
  • 28