खोज…


परिचय

Arrays एक ही प्रकार के तत्व आसन्न स्मृति स्थानों में रखे गए हैं। तत्वों को व्यक्तिगत रूप से एक जोड़ा सूचकांक के साथ एक अद्वितीय पहचानकर्ता द्वारा संदर्भित किया जा सकता है।

यह आपको एक विशिष्ट प्रकार के कई चर मानों की घोषणा करने और प्रत्येक मूल्य के लिए एक चर घोषित करने की आवश्यकता के बिना व्यक्तिगत रूप से उन तक पहुंचने की अनुमति देता है।

सरणी आकार: संकलित समय पर सुरक्षित टाइप करें।

#include <stddef.h>     // size_t, ptrdiff_t

//----------------------------------- Machinery:

using Size = ptrdiff_t;

template< class Item, size_t n >
constexpr auto n_items( Item (&)[n] ) noexcept
    -> Size
{ return n; }


//----------------------------------- Usage:

#include <iostream>
using namespace std;
auto main()
    -> int
{
    int const   a[]     = {3, 1, 4, 1, 5, 9, 2, 6, 5, 4};
    Size const  n       = n_items( a );
    int         b[n]    = {};       // An array of the same size as a.
    
    (void) b;
    cout << "Size = " << n << "\n";
}

सरणी आकार, sizeof(a)/sizeof(a[0]) लिए C मुहावरा, एक सूचक को तर्क के रूप में स्वीकार करेगा और फिर आम तौर पर गलत परिणाम देगा।

C ++ 11 के लिए

C ++ 11 का उपयोग करके आप कर सकते हैं:

std::extent<decltype(MyArray)>::value;

उदाहरण:

char MyArray[] = { 'X','o','c','e' };
const auto n = std::extent<decltype(MyArray)>::value;
std::cout << n << "\n"; // Prints 4

C ++ 17 तक (इस लेखन के अनुसार आगामी) C ++ में किसी सरणी का आकार प्राप्त करने के लिए कोई अंतर्निहित कोर भाषा या मानक लाइब्रेरी उपयोगिता नहीं थी, लेकिन इसे फ़ंक्शन टेम्पलेट के संदर्भ में सरणी पास करके कार्यान्वित किया जा सकता है, जैसा कि ऊपर दिखाए गए। ठीक लेकिन महत्वपूर्ण बिंदु: टेम्पलेट आकार पैरामीटर एक size_t , जो कि हस्ताक्षरित Size फ़ंक्शन परिणाम प्रकार के साथ कुछ असंगत है, जी ++ कंपाइलर को समायोजित करने के लिए जो कभी-कभी टेम्पलेट मिलान के लिए size_t पर जोर देता है।

C ++ 17 के साथ और बाद में इसके बजाय std::size उपयोग किया जा सकता है, जो सरणियों के लिए विशिष्ट है।

डायनामिक रूप से कच्चे सरणी का आकार

// Example of raw dynamic size array. It's generally better to use std::vector.
#include <algorithm>            // std::sort
#include <iostream>
using namespace std;

auto int_from( istream& in ) -> int { int x; in >> x; return x; }

auto main()
    -> int
{
    cout << "Sorting n integers provided by you.\n";
    cout << "n? ";
    int const   n   = int_from( cin );
    int*        a   = new int[n];       // ← Allocation of array of n items.
    
    for( int i = 1; i <= n; ++i )
    {
        cout << "The #" << i << " number, please: ";
        a[i-1] = int_from( cin );
    }

    sort( a, a + n );
    for( int i = 0; i < n; ++i ) { cout << a[i] << ' '; }
    cout << '\n';
    
    delete[] a;
}

एक प्रोग्राम जो एक सरणी T a[n]; घोषित करता है T a[n]; जहाँ n एक रन-टाइम निर्धारित किया जाता है, कुछ संकलक के साथ संकलित कर सकता है जो भाषा विस्तार के रूप में C99 वैरिएड लंबाई सरणियों (VLAs) का समर्थन करते हैं। लेकिन VLAs मानक C ++ द्वारा समर्थित नहीं हैं। यह उदाहरण दिखाता है कि एक new[] -प्रचार के माध्यम से एक गतिशील आकार सरणी को मैन्युअल रूप से कैसे आवंटित किया जाए,

int*        a   = new int[n];       // ← Allocation of array of n items.

... तो इसका उपयोग करें, और अंत में इसे delete[] -प्रचार:

delete[] a;

यहाँ आबंटित सरणी में अनिश्चित मान हैं, लेकिन इसे केवल एक खाली कोष्ठक () जोड़कर शून्य-आरंभीकृत किया जा सकता है, जैसे: new int[n]() । आम तौर पर, मनमाने ढंग से आइटम प्रकार के लिए, यह एक मूल्य-आरंभ करता है।

कॉल पदानुक्रम में फ़ंक्शन के भाग के रूप में यह कोड अपवाद सुरक्षित नहीं होगा, क्योंकि delete[] से पहले एक अपवाद delete[] अभिव्यक्ति (और new[] बाद) एक मेमोरी लीक का कारण होगा। उस मुद्दे को संबोधित करने का एक तरीका उदाहरण के लिए एक std::unique_ptr स्मार्ट पॉइंटर के माध्यम से सफाई को स्वचालित करना है। लेकिन इसे संबोधित करने का एक आम तौर पर बेहतर तरीका यह है कि आप केवल एक std::vector उपयोग करें: यह वही है जो std::vector लिए है।

Std :: वेक्टर का उपयोग करके गतिशील आकार सरणी का विस्तार करना।

// Example of std::vector as an expanding dynamic size array.
#include <algorithm>            // std::sort
#include <iostream>
#include <vector>               // std::vector
using namespace std;

int int_from( std::istream& in ) { int x = 0; in >> x; return x; }

int main()
{
    cout << "Sorting integers provided by you.\n";
    cout << "You can indicate EOF via F6 in Windows or Ctrl+D in Unix-land.\n";
    vector<int> a;      // ← Zero size by default.

    while( cin )
    {
        cout << "One number, please, or indicate EOF: ";
        int const x = int_from( cin );
        if( !cin.fail() ) { a.push_back( x ); }  // Expands as necessary.
    }

    sort( a.begin(), a.end() );
    int const n = a.size();
    for( int i = 0; i < n; ++i ) { cout << a[i] << ' '; }
    cout << '\n';
}

std::vector एक मानक लाइब्रेरी क्लास टेम्प्लेट है जो वैरिएबल साइज़ ऐरे की धारणा प्रदान करता है। यह सभी मेमोरी प्रबंधन का ख्याल रखता है, और बफर सन्निहित है, इसलिए बफर को एक पॉइंटर (जैसे &v[0] या v.data() ) एक कच्चे सरणी की आवश्यकता के लिए एपीआई फ़ंक्शन को पास किया जा सकता है। एक vector को रन टाइम पर भी विस्तारित किया जा सकता है, उदाहरण के लिए push_back सदस्य फ़ंक्शन जो किसी आइटम को जोड़ता है।

वेक्टर push_back में शामिल push_back या मूविंग सहित n push_back ऑपरेशंस के अनुक्रम की जटिलता, O ( n ) amortized है। "प्रवर्धित": औसत पर।

आंतरिक रूप से यह आमतौर पर वेक्टर द्वारा अपने बफर आकार, इसकी क्षमता को दोगुना करने पर प्राप्त किया जाता है, जब एक बड़े बफर की आवश्यकता होती है। उदाहरण के लिए 1 के रूप में शुरू होने वाले बफर के लिए, और n = 17 push_back कॉल के लिए आवश्यकतानुसार बार-बार दोगुना किया जा रहा है, इसमें 1 + 2 + 4 + 8 + 16 = 31 कॉपी ऑपरेशन शामिल हैं, जो 2 × n = 34 से कम है। और आम तौर पर इस क्रम का योग 2 × n से अधिक नहीं हो सकता है।

डायनेमिक आकार के कच्चे सरणी उदाहरण की तुलना में, इस vector आधारित कोड को उपयोगकर्ता को सामने वाले आइटमों की संख्या की आपूर्ति (और पता) करने की आवश्यकता नहीं है। इसके बजाय वेक्टर केवल उपयोगकर्ता द्वारा निर्दिष्ट प्रत्येक नए आइटम मूल्य के लिए आवश्यक रूप से विस्तारित है।

एक निश्चित आकार का कच्चा सरणी मैट्रिक्स (जो कि 2 डी कच्चा सरणी है)।

// A fixed size raw array matrix (that is, a 2D raw array).
#include <iostream>
#include <iomanip>
using namespace std;

auto main() -> int
{
    int const   n_rows  = 3;
    int const   n_cols  = 7;
    int const   m[n_rows][n_cols] =             // A raw array matrix.
    {
        {  1,  2,  3,  4,  5,  6,  7 },
        {  8,  9, 10, 11, 12, 13, 14 },
        { 15, 16, 17, 18, 19, 20, 21 }
    };
    
    for( int y = 0; y < n_rows; ++y )
    {
        for( int x = 0; x < n_cols; ++x )
        {
            cout << setw( 4 ) << m[y][x];       // Note: do NOT use m[y,x]!
        }
        cout << '\n';
    }
}

आउटपुट:

   1   2   3   4   5   6   7
   8   9  10  11  12  13  14
  15  16  17  18  19  20  21

बहु-आयामी सरणी को अनुक्रमित करने के लिए C ++ विशेष सिंटैक्स का समर्थन नहीं करता है। इसके बजाय इस तरह के एक सरणी को सरणियों के एक सरणी (संभवतः सरणियों, और इसी तरह) के रूप में देखा जाता है, और प्रत्येक स्तर के लिए साधारण एकल सूचकांक संकेतन [ i ] का उपयोग किया जाता है। ऊपर के उदाहरण में m[y] पंक्ति को संदर्भित करता है y के m है, जहां y एक शून्य आधारित सूचकांक है। तो फिर इस पंक्ति बदले में अनुक्रमित किया जा सकता है, जैसे m[y][x] है, जो को संदर्भित करता है x या स्तंभ - - पंक्ति के वें आइटम y

यानी अंतिम सूचकांक सबसे तेजी से बदलता है, और घोषणा में इस सूचकांक की सीमा, जो यहां प्रति पंक्ति कॉलम की संख्या है, अंतिम और "अंतरतम" आकार निर्दिष्ट है।

चूंकि C ++ डायनेमिक आकार के सरणियों के लिए अंतर्निहित समर्थन प्रदान नहीं करता है, गतिशील आवंटन के अलावा, एक डायनामिक आकार मैट्रिक्स अक्सर एक वर्ग के रूप में लागू किया जाता है। फिर कच्चे सरणी मैट्रिक्स अनुक्रमण संकेतन m[y][x] की कुछ लागत होती है, या तो कार्यान्वयन को उजागर करने से (ताकि उदाहरण के लिए एक ट्रांसपोज़्ड मैट्रिक्स का एक दृश्य व्यावहारिक रूप से असंभव हो जाए) या जब यह प्रवाह के साथ हो जाए तो कुछ ओवरहेड और थोड़ी असुविधा जोड़कर operator[] से एक प्रॉक्सी वस्तु operator[] । और इसलिए इस तरह के अमूर्तता के लिए अनुक्रमण संकेतन आम तौर पर अलग-अलग होंगे, दोनों ही लुक-एंड-फील और सूचकांकों के क्रम में, उदाहरण के लिए m(x,y) या m.at(x,y) या m.item(x,y)

भंडारण के लिए std :: वेक्टर का उपयोग कर एक गतिशील आकार मैट्रिक्स।

दुर्भाग्य से C ++ 14 के रूप में C ++ मानक लाइब्रेरी में कोई डायनामिक आकार मैट्रिक्स क्लास नहीं है। मैट्रिक्स वर्गों है कि समर्थन गतिशील आकार बूस्ट मैट्रिक्स पुस्तकालय (बूस्ट पुस्तकालय के भीतर एक उप पुस्तकालय) सहित 3 पक्ष के पुस्तकालयों के एक नंबर, से तथापि उपलब्ध हैं।

यदि आप बूस्ट या किसी अन्य लाइब्रेरी पर निर्भरता नहीं चाहते हैं, तो C ++ में एक गरीब आदमी का डायनामिक आकार मैट्रिक्स जैसा है

vector<vector<int>> m( 3, vector<int>( 7 ) );

… जहां vector std::vector । मैट्रिक्स यहाँ एक पंक्ति सदिश n बार कॉपी करके बनाई गई है जहाँ n पंक्तियों की संख्या है, यहाँ 3. यह एक ही आकार प्रदान करने का लाभ है m[y][x] एक निश्चित आकार के कच्चे सरणी मैट्रिक्स के रूप में अनुक्रमण संकेतन, लेकिन यह थोड़ा अक्षम है क्योंकि इसमें प्रत्येक पंक्ति के लिए एक गतिशील आवंटन शामिल है, और यह थोड़ा असुरक्षित है क्योंकि यह संभव है कि अनजाने में एक पंक्ति का आकार बदल जाए।

एक अधिक सुरक्षित और कुशल दृष्टिकोण मैट्रिक्स के लिए भंडारण के रूप में एकल वेक्टर का उपयोग करना है, और उस वेक्टर में संबंधित कोड के लिए क्लाइंट कोड ( x , y ) को मैप करना है:

// A dynamic size matrix using std::vector for storage.

//--------------------------------------------- Machinery:
#include <algorithm>        // std::copy
#include <assert.h>         // assert
#include <initializer_list> // std::initializer_list
#include <vector>           // std::vector
#include <stddef.h>         // ptrdiff_t

namespace my {
    using Size = ptrdiff_t;
    using std::initializer_list;
    using std::vector;

    template< class Item >
    class Matrix
    {
    private:
        vector<Item>    items_;
        Size            n_cols_;
        
        auto index_for( Size const x, Size const y ) const
            -> Size
        { return y*n_cols_ + x; }

    public:
        auto n_rows() const -> Size { return items_.size()/n_cols_; }
        auto n_cols() const -> Size { return n_cols_; }

        auto item( Size const x, Size const y )
            -> Item&
        { return items_[index_for(x, y)]; }
        
        auto item( Size const x, Size const y ) const
            -> Item const&
        { return items_[index_for(x, y)]; }

        Matrix(): n_cols_( 0 ) {}

        Matrix( Size const n_cols, Size const n_rows )
            : items_( n_cols*n_rows )
            , n_cols_( n_cols )
        {}
        
        Matrix( initializer_list< initializer_list<Item> > const& values )
            : items_()
            , n_cols_( values.size() == 0? 0 : values.begin()->size() )
        {
            for( auto const& row : values )
            {
                assert( Size( row.size() ) == n_cols_ );
                items_.insert( items_.end(), row.begin(), row.end() );
            }
        }
    };
}  // namespace my

//--------------------------------------------- Usage:
using my::Matrix;

auto some_matrix()
    -> Matrix<int>
{
    return
    {
        {  1,  2,  3,  4,  5,  6,  7 },
        {  8,  9, 10, 11, 12, 13, 14 },
        { 15, 16, 17, 18, 19, 20, 21 }
    };
}

#include <iostream>
#include <iomanip>
using namespace std;
auto main() -> int
{
    Matrix<int> const m = some_matrix();
    assert( m.n_cols() == 7 );
    assert( m.n_rows() == 3 );
    for( int y = 0, y_end = m.n_rows(); y < y_end; ++y )
    {
        for( int x = 0, x_end = m.n_cols(); x < x_end; ++x )
        {
            cout << setw( 4 ) << m.item( x, y );        // ← Note: not `m[y][x]`!
        }
        cout << '\n';
    }
}

आउटपुट:

   1   2   3   4   5   6   7
   8   9  10  11  12  13  14
  15  16  17  18  19  20  21

उपरोक्त कोड औद्योगिक ग्रेड नहीं है: यह मूल सिद्धांतों को दिखाने के लिए डिज़ाइन किया गया है, और C ++ सीखने वाले छात्रों की आवश्यकताओं की सेवा करता है।

उदाहरण के लिए, कोई अनुक्रमण संकेतन को सरल बनाने के लिए operator() अधिभार को परिभाषित कर सकता है।

ऐरे इनिशियलाइज़ेशन

एक सरणी एक विशिष्ट प्रकार के चर के लिए अनुक्रमिक मेमोरी स्थानों का एक ब्लॉक है। सरणी को सामान्य चर के समान तरीके से आवंटित किया जाता है, लेकिन इसके नाम से जुड़े वर्ग कोष्ठक के साथ [] इसमें उन तत्वों की संख्या होती है जो सरणी मेमोरी में फिट होते हैं।

किसी सरणी का निम्न उदाहरण टाइप int , चर नाम arrayOfInts और तत्वों की संख्या का उपयोग करता है [5] जिसमें सरणी के लिए स्थान है:

int arrayOfInts[5];

एक सरणी को इस तरह से उसी समय घोषित किया जा सकता है और आरंभ किया जा सकता है

int arrayOfInts[5] = {10, 20, 30, 40, 50};

अपने सभी सदस्यों को सूचीबद्ध करके एक सरणी को आरम्भ करते समय, वर्ग कोष्ठक के अंदर तत्वों की संख्या को शामिल करना आवश्यक नहीं है। यह संकलक द्वारा स्वचालित रूप से गणना की जाएगी। निम्नलिखित उदाहरण में, यह 5 है:

int arrayOfInts[] = {10, 20, 30, 40, 50};

अधिक स्थान आवंटित करते समय केवल पहले तत्वों को इनिशियलाइज़ करना भी संभव है। इस मामले में, कोष्ठक में लंबाई को परिभाषित करना अनिवार्य है। निम्नलिखित आंशिक आरंभीकरण के साथ लंबाई 5 की एक सरणी आवंटित करेगा, कंपाइलर शेष सभी तत्वों को तत्व प्रकार के मानक मूल्य के साथ इस मामले में शून्य करता है।

int arrayOfInts[5] = {10,20}; // means 10, 20, 0, 0, 0

अन्य बुनियादी डेटा प्रकारों की सारणियों को उसी तरह से आरंभ किया जा सकता है।

char arrayOfChars[5]; // declare the array and allocate the memory, don't initialize

char arrayOfChars[5] = { 'a', 'b', 'c', 'd', 'e' } ; //declare and initialize

double arrayOfDoubles[5] = {1.14159, 2.14159, 3.14159, 4.14159, 5.14159};

string arrayOfStrings[5] = { "C++", "is", "super", "duper", "great!"};

यह भी ध्यान रखना महत्वपूर्ण है कि सरणी तत्वों तक पहुंचने पर, सरणी का तत्व सूचकांक (या स्थिति) 0 से शुरू होता है।

int array[5] = { 10/*Element no.0*/, 20/*Element no.1*/, 30, 40, 50/*Element no.4*/};
std::cout << array[4]; //outputs 50
std::cout << array[0]; //outputs 10


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow