How to print out the contents of a vector?

后端 未结 19 1195
旧时难觅i
旧时难觅i 2020-11-22 03:46

I want to print out the contents of a vector in C++, here is what I have:

#include 
#include 
#include 
#include         


        
相关标签:
19条回答
  • 2020-11-22 04:15

    You can write your own function:

    void printVec(vector<char> vec){
        for(int i = 0; i < vec.size(); i++){
            cout << vec[i] << " ";
        }
        cout << endl;
    }
    
    0 讨论(0)
  • 2020-11-22 04:16

    In C++11, a range-based for loop might be a good solution:

    vector<char> items = {'a','b','c'};
    for (char n : items)
        cout << n << ' ';
    

    Output:

    a b c 
    
    0 讨论(0)
  • 2020-11-22 04:17

    I see two problems. As pointed out in for (x = 17; isalpha(firstsquare); x++) there's either an infinite loop or never executed at all, and also in if (entrance == 'S') if the entrance character is different than 'S' then nothing in pushed to the path vector, making it empty and thus printing nothing on screen. You can test the latter checking for path.empty() or printing path.size().

    Either way, wouldn't it be better to use a string instead of a vector? You can access the string contents like an array as well, seek characters, extract substrings and print the string easily (without a loop).

    Doing it all with strings might be the way to have it written in a less convoluted way and easier to spot the problem.

    0 讨论(0)
  • 2020-11-22 04:17

    For those that are interested: I wrote a generalized solution that takes the best of both worlds, is more generalized to any type of range and puts quotes around non-arithmetic types (desired for string-like types). Additionally, this approach should not have any ADL issues and also avoid 'surprises' (since it's added explicitly on a case-by-case basis):

    template <typename T>
    inline constexpr bool is_string_type_v = std::is_convertible_v<const T&, std::string_view>;
    
    template<class T>
    struct range_out {
      range_out(T& range) : r_(range) {
      }
      T& r_;
      static_assert(!::is_string_type_v<T>, "strings and string-like types should use operator << directly");
    };
    
    template <typename T>
    std::ostream& operator<< (std::ostream& out, range_out<T>& range) {
      constexpr bool is_string_like = is_string_type_v<T::value_type>;
      constexpr std::string_view sep{ is_string_like ? "', '" : ", " };
    
      if (!range.r_.empty()) {
        out << (is_string_like ? "['" : "[");
        out << *range.r_.begin();
        for (auto it = range.r_.begin() + 1; it != range.r_.end(); ++it) {
          out << sep << *it;
        }
        out << (is_string_like ? "']" : "]");
      }
      else {
        out << "[]";
      }
    
      return out;
    }
    

    Now it's fairly easy to use on any range:

    std::cout << range_out{ my_vector };
    

    The string-like check leaves room for improvement. I do also have static_assert check in my solution to avoid std::basic_string<>, but I left it out here for simplicity.

    0 讨论(0)
  • 2020-11-22 04:20

    Using std::copy but without extra trailing separator

    An alternative/modified approach using std::copy (as originally used in @JoshuaKravtiz answer) but without including an additional trailing separator after the last element:

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <vector>
    
    template <typename T>
    void print_contents(const std::vector<T>& v, const char * const separator = " ")
    {
        if(!v.empty())
        {
            std::copy(v.begin(),
                      --v.end(),
                      std::ostream_iterator<T>(std::cout, separator));
            std::cout << v.back() << "\n";
        }
    }
    
    // example usage
    int main() {
        std::vector<int> v{1, 2, 3, 4};
        print_contents(v);      // '1 2 3 4'
        print_contents(v, ":"); // '1:2:3:4'
        v = {};
        print_contents(v);      // ... no std::cout
        v = {1};
        print_contents(v);      // '1'
        return 0;
    }
    

    Example usage applied to container of a custom POD type:

    // includes and 'print_contents(...)' as above ...
    
    class Foo
    {
        int i;
        friend std::ostream& operator<<(std::ostream& out, const Foo& obj);
    public:
        Foo(const int i) : i(i) {}
    };
    
    std::ostream& operator<<(std::ostream& out, const Foo& obj)
    {
        return out << "foo_" << obj.i; 
    }
    
    int main() {
        std::vector<Foo> v{1, 2, 3, 4};
        print_contents(v);      // 'foo_1 foo_2 foo_3 foo_4'
        print_contents(v, ":"); // 'foo_1:foo_2:foo_3:foo_4'
        v = {};
        print_contents(v);      // ... no std::cout
        v = {1};
        print_contents(v);      // 'foo_1'
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 04:20

    template collection:

    apply std::cout << and std::to_string

    to std::vector, std::array and std::tuple

    As printing a vector in cpp turned out to be surprisingly much work (at least compared to how basic this task is) and as one steps over the same problem again, when working with other container, here a more general solution ...

    Template collection content

    This template collection handles 3 container types: std::vector, std::array and std::tuple. It defines std::to_string() for those and makes it possible to directly print them out by std::cout << container;.

    Further it defines the << operator for std::string << container. With this it gets possible to construct strings containig these container types in a compact way.

    From

    std::string s1 = "s1: " + std::to_string(arr) + "; " + std::to_string(vec) + "; " + std::to_string(tup);
    

    we get to

    std::string s2 = STR() << "s2: " << arr << "; " << vec << "; " << tup;
    

    Code

    You can test this code interactively: here.

    #include <iostream>
    #include <string>
    #include <tuple>
    #include <vector>
    #include <array>
    
    namespace std
    {   
        // declations: needed for std::to_string(std::vector<std::tuple<int, float>>)
        std::string to_string(std::string str);
        std::string to_string(const char *str);
        template<typename T, size_t N>
        std::string to_string(std::array<T, N> const& arr);
        template<typename T>
        std::string to_string(std::vector<T> const& vec);
        template<typename... Args>
        std::string to_string(const std::tuple<Args...>& tup);
        
        std::string to_string(std::string str)
        {
            return std::string(str);
        }
        std::string to_string(const char *str)
        {
            return std::string(str);
        }
    
        template<typename T, size_t N>
        std::string to_string(std::array<T, N> const& arr)
        {
            std::string s="{";
            for (std::size_t t = 0; t != N; ++t)
                s += std::to_string(arr[t]) + (t+1 < N ? ", ":"");
            return s + "}";
        }
    
        template<typename T>
        std::string to_string(std::vector<T> const& vec)
        {
            std::string s="[";
            for (std::size_t t = 0; t != vec.size(); ++t)
                s += std::to_string(vec[t]) + (t+1 < vec.size() ? ", ":"");
            return s + "]";
        }
        
        // to_string(tuple)
        // https://en.cppreference.com/w/cpp/utility/tuple/operator%3D
        template<class Tuple, std::size_t N>
        struct TupleString
        {
            static std::string str(const Tuple& tup)
            {
                std::string out;
                out += TupleString<Tuple, N-1>::str(tup);
                out += ", ";
                out += std::to_string(std::get<N-1>(tup));
                return out;
            }
        };
        template<class Tuple>
        struct TupleString<Tuple, 1>
        {
            static std::string str(const Tuple& tup)
            {
                std::string out;
                out += std::to_string(std::get<0>(tup));
                return out;
            }
        };
        template<typename... Args>
        std::string to_string(const std::tuple<Args...>& tup)
        {
            std::string out = "(";
            out += TupleString<decltype(tup), sizeof...(Args)>::str(tup);
            out += ")";
            return out;
        }
    } // namespace std
    
    
    /**
     * cout: cout << continer
     */
    template <typename T, std::size_t N> // cout << array
    std::ostream& operator <<(std::ostream &out, std::array<T, N> &con)
    {
        out <<  std::to_string(con);
        return out;
    }
    template <typename T, typename A> // cout << vector
    std::ostream& operator <<(std::ostream &out, std::vector<T, A> &con)
    {
        out <<  std::to_string(con);
        return out;
    }
    template<typename... Args> // cout << tuple
    std::ostream& operator <<(std::ostream &out, std::tuple<Args...> &con)
    {
        out <<  std::to_string(con);
        return out;
    }
    
    /**
     * Concatenate: string << continer
     */
    template <class C>
    std::string operator <<(std::string str, C &con)
    {
        std::string out = str;
        out += std::to_string(con);
        return out;
    }
    #define STR() std::string("")
    
    int main()
    {
        std::array<int, 3> arr {1, 2, 3};
        std::string sArr = std::to_string(arr);
        std::cout << "std::array" << std::endl;
        std::cout << "\ttest to_string: " << sArr << std::endl;
        std::cout << "\ttest cout <<: " << arr << std::endl;
        std::cout << "\ttest string <<: " << (std::string() << arr) << std::endl;
        
        std::vector<std::string> vec {"a", "b"};
        std::string sVec = std::to_string(vec);
        std::cout << "std::vector" << std::endl;
        std::cout << "\ttest to_string: " << sVec << std::endl;
        std::cout << "\ttest cout <<: " << vec << std::endl;
        std::cout << "\ttest string <<: " << (std::string() << vec) << std::endl;
        
        std::tuple<int, std::string> tup = std::make_tuple(5, "five");
        std::string sTup = std::to_string(tup);
        std::cout << "std::tuple" << std::endl;
        std::cout << "\ttest to_string: " << sTup << std::endl;
        std::cout << "\ttest cout <<: " << tup << std::endl;
        std::cout << "\ttest string <<: " << (std::string() << tup) << std::endl;
        
        std::vector<std::tuple<int, float>> vt {std::make_tuple(1, .1), std::make_tuple(2, .2)};
        std::string sVt = std::to_string(vt);
        std::cout << "std::vector<std::tuple>" << std::endl;
        std::cout << "\ttest to_string: " << sVt << std::endl;
        std::cout << "\ttest cout <<: " << vt << std::endl;
        std::cout << "\ttest string <<: " << (std::string() << vt) << std::endl;
        
        std::cout << std::endl;
        
        std::string s1 = "s1: " + std::to_string(arr) + "; " + std::to_string(vec) + "; " + std::to_string(tup);
        std::cout << s1 << std::endl;
        
        std::string s2 = STR() << "s2: " << arr << "; " << vec << "; " << tup;
        std::cout << s2 << std::endl;
    
        return 0;
    }
    

    Output

    std::array
        test to_string: {1, 2, 3}
        test cout <<: {1, 2, 3}
        test string <<: {1, 2, 3}
    std::vector
        test to_string: [a, b]
        test cout <<: [a, b]
        test string <<: [a, b]
    std::tuple
        test to_string: (5, five)
        test cout <<: (5, five)
        test string <<: (5, five)
    std::vector<std::tuple>
        test to_string: [(1, 0.100000), (2, 0.200000)]
        test cout <<: [(1, 0.100000), (2, 0.200000)]
        test string <<: [(1, 0.100000), (2, 0.200000)]
    
    s1: {1, 2, 3}; [a, b]; (5, five)
    s2: {1, 2, 3}; [a, b]; (5, five)
    
    0 讨论(0)
提交回复
热议问题