How to read N integers into a vector?












10















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

























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

    – JeJo
    32 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    20 mins ago
















10















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

























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

    – JeJo
    32 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    20 mins ago














10












10








10


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 19 mins ago









JorgeAmVF

499520




499520










asked 1 hour ago









gaazkamgaazkam

2,143938




2,143938













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

    – JeJo
    32 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    20 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
    32 mins ago











  • @Someprogrammerdude No.

    – Lightness Races in Orbit
    20 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
32 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
32 mins ago













@Someprogrammerdude No.

– Lightness Races in Orbit
20 mins ago





@Someprogrammerdude No.

– Lightness Races in Orbit
20 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
    53 mins ago






  • 1





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

    – Lightness Races in Orbit
    48 mins ago






  • 1





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

    – Lightness Races in Orbit
    37 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
    23 mins ago





















4














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
      53 mins ago






    • 1





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

      – Lightness Races in Orbit
      48 mins ago






    • 1





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

      – Lightness Races in Orbit
      37 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
      23 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
      53 mins ago






    • 1





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

      – Lightness Races in Orbit
      48 mins ago






    • 1





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

      – Lightness Races in Orbit
      37 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
      23 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 12 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
      53 mins ago






    • 1





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

      – Lightness Races in Orbit
      48 mins ago






    • 1





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

      – Lightness Races in Orbit
      37 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
      23 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
      53 mins ago






    • 1





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

      – Lightness Races in Orbit
      48 mins ago






    • 1





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

      – Lightness Races in Orbit
      37 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
      23 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
    53 mins ago





    Indeed, this is incorrect.

    – Lightness Races in Orbit
    53 mins ago




    1




    1





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

    – Lightness Races in Orbit
    48 mins ago





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

    – Lightness Races in Orbit
    48 mins ago




    1




    1





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

    – Lightness Races in Orbit
    37 mins ago







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

    – Lightness Races in Orbit
    37 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
    23 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
    23 mins ago















    4














    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






























      4














      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




























        4












        4








        4







        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 17 mins ago

























        answered 49 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

            Statuo de Libereco

            Tanganjiko

            Liste der Baudenkmäler in Enneberg