Eindimensionales Array wie eine zweidimensionale Matrix ausgeben?



  • Hi Leute!

    Ich hab hier eine Methode, die mir (wenn sie mal funktioniert) ein eindimensionales Array wie eine zweidimensionale Matrix ausgeben soll. Leider verstehe ich nicht so ganz wie das funktionieren soll. Ich habe anfangs gedacht, dass man da mit dem modulo-Operator dran kommt, aber irgendwie kapier ich es nicht 😞

    Einen zweiten Ansatz mit zwei ineinanderverschachtelten for-Schleifen hat mich auch nicht weiter gebracht, weil immer wenn die äußere Schleife ein cout macht und ich zu inneren zurückkehre wird der Laufindex auf 0 zurückgesetzt, was mir nicht die nachfolgenden Werte im Array ausgibt, sondern wieder die ersten n-Werte...

    m ist die Zeilenanzahl und n ist die Spaltenanzahl der Matrix.

    void matrix::Print()
    {
    	for(int j=0; j<(m*n); j++)
    	{
    		cout << feld[j] << " ";
    
    		if(j%n == 0)
    		{
    			cout << endl;
    		}
    	}
    }
    


  • void matrix::Print()
    {
      for(int y=0; y<hoehe; ++y)
      {
        for(int x=0; x<breite; ++x)
        {
          cout << feld[y*breite+x] << ' ';
        }
        cout<<'\n';//endl hat da nix zu suchen. 
    }
    

    Aber eigentlich schreibt man sich auch gerne einen Adapter mit [][] um den Speicher, sonst ist die Klasse ruck zuck überlastet.


  • Mod

    #include <iostream>
    
    int main()
    {
        using namespace std;
        int feld[] = {1,2,3,4,5,6,7,8,9};
        const int m =3, n = 3;
    
        cout<< "Erster Versuch:\n";
        for(int j=0; j<(m*n); j++)
        {
            cout << feld[j] << ' ';
    
            if(j%n == m - 1)
            {
                cout << '\n';
            }
        }
    
        cout << "Zweiter Versuch:\n";
        for (int i = 0; i < m; ++i)
        {
            for (int j = 0; j < n; ++j)
                cout << feld[i*n + j] << ' ';
            cout << '\n';
        }
    }
    


  • Danke! Es funktioniert so in der Tat!

    Was ist ein [][]-Adapter?



  • x,y zu index:
    y * breite + x
    index zu x,y:
    x % breite
    y / höhe

    Edit: Ich glaube, eine Klasse multi_array, die ein n-dimensionales Array auf ein eindimensionales abbildet.



  • vip@r schrieb:

    Was ist ein [][]-Adapter?

    Ichj dachte im Prinzip an sowas:
    http://www.c-plusplus.net/forum/175426-full



  • Dank std::initializer_list kann man eigentlich auch [{x, y}] schreiben.
    Ich hatte mal sowas:

    Nathan schrieb:

    *Mal alten Code rauskram*:

    // Library MySTL
    // multiarray.hpp
    // More-dimensional arrays/vectors
    
    #ifndef MULTIARRAY_HPP_INCLUDED
    #define MULTIARRAY_HPP_INCLUDED
    
    #include <array>
    #include <map>
    #include <stdexcept>
    #include <tuple>
    #include <type_traits>
    #include <vector>
    
    #include <iostream>
    
    namespace my
    {
    namespace stl
    {
        // Forwards
        template <std::size_t dims>
        class multi_array_index_t;
        template <std::size_t dims>
        class multi_array_getter;
    
        /// \brief A more-dimensional, dynamic growing vector, based on a spezific STL-Container
        /// \param T: the type of the multi_array
        /// \param dims: the number of dimensions (more than one is recommend!)
        /// \param G: the getter function for the multi_array (says how the values are stored); default: multi_array_getter
        /// \param C: the container storing the values, must have a random_access_iterator (vector or deque); default: vector
        template <typename T, std::size_t dims, template<std::size_t> class G = multi_array_getter, template<typename, typename...> class C = std::vector>
        class multi_array
        {
        public:
            // Typedefs
            /// \brief The type and its references, const_references, allocators and pointers
            using value_type            = typename C<T>::value_type;
            using allocator_type        = typename C<T>::allocator_type;
            using reference             = typename C<T>::reference;
            using const_reference       = typename C<T>::const_reference;
            using pointer               = typename C<T>::pointer;
            using const_pointer         = typename C<T>::const_pointer;
    
            /// \brief The getter class and the container
            using getter    = G<dims>;
            using container = C<T>;
    
            /// \brief The iterators
            using iterator               = typename C<T>::iterator;
            using const_iterator         = typename C<T>::const_iterator;
            using reverse_iterator       = typename C<T>::reverse_iterator;
            using const_reverse_iterator = typename C<T>::const_reverse_iterator;
    
            /// \brief Type representing an index in the multi_array
            using index_t   = multi_array_index_t<dims>;
            /// \brief Type representing a size in the multi_array
            using size_type = multi_array_index_t<dims>;
    
            // Static Functions
            /// \brief Returns the dimensions of the multi_array
            static constexpr std::size_t dimensions() noexcept {return dims;}
    
        public:
            // Constructors
            /// \brief Default Constructor
            multi_array() = default;
            /// \brief Constructor
            /// Initalize the multi_array with a size and another container (optional)
            /// \param size: the size (from type size_type)
            /// \param container: the other container (from type container) (optional)
            explicit multi_array(size_type size) : size_(size) {}
            multi_array(size_type size, const container  &container);
            multi_array(size_type size, const container &&container);
    
            // Iterators
            /// \brief Common iterator access
            /// Is like any other iterator access, see STL-Documentation
            iterator begin() noexcept;
            const_iterator begin() const noexcept;
            iterator end() noexcept;
            const_iterator end() const noexcept;
    
            reverse_iterator rbegin() noexcept;
            const_reverse_iterator rbegin() const noexcept;
            reverse_iterator rend() noexcept;
            const_reverse_iterator rend() const noexcept;
    
            const_iterator cbegin() const noexcept;
            const_iterator cend() const noexcept;
    
            const_reverse_iterator crbegin() const noexcept;
            const_reverse_iterator crend() const noexcept;
    
            /// \brief Iterator access to certain sequences (rows, columns, etc.)
            /// \param iterator_t: a typename for the return type (a typename)
            /// \param dimension: the dimension you want to access (0 for the first (default: x-dimension), 1 for the second,...) (from type std::size_t)
            /// \param position: the position where the sequence is located, the dimension set with dimension will be ignored (from type index_t)
            /// \param begin: a function returning an iterator from type iterator_t to the first object (function pointer) (default: begin)
            /// \return an iterator to the start of the sequence and one to the end (from type std::pair<iterator_t, iterator_t)
            template <typename iterator_t = decltype(multi_array::begin())>
            std::tuple<iterator_t, iterator_t> range(std::size_t dimension, index_t position);
            template <typename iterator_t = decltype(multi_array::cbegin())>
            std::tuple<iterator_t, iterator_t> range(std::size_t dimension, index_t position,
                                                    iterator_t (multi_array::*begin) (void)) const;
    
            /// \brief Iterator access to certain levels (like range, but more-dimensional)
            /// \param iterator_t: a typename for the return type (a typename)
            /// \param dimensions: how many dimensions you want to access (from type std::size_t)
            /// \param dimension: the dimensions you want to access (from type std::array<std::size_t, dimensions>)
            /// \param position: the position where the level is located (from type
    
            // Capacity
            /// \brief Get the size of the multi_array
            /// \return The current size of the multi_array (from type size_type)
            constexpr size_type size() noexcept;
    
            /// \brief Get the maximum size of the multi_array
            /// \return The maximum size of the multi_array (from type std::size_t)
            constexpr std::size_t max_size() noexcept;
    
            /// \brief Check wether container is empty or not
            /// \return true if the container is empty, false otherwise (from type bool)
            constexpr bool empty() noexcept;
    
            /// \brief Resize the multi_array, behaves like the resize of the container
            /// \param size: the new size of the multi_array (from type size_type)
            /// \param value: an initialization value for the new values (from type value_type) (default: value_type())
            void resize(size_type size, const value_type &value = value_type());
    
            // Element access
            /// \brief Get element
            /// \param at: the position of the element (from type index_t)
            /// \return The element at the position at (from type reference/const_reference)
            reference       operator [] (index_t at);
            const_reference operator [] (index_t at) const;
    
            /// \brief Get element, if it has a wrong index, std::out_of_range is thrown
            /// \param at: the position of the element (from type index_t)
            /// \return The element at the position at (from type reference/const_reference)
            reference       at(index_t at);
            const_reference at(index_t at) const;
    
            /// \brief Get the data of the container
            /// \return The container (copy) (from type container)
            container data() const noexcept;
    
            // Modifiers
            /// \brief Assign the multi_array with another multi_array (like operator =)
            /// \param array: the other multi_array (from type multi_array)
            void assign(const multi_array  &array);
            void assign(const multi_array &&array);
    
            /// \brief Assign the multi_array with another container and a new size
            /// \param size: the new size (from type size_type)
            /// \param container: the container (from type container)
            void assign(size_type size, const container  &container);
            void assign(size_type size, const container &&container);
    
            /// \brief Assign the multi_array with another container; size remains the same
            /// \param container: the container (from type container)
            void assign(const container  &container);
            void assign(const container &&container);
    
            /// Size can't be modified directly, so objects can't be inserted.
    
            /// \brief Swaps the content of this multi_array and another, size is swapped too
            /// \param other: the other multi_array (from type multi_array)
            void swap(multi_array &other);
    
            /// \brief Clears the multi_array, container has no objects any longer, size is 0 in all dimensions.
            void clear();
    
        private:
            container container_; ///< The one-dimensional container which stores the data
            size_type size_; ///< The size of the MultiArray
            getter get_; ///< The Getter of the MultiArray
        };
    
        /// \brief An index-type for the multi_array based on an std::array<std::size_t, dims>
        /// \param dims: the dimension of the index_t (from type std::size_t)
        template <std::size_t dims>
        class multi_array_index_t : public std::array<std::size_t, dims>
        {
        public:
            /// \brief Default Constructor
            multi_array_index_t() = default;
    
            /// \brief Constructor
            /// Initialize with an initializer-list
            /// \param il: the initializer-list (from type std::initalizer_list<std::size_t>)
            multi_array_index_t(std::initializer_list<std::size_t> il) noexcept;
    
            /// \brief Get the length of the index_t
            /// \return The length of the index_t (from type std::size_t)
            constexpr std::size_t length() noexcept;
        };
    
        /// \brief A getter class for a multi_array
        /// This class converts more-dimensional indices to a one-dimensional
        /// \param dims: the dimensions of the getter (from type std::size_t)
        template <std::size_t dims>
        class multi_array_getter
        {
        public:
            /// \brief Operator ()
            /// Converts more-dimensional indices to a one-dimensional
            /// \param position: the position being converted (from type multi_array_index_t<dims>)
            /// \param size: the size of the relating multi_array (from type multi_array_index_t<dims>)
            /// \return the one-dimensional coordinates (from type std::size_t)
            std::size_t operator () (multi_array_index_t<dims> position, multi_array_index_t<dims> size) const noexcept;
    
            /// \brief Operator ()
            /// Converts one-dimensional indices to more-dimensional
            /// \param index: the one-dimensional index (from type std::size_t)
            /// \param size: the size of the related multi_array (from type multi_array_index_t<dims>)
            /// \return the more-dimensional coordinates (from type multi_array_index_t<dims>)
            multi_array_index_t<dims> operator () (std::size_t index, multi_array_index_t<dims> size) const noexcept;
        };
    
        #include "impl\multiarray-impl.hpp"
    
    } // namespace stl
    } // namespace my
    
    #endif // MULTIARRAY_HPP_INCLUDED
    


  • Nathan schrieb:

    /// \brief An index-type for the multi_array based on an std::array<std::size_t, dims>
        class multi_array_index_t : public std::array<std::size_t, dims>
        {
        public:
            /// \brief Default Constructor
            multi_array_index_t() = default;
     
            /// \brief Constructor
            /// Initialize with an initializer-list
            /// \param il: the initializer-list (from type std::initalizer_list<std::size_t>)
            multi_array_index_t(std::initializer_list<std::size_t> il) noexcept;
     
            /// \brief Get the length of the index_t
            /// \return The length of the index_t (from type std::size_t)
            constexpr std::size_t length() noexcept;
        };
    

    Das macht ja wohl gar keinen Sinn.

    • Die Kommentare könnte man gleich weglassen.
    • Die initializer_list macht hier nur Probleme.
    • Length ist überflüssig.
    • Der Default-Konstruktor sollte wenn schon alles auf 0 initialisieren
    • Vererbung ist fehl am Platz.

    Besser:

    struct better {
      std::array<std::size_t, dims> d;
      template<typename...T>
      better(T... a) : d{{a...}} {static_assert(sizeof...(T) == dims, "Wrong dimension");}
    };
    

    Aber auch sonst ist der Code verworren.

    Nathan schrieb:

    Dank std::initializer_list kann man eigentlich auch [{x, y}] schreiben

    Das hat nichts mit initializer_list zu tun.



  • Wenn man sich das Leben nicht unnötig schwer machen will, kann man vielleicht einfach den operator() (int x, int y) überladen.



  • ichbinsisyphos schrieb:

    Wenn man sich das Leben nicht unnötig schwer machen will, kann man vielleicht einfach den operator() (int x, int y) überladen.

    Dann könnte das Array aber anfangen zu denken, es wäre eine Funktion.

    at(int x,int y)
    

Anmelden zum Antworten