I'm trying to read multiple integers from a single input line into an array eg. Input: 100 200 300 400, so the array is: a[0] = 100, a[1] = 200, a[2] = 300, a[3] = 400 The thing is, the number of integers are unknown, so the size of the array is unknown.
Asked
Active
Viewed 1.5k times
3 Answers
8
You should use a container that automatically resizes itself, such as std::vector
.
For example, something like this:
#include <string>
#include <iostream>
#include <sstream>
#include <utility>
#include <iterator>
std::string line;
getline(instream, line);
std::istringstream this_line(line);
std::istream_iterator<int> begin(this_line), end;
std::vector<int> values(begin, end);

Benjamin Lindley
- 101,917
- 9
- 204
- 274

Ben Voigt
- 277,958
- 43
- 419
- 720
-
I guess you meant to use `std::istream_iterator
` and you wanted to use appropriate parenthesis to avoid the most vexing parse. – Dietmar Kühl Feb 19 '12 at 23:14 -
@DietmarKühl: Thanks you pointing out the wrong name. Is that a valid way to avoid most vexing parse? – Ben Voigt Feb 19 '12 at 23:18
-
Yes, it definitely avoids the most vexing parse but unnecessarily requires the use of C++2011. A somewhat more subtle version is `std::vector
values(std::istream_iterator – Dietmar Kühl Feb 19 '12 at 23:22(this_line), (std::istream_iterator ()))` (note the extra set of parenthesis around the second argument). Also, I had intentionally used `std::istream_iterator ` instead of `istream_iterator ` ;) -
@DietmarKühl: Oh fine, no C++11 fun used. C++11 would also allow using `{}` instead of `()`, to avoid parsing as a function declaration, right? – Ben Voigt Feb 19 '12 at 23:23
-
@BenVoigt: yes, I think this is correct although I'm not entirely sure: the "uniform initialization syntax" is **far** from uniform and `std::vector
` supports initializer lists: I haven't quite wrapped my head around the interaction between those and the uniform initializations. Since `std::vector – Dietmar Kühl Feb 19 '12 at 23:30` uses `std::initializer_list ` this should be OK (need to try it out though). -
@DietmarKühl: A difference between `values{ begin, end }` and `values{{ first, second }}` perhaps? – Ben Voigt Feb 19 '12 at 23:34
-
@BenVoigt: I get this warning: `warning C4930: 'std::vector<_Ty> values(std::istream_iterator<_Ty> (__cdecl *)(std::istringstream),std::istream_iterator<_Ty> (__cdecl *)(void))': prototyped function not called (was a variable definition intended?)` and it also doesn't work properly. – LihO Feb 19 '12 at 23:35
-
When I replace `std::vector
values(` with `std::vector – LihO Feb 19 '12 at 23:35values = std::vector (`, everything works fine. -
@LihO: Thanks, I thought most vexing parse was avoided, guess it still found a way to make it look like a function. Re-fixed. – Ben Voigt Feb 19 '12 at 23:37
-
May I make a suggestion that avoids the most vexing parse, and is, IMO, much more readable? http://ideone.com/dUAcD – Benjamin Lindley Feb 19 '12 at 23:43
-
@BenjaminLindley: Yeah, yeah, go ahead and change it. – Ben Voigt Feb 19 '12 at 23:44
-
@BenVoigt: it seems, the constructor taking an initializer list is only taken if the values are convertible to `T`: `std::vector
{ 1u, 2u, 3u }` uses `std::initializer_list – Dietmar Kühl Feb 19 '12 at 23:52` while `std::vector { std::istream_iterator (in), std::istream_iterator () }` uses the constructor taking a pair of iterators. I still need to do some reading in the standard to sort this out for me... -
@DietmarKühl: most vexing parse could also be avoided by `std::vector
( std::istream_iterator – Ben Voigt Oct 16 '17 at 21:01{in}, std::istream_iterator {} )` couldn't it?
6
You could use std::vector
for this:
std::vector<int> myVector;
std::string line;
std::getline(std::cin, line);
std::istringstream os(line);
int i;
while(os >> i)
myVector.push_back(i);
This code requires following includes: <iostream>
, <string>
, <sstream>
and <vector>
.

LihO
- 41,190
- 11
- 99
- 167
-
2Please stop `abusing namepsace std;`. It's a really, really filthy habit, and it ruins the minds of all those newcomers... – Kerrek SB Feb 19 '12 at 23:12
-
I don't think it's quite as bad as Kerrek makes it out to be, but example code should be even more pristine than production code. – Ben Voigt Feb 19 '12 at 23:21
-
@BenVoigt: I know that it is not a good practice and I abuse it really quite a lot especially when I know that I'm going to write more than 5 `std::` prefixes. He made a good thing when he wrote this comment. – LihO Feb 19 '12 at 23:24
-
1@LihO: As long as it`s within a limited scope, `using namespace std;` is fine. The main complaint is related to "action at a distance", which is why it's especially bad to find it in a header file. – Ben Voigt Feb 19 '12 at 23:26
1
Inserters and stream iterators can do this nicely:
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
std::vector<int> numbers;
std::copy(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(numbers));
Or, as @Ben Voigt has it, construct the vector from the input in one go (if that's an option):
std::vector numbers(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>());
You can replace std::cin
by a suitable string stream if your input requirements are more complex.

Kerrek SB
- 464,522
- 92
- 875
- 1,084
-
Boo to `std::copy`, `std::vector` knows how to construct itself from a range. – Ben Voigt Feb 19 '12 at 23:14
-
-
What pun? Your code reads the entire standard input stream. The OP only wants a single line. – Benjamin Lindley Feb 19 '12 at 23:19
-
+1 for side-stepping the issue of the most vexing parse by using `std::cin`. Unfortunately, this won't work as easily if the stream is a local variable, though: in this case an extra set of parenthesis is needed. – Dietmar Kühl Feb 19 '12 at 23:25
-
@DietmarKühl: Yeah, we discussed this a while back, where we did everything inside one single `for` loop, using an ad-hoc helper `std::stay` (the opposite of `std::move`). – Kerrek SB Feb 19 '12 at 23:27
-
@DietmarKühl: Ah, [here it is](http://stackoverflow.com/a/8116843/596781). Turns out that `std::stay` makes for good Googlability. – Kerrek SB Feb 19 '12 at 23:29
-
@KerreK: Whole question looks like a dupe at this point, doesn't it? – Ben Voigt Feb 19 '12 at 23:35
-
-
@KerrekSB: You don't even need `std::stay()` (not to mention that you aren't allowed to add this to `namespace std` anyway): `std::vector
values(std::istream_iterator – Dietmar Kühl Feb 19 '12 at 23:41(std::istringstream(line) >> std::skipws), (std::istream_iterator ()));`.