How to read N integers into a vector?












9















If I want to read all integers from standard input to a vector, I can use the handy:



vector<int> v{istream_iterator<int>(cin), istream_iterator()};


But let's assume I only want to read n integers. Is the hand-typed loop everything I got?



vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
cin >> v[i];


Or is there any more right-handed way to do this?










share|improve this question




















  • 2





    std::copy_n?

    – Some programmer dude
    1 hour ago











  • alternatively, you could use range-based loop as follows: std::vector<int> vec(N); for (int& element : vec) if(!std::cin >> element) break;

    – JeJo
    22 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    11 mins ago
















9















If I want to read all integers from standard input to a vector, I can use the handy:



vector<int> v{istream_iterator<int>(cin), istream_iterator()};


But let's assume I only want to read n integers. Is the hand-typed loop everything I got?



vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
cin >> v[i];


Or is there any more right-handed way to do this?










share|improve this question




















  • 2





    std::copy_n?

    – Some programmer dude
    1 hour ago











  • alternatively, you could use range-based loop as follows: std::vector<int> vec(N); for (int& element : vec) if(!std::cin >> element) break;

    – JeJo
    22 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    11 mins ago














9












9








9


2






If I want to read all integers from standard input to a vector, I can use the handy:



vector<int> v{istream_iterator<int>(cin), istream_iterator()};


But let's assume I only want to read n integers. Is the hand-typed loop everything I got?



vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
cin >> v[i];


Or is there any more right-handed way to do this?










share|improve this question
















If I want to read all integers from standard input to a vector, I can use the handy:



vector<int> v{istream_iterator<int>(cin), istream_iterator()};


But let's assume I only want to read n integers. Is the hand-typed loop everything I got?



vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
cin >> v[i];


Or is there any more right-handed way to do this?







c++ vector input






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 9 mins ago









JorgeAmVF

499520




499520










asked 1 hour ago









gaazkamgaazkam

2,138937




2,138937








  • 2





    std::copy_n?

    – Some programmer dude
    1 hour ago











  • alternatively, you could use range-based loop as follows: std::vector<int> vec(N); for (int& element : vec) if(!std::cin >> element) break;

    – JeJo
    22 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    11 mins ago














  • 2





    std::copy_n?

    – Some programmer dude
    1 hour ago











  • alternatively, you could use range-based loop as follows: std::vector<int> vec(N); for (int& element : vec) if(!std::cin >> element) break;

    – JeJo
    22 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    11 mins ago








2




2





std::copy_n?

– Some programmer dude
1 hour ago





std::copy_n?

– Some programmer dude
1 hour ago













alternatively, you could use range-based loop as follows: std::vector<int> vec(N); for (int& element : vec) if(!std::cin >> element) break;

– JeJo
22 mins ago





alternatively, you could use range-based loop as follows: std::vector<int> vec(N); for (int& element : vec) if(!std::cin >> element) break;

– JeJo
22 mins ago













@Someprogrammerdude No.

– Lightness Races in Orbit
11 mins ago





@Someprogrammerdude No.

– Lightness Races in Orbit
11 mins ago












2 Answers
2






active

oldest

votes


















12














As given in comments, copy_n is unsafe for this job, but you can use copy_if with mutable lambda:



#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>

int main(){
const int N = 10;
std::vector<int> v;
//optionally v.reserve(N);
std::copy_if(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(v),
[count=N] (int) mutable {
return --count;
});

return 0;
}





share|improve this answer





















  • 3





    Wouldn't it cause UB if there is not enough input provided?

    – paler123
    1 hour ago











  • Indeed, this is incorrect.

    – Lightness Races in Orbit
    44 mins ago






  • 1





    You can't fix it. std::copy_n is not fit for this task.

    – Lightness Races in Orbit
    39 mins ago











  • Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

    – Lightness Races in Orbit
    27 mins ago








  • 1





    @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

    – Ted Lyngmo
    14 mins ago





















3














You usually shouldn't do this with std::copy_n, which assumes that the provided iterator, when incremented n times, remains valid:




Copies exactly count values from the range beginning at first to the range beginning at result. Formally, for each non-negative integer i < n, performs *(result + i) = *(first + i).



(cppreference.com article on std::copy_n)




If you can guarantee that, then fine, but generally with std::cin that's not possible. You can quite easily have it dereferencing an invalid iterator:




The default-constructed std::istream_iterator is known as the end-of-stream iterator. When a valid std::istream_iterator reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. Dereferencing or incrementing it further invokes undefined behavior.



(cppreference.com article on std::istream_iterator)




You're pretty much there with your loop, though I'd probably use stronger termination condition to avoid excess reads from a "dead" stream:



vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
if (!cin >> v[i])
break;


I'd be tempted actually to wrap this into something that's like std::copy_n, but accepts a full "range" whose bounds may be validated in addition to counting from 0 to N.



An implementation might look like:



template<class InputIt, class Size, class OutputIt>
OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
{
for (Size i = 0; i < count && first != last; ++i)
*result++ = *first++;
return result;
}


You'd use it like this:



copy_atmost_n(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
N,
std::back_inserter(v)
);


Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.



(live demo)






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54254075%2fhow-to-read-n-integers-into-a-vector%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    12














    As given in comments, copy_n is unsafe for this job, but you can use copy_if with mutable lambda:



    #include <iterator>
    #include <vector>
    #include <iostream>
    #include <algorithm>

    int main(){
    const int N = 10;
    std::vector<int> v;
    //optionally v.reserve(N);
    std::copy_if(
    std::istream_iterator<int>(std::cin),
    std::istream_iterator<int>(),
    std::back_inserter(v),
    [count=N] (int) mutable {
    return --count;
    });

    return 0;
    }





    share|improve this answer





















    • 3





      Wouldn't it cause UB if there is not enough input provided?

      – paler123
      1 hour ago











    • Indeed, this is incorrect.

      – Lightness Races in Orbit
      44 mins ago






    • 1





      You can't fix it. std::copy_n is not fit for this task.

      – Lightness Races in Orbit
      39 mins ago











    • Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

      – Lightness Races in Orbit
      27 mins ago








    • 1





      @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

      – Ted Lyngmo
      14 mins ago


















    12














    As given in comments, copy_n is unsafe for this job, but you can use copy_if with mutable lambda:



    #include <iterator>
    #include <vector>
    #include <iostream>
    #include <algorithm>

    int main(){
    const int N = 10;
    std::vector<int> v;
    //optionally v.reserve(N);
    std::copy_if(
    std::istream_iterator<int>(std::cin),
    std::istream_iterator<int>(),
    std::back_inserter(v),
    [count=N] (int) mutable {
    return --count;
    });

    return 0;
    }





    share|improve this answer





















    • 3





      Wouldn't it cause UB if there is not enough input provided?

      – paler123
      1 hour ago











    • Indeed, this is incorrect.

      – Lightness Races in Orbit
      44 mins ago






    • 1





      You can't fix it. std::copy_n is not fit for this task.

      – Lightness Races in Orbit
      39 mins ago











    • Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

      – Lightness Races in Orbit
      27 mins ago








    • 1





      @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

      – Ted Lyngmo
      14 mins ago
















    12












    12








    12







    As given in comments, copy_n is unsafe for this job, but you can use copy_if with mutable lambda:



    #include <iterator>
    #include <vector>
    #include <iostream>
    #include <algorithm>

    int main(){
    const int N = 10;
    std::vector<int> v;
    //optionally v.reserve(N);
    std::copy_if(
    std::istream_iterator<int>(std::cin),
    std::istream_iterator<int>(),
    std::back_inserter(v),
    [count=N] (int) mutable {
    return --count;
    });

    return 0;
    }





    share|improve this answer















    As given in comments, copy_n is unsafe for this job, but you can use copy_if with mutable lambda:



    #include <iterator>
    #include <vector>
    #include <iostream>
    #include <algorithm>

    int main(){
    const int N = 10;
    std::vector<int> v;
    //optionally v.reserve(N);
    std::copy_if(
    std::istream_iterator<int>(std::cin),
    std::istream_iterator<int>(),
    std::back_inserter(v),
    [count=N] (int) mutable {
    return --count;
    });

    return 0;
    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 3 mins ago

























    answered 1 hour ago









    bartopbartop

    2,845826




    2,845826








    • 3





      Wouldn't it cause UB if there is not enough input provided?

      – paler123
      1 hour ago











    • Indeed, this is incorrect.

      – Lightness Races in Orbit
      44 mins ago






    • 1





      You can't fix it. std::copy_n is not fit for this task.

      – Lightness Races in Orbit
      39 mins ago











    • Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

      – Lightness Races in Orbit
      27 mins ago








    • 1





      @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

      – Ted Lyngmo
      14 mins ago
















    • 3





      Wouldn't it cause UB if there is not enough input provided?

      – paler123
      1 hour ago











    • Indeed, this is incorrect.

      – Lightness Races in Orbit
      44 mins ago






    • 1





      You can't fix it. std::copy_n is not fit for this task.

      – Lightness Races in Orbit
      39 mins ago











    • Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

      – Lightness Races in Orbit
      27 mins ago








    • 1





      @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

      – Ted Lyngmo
      14 mins ago










    3




    3





    Wouldn't it cause UB if there is not enough input provided?

    – paler123
    1 hour ago





    Wouldn't it cause UB if there is not enough input provided?

    – paler123
    1 hour ago













    Indeed, this is incorrect.

    – Lightness Races in Orbit
    44 mins ago





    Indeed, this is incorrect.

    – Lightness Races in Orbit
    44 mins ago




    1




    1





    You can't fix it. std::copy_n is not fit for this task.

    – Lightness Races in Orbit
    39 mins ago





    You can't fix it. std::copy_n is not fit for this task.

    – Lightness Races in Orbit
    39 mins ago













    Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

    – Lightness Races in Orbit
    27 mins ago







    Still no. Dereferencing the std::istream_iterator "end iterator" has UB, not throw semantics. (See my answer)

    – Lightness Races in Orbit
    27 mins ago






    1




    1





    @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

    – Ted Lyngmo
    14 mins ago







    @bartop I suggest removing the copy_n part and just leave As given in comments, copy_n is unsafe, but you can use copy_if with mutable lambda: followed by your nice solution.

    – Ted Lyngmo
    14 mins ago















    3














    You usually shouldn't do this with std::copy_n, which assumes that the provided iterator, when incremented n times, remains valid:




    Copies exactly count values from the range beginning at first to the range beginning at result. Formally, for each non-negative integer i < n, performs *(result + i) = *(first + i).



    (cppreference.com article on std::copy_n)




    If you can guarantee that, then fine, but generally with std::cin that's not possible. You can quite easily have it dereferencing an invalid iterator:




    The default-constructed std::istream_iterator is known as the end-of-stream iterator. When a valid std::istream_iterator reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. Dereferencing or incrementing it further invokes undefined behavior.



    (cppreference.com article on std::istream_iterator)




    You're pretty much there with your loop, though I'd probably use stronger termination condition to avoid excess reads from a "dead" stream:



    vector<int> v(n);
    for(vector<int>::size_type i = 0; i < n; i++)
    if (!cin >> v[i])
    break;


    I'd be tempted actually to wrap this into something that's like std::copy_n, but accepts a full "range" whose bounds may be validated in addition to counting from 0 to N.



    An implementation might look like:



    template<class InputIt, class Size, class OutputIt>
    OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
    {
    for (Size i = 0; i < count && first != last; ++i)
    *result++ = *first++;
    return result;
    }


    You'd use it like this:



    copy_atmost_n(
    std::istream_iterator<int>(std::cin),
    std::istream_iterator<int>(),
    N,
    std::back_inserter(v)
    );


    Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.



    (live demo)






    share|improve this answer






























      3














      You usually shouldn't do this with std::copy_n, which assumes that the provided iterator, when incremented n times, remains valid:




      Copies exactly count values from the range beginning at first to the range beginning at result. Formally, for each non-negative integer i < n, performs *(result + i) = *(first + i).



      (cppreference.com article on std::copy_n)




      If you can guarantee that, then fine, but generally with std::cin that's not possible. You can quite easily have it dereferencing an invalid iterator:




      The default-constructed std::istream_iterator is known as the end-of-stream iterator. When a valid std::istream_iterator reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. Dereferencing or incrementing it further invokes undefined behavior.



      (cppreference.com article on std::istream_iterator)




      You're pretty much there with your loop, though I'd probably use stronger termination condition to avoid excess reads from a "dead" stream:



      vector<int> v(n);
      for(vector<int>::size_type i = 0; i < n; i++)
      if (!cin >> v[i])
      break;


      I'd be tempted actually to wrap this into something that's like std::copy_n, but accepts a full "range" whose bounds may be validated in addition to counting from 0 to N.



      An implementation might look like:



      template<class InputIt, class Size, class OutputIt>
      OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
      {
      for (Size i = 0; i < count && first != last; ++i)
      *result++ = *first++;
      return result;
      }


      You'd use it like this:



      copy_atmost_n(
      std::istream_iterator<int>(std::cin),
      std::istream_iterator<int>(),
      N,
      std::back_inserter(v)
      );


      Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.



      (live demo)






      share|improve this answer




























        3












        3








        3







        You usually shouldn't do this with std::copy_n, which assumes that the provided iterator, when incremented n times, remains valid:




        Copies exactly count values from the range beginning at first to the range beginning at result. Formally, for each non-negative integer i < n, performs *(result + i) = *(first + i).



        (cppreference.com article on std::copy_n)




        If you can guarantee that, then fine, but generally with std::cin that's not possible. You can quite easily have it dereferencing an invalid iterator:




        The default-constructed std::istream_iterator is known as the end-of-stream iterator. When a valid std::istream_iterator reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. Dereferencing or incrementing it further invokes undefined behavior.



        (cppreference.com article on std::istream_iterator)




        You're pretty much there with your loop, though I'd probably use stronger termination condition to avoid excess reads from a "dead" stream:



        vector<int> v(n);
        for(vector<int>::size_type i = 0; i < n; i++)
        if (!cin >> v[i])
        break;


        I'd be tempted actually to wrap this into something that's like std::copy_n, but accepts a full "range" whose bounds may be validated in addition to counting from 0 to N.



        An implementation might look like:



        template<class InputIt, class Size, class OutputIt>
        OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
        {
        for (Size i = 0; i < count && first != last; ++i)
        *result++ = *first++;
        return result;
        }


        You'd use it like this:



        copy_atmost_n(
        std::istream_iterator<int>(std::cin),
        std::istream_iterator<int>(),
        N,
        std::back_inserter(v)
        );


        Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.



        (live demo)






        share|improve this answer















        You usually shouldn't do this with std::copy_n, which assumes that the provided iterator, when incremented n times, remains valid:




        Copies exactly count values from the range beginning at first to the range beginning at result. Formally, for each non-negative integer i < n, performs *(result + i) = *(first + i).



        (cppreference.com article on std::copy_n)




        If you can guarantee that, then fine, but generally with std::cin that's not possible. You can quite easily have it dereferencing an invalid iterator:




        The default-constructed std::istream_iterator is known as the end-of-stream iterator. When a valid std::istream_iterator reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. Dereferencing or incrementing it further invokes undefined behavior.



        (cppreference.com article on std::istream_iterator)




        You're pretty much there with your loop, though I'd probably use stronger termination condition to avoid excess reads from a "dead" stream:



        vector<int> v(n);
        for(vector<int>::size_type i = 0; i < n; i++)
        if (!cin >> v[i])
        break;


        I'd be tempted actually to wrap this into something that's like std::copy_n, but accepts a full "range" whose bounds may be validated in addition to counting from 0 to N.



        An implementation might look like:



        template<class InputIt, class Size, class OutputIt>
        OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
        {
        for (Size i = 0; i < count && first != last; ++i)
        *result++ = *first++;
        return result;
        }


        You'd use it like this:



        copy_atmost_n(
        std::istream_iterator<int>(std::cin),
        std::istream_iterator<int>(),
        N,
        std::back_inserter(v)
        );


        Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.



        (live demo)







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 7 mins ago

























        answered 39 mins ago









        Lightness Races in OrbitLightness Races in Orbit

        287k51466788




        287k51466788






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54254075%2fhow-to-read-n-integers-into-a-vector%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Polycentropodidae

            Magento 2 Error message: Invalid state change requested

            Paulmy