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::vectorvalues(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::vectorvalues(` 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::vectorvalues(std::istream_iterator – Dietmar Kühl Feb 19 '12 at 23:41(std::istringstream(line) >> std::skipws), (std::istream_iterator ()));`. 
