मुख्य सामग्री पर जाएँ

ऐरे के तत्व और सही इंडेक्स

पाठ 7 / 1315 मिनटPDF नोट्समुफ़्त

कौन-से मान बदलते हैं

आप पूर्णांक चर का वर्तमान मान दर्ज करना जानते हैं। अब मान लें कि चार संबंधित मान एक साथ रखने हैं। उन्हें एक ऐरे में रखकर भी हम हर असाइनमेंट का एक-एक चरण में ट्रेस कर सकते हैं।

इस पाठ में आप ऐरे के सही इंडेक्स पहचानेंगे, उसके शुरुआती मान पढ़ेंगे और समझाएँगे कि असाइनमेंट किस तत्व को बदलता है। आप अलग पूर्णांक चर में बचाई गई कॉपी को ऐरे के तत्व से अलग रखेंगे और आंशिक इनिशियलाइज़र से मिलने वाले शून्यों का कारण भी समझेंगे।

पहले से आवश्यक बातें: चर, वर्तमान अवस्था का ट्रेस, सरल अंकगणित, शर्तें और मानों की कॉपी वाले बुनियादी पाठ। यहाँ पॉइंटर, लूप, स्ट्रिंग या मेमोरी एड्रेस की जानकारी आवश्यक नहीं है।

पढ़ाने के लिए हम C11 का उपयोग जारी रखते हैं। हमारे ऐरे में साधारण signed int तत्व हैं और उनका आकार स्पष्ट धनात्मक स्थिरांक है। चलाए जा सकने वाले हर उदाहरण में पढ़े गए मान पहले इनिशियलाइज़ किए गए हैं और गणना का हर पूर्णांक परिणाम −32767 से 32767 के भीतर है। हम यह नहीं मानते कि एक int चार बाइट का होता है। हर पूरा प्रोग्राम नई शुरुआत वाला अलग उदाहरण है और अलग से कंपाइल किया जा सकता है। एक जानबूझकर असुरक्षित अंश केवल वर्गीकरण के लिए स्पष्ट रूप से चिह्नित है।

एक ऐरे का नाम और कई तत्वों की जगहें

int scores[4] = {6, 2, 9, 4}; को दो हिस्सों में पढ़ें। इस घोषणा में scores[4] चार पूर्णांक तत्वों वाला ऐरे बनाता है। ब्रेसिज़ में दिया इनिशियलाइज़र क्रम से उनके शुरुआती मान देता है।

इंडेक्स0123
शुरुआती मान6294

इंडेक्स किसी जगह को पहचानता है। पहली जगह का इंडेक्स 0 है, इसलिए पढ़ने पर scores[0] से 6 और scores[1] से 2 मिलता है। चौथा और अंतिम तत्व scores[3] है। घोषित तत्वों की संख्या 4 है; वह इस ऐरे का सही इंडेक्स नहीं है।

किसी जगह और उसमें रखे मान को अलग रखें। मान 9 इंडेक्स 2 पर है। इससे ऐरे में इंडेक्स 9 वाला तत्व नहीं बन जाता। किसी तत्व में ऋणात्मक संख्या या ऐरे की लंबाई से बड़ी संख्या हो सकती है; रखी हुई संख्या सही जगहों की सीमा नहीं बदलती।

घोषणा में और बाद के व्यंजक में इन्हीं वर्ग कोष्ठकों का काम अलग है। घोषणा int scores[4] तत्वों की संख्या बताती है। बाद में scores[4] पढ़ने का अर्थ पाँचवें तत्व को पढ़ने की कोशिश होगा, जबकि इस ऐरे में वह तत्व है ही नहीं।

N तत्वों वाले ऐरे में पूर्णांक इंडेक्स i से किसी तत्व तक पहुँचने के लिए दोनों शर्तें चाहिए: i >= 0 और i < N। यहाँ व्याख्या में N तत्वों की संख्या है; वास्तविक घोषणाओं में हम 4 और 5 जैसे धनात्मक स्थिरांक लिखते हैं। अंतिम सही इंडेक्स N - 1 है। इन ऐरे-अभिगमों के लिए ऋणात्मक इंडेक्स और तत्वों की संख्या के बराबर इंडेक्स, दोनों गलत हैं।

परिचित असाइनमेंट नियम एक तत्व पर लगाएँ

scores[1] = scores[0] + scores[2]; की दाईं ओर दो तत्वों के वर्तमान मान पढ़े जाते हैं। उनका योग इंडेक्स 1 वाले तत्व में रखा जाता है। यह स्टेटमेंट हर तत्व में असाइनमेंट नहीं करता।

हर जगह के लिए एक प्रविष्टि वाला रिकॉर्ड बनाएँ:

  1. जिन तत्वों तक पहुँचना है, उनके इंडेक्स निकालें और सीमा जाँचें
  2. दाईं ओर की गणना में लगने वाले वर्तमान मान पढ़ें
  3. परिणाम निकालें
  4. चुने गए तत्व में परिणाम लिखें और बाकी प्रविष्टियाँ ज्यों की त्यों आगे रखें

हमारे स्टेटमेंट इंडेक्स बदलने और तत्व अपडेट करने को अलग रखते हैं। एक ही व्यंजक में इंडेक्स को बढ़ाने के साथ उसका दूसरा उपयोग नहीं जोड़ते। यह बुनियादी पाठ में सीखे सुरक्षित अनुक्रम का ही विस्तार है।

हल किया हुआ उदाहरण 1 सहेजा गया मान और दो तत्वों में बदलाव

ट्रेस पढ़ने से पहले पूरा आउटपुट बताएँ। scores[1] बदलने पर क्या saved भी बदलेगा?

C
#include <stdio.h>

int main(void)
{
    int scores[4] = {6, 2, 9, 4};
    int saved = scores[1];
    scores[1] = scores[0] + scores[2];
    scores[0] = saved - 1;
    printf("%d %d %d %d | %d\n",
           scores[0], scores[1], scores[2], scores[3], saved);
    return 0;
}
  • इनिशियलाइज़ेशन के बाद: scores = {6, 2, 9, 4}
  • saved = scores[1] वर्तमान मान 2 पढ़ता है। अब saved = 2 है; ऐरे नहीं बदला
  • scores[1] = scores[0] + scores[2] में 6 + 9 = 15 मिलता है। अब scores = {6, 15, 9, 4} और saved = 2 है
  • scores[0] = saved - 1 में 2 - 1 = 1 मिलता है। अब scores = {1, 15, 9, 4} और saved = 2 है
  • प्रिंट होने वाले आर्ग्युमेंट का क्रम पहले चार तत्व, फिर saved है। आउटपुट 1 15 9 4 | 2 है, जिसके बाद नई पंक्ति आती है। | केवल प्रिंट किया गया विभाजक है

उपयोग हुए सभी इंडेक्स 0 से 3 के भीतर हैं। हर असाइनमेंट एक तत्व का रखा हुआ मान बदलता है; बाकी जगहों पर पुराने मान बने रहते हैं।

saved में पूर्णांक मान की कॉपी है। वह तत्व 1 का दूसरा नाम नहीं है और उसके साथ लगातार नहीं बदलता। यदि आपने 14 15 9 4 | 15 बताया, तो सहेजी गई कॉपी को स्थायी जुड़ाव मान लिया। यदि पहला तत्व 6 ही रखा, तो तत्व पर दूसरा असाइनमेंट छोड़ दिया। यदि हर जगह 15 रख दिया, तो चुने हुए एक तत्व को पूरा ऐरे समझ लिया।

आंशिक इनिशियलाइज़ेशन बाकी शून्य देता है

धनात्मक स्थिर आकार वाले पूर्णांक ऐरे में तत्वों से कम शुरुआती मान दिए जा सकते हैं। int bins[5] = {4, -1}; में लिखी दो संख्याएँ जगह 0 और 1 को इनिशियलाइज़ करती हैं। बाकी जगह 2, 3 और 4 का शुरुआती मान शून्य होता है।

इंडेक्स01234
शुरुआती मान4−1000

आकार अभी भी पाँच है। इनिशियलाइज़र में मान न लिखने से तत्व हटता नहीं, आखिरी लिखा मान दोहराया नहीं जाता और बचा तत्व इनपुट की प्रतीक्षा में नहीं रहता। इसलिए int ready[3] = {0}; तीनों तत्वों को शून्य से शुरू करता है: पहले के लिए शून्य स्पष्ट लिखा है और बाकी दो को शून्य अपने-आप मिलता है।

यह नियम main के भीतर int bins[5]; पर न लगाएँ। उस घोषणा में कोई इनिशियलाइज़र नहीं है। उसके automatic तत्वों को शून्य मिलने की गारंटी नहीं है। पढ़ने से पहले ज्ञात मान रखें; बिना इनिशियलाइज़ किए मान पढ़कर यह तय न करें कि C में “आमतौर पर” क्या मिलता है। static storage वाले ऐरे के इनिशियलाइज़ेशन नियम अलग हैं और इस पाठ के बाहर हैं।

घोषणाओं तक पहुँचने पर इनिशियलाइज़र सूची एक बार शुरुआती मान रखती है। बाद का असाइनमेंट इनिशियलाइज़ेशन फिर शुरू नहीं करता और बाकी तत्वों को दोबारा शून्य से नहीं भरता।

हल किया हुआ उदाहरण 2 अपने-आप मिले शुरुआती मान का उपयोग

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

C
#include <stdio.h>

int main(void)
{
    int bins[5] = {4, -1};
    bins[3] = bins[0] + bins[2];
    bins[2] = bins[1] - bins[4];
    printf("%d %d %d %d %d\n",
           bins[0], bins[1], bins[2], bins[3], bins[4]);
    return 0;
}
  • घोषणा से bins = {4, -1, 0, 0, 0} मिलता है
  • bins[3] = bins[0] + bins[2] में ऑपरेंड 4 और 0 हैं। इंडेक्स 3 पर 4 रखें: {4, -1, 0, 4, 0}
  • bins[2] = bins[1] - bins[4] में ऑपरेंड −1 और 0 हैं। इंडेक्स 2 पर −1 रखें: {4, -1, -1, 4, 0}
  • आउटपुट: 4 -1 -1 4 0, फिर नई पंक्ति

पहले असाइनमेंट में bins[2] को पढ़ना सही है: उसका अपने-आप मिला शुरुआती मान शून्य है। बाद का असाइनमेंट उसी तत्व को −1 कर देता है। अपने-आप मिला शून्य शुरुआती मान है, हमेशा बने रहने वाली पाबंदी नहीं।

4 की पाँच कॉपियाँ या अंत में −1 की तीन कॉपियाँ लिखना इनिशियलाइज़र सूची को गलत पढ़ना होगा। bins[4] को बिना इनिशियलाइज़ हुआ बताना भी गलत होगा, क्योंकि इस इनिशियलाइज़ किए गए ऐरे के बचे तत्वों पर शून्य वाला नियम लागू है। फिर भी bins[5] पढ़ना गलत है; आंशिक इनिशियलाइज़ेशन घोषित आकार के बाहर कोई अतिरिक्त तत्व नहीं बनाता।

इंडेक्स की गणना भी हो सकती है

कोष्ठकों के भीतर पूर्णांक व्यंजक हो सकता है। k का उपयुक्त मान होने पर scores[k] वर्तमान k की बताई जगह चुनता है, जबकि scores[k - 1] पिछली जगह चुनता है। हर निकले हुए इंडेक्स को अलग जाँचें। k सही होने से k - 1 या k + 1 अपने-आप सही नहीं हो जाता।

चार तत्वों वाले scores में k = 0 होने पर scores[k] सही है, पर scores[k - 1] नहीं। k = 3 होने पर scores[k] सही है, पर scores[k + 1] नहीं। बाद में इंडेक्स चर बदलने से पहले हुआ ऐरे अपडेट वापस नहीं होता। उससे यह बदलता है कि अगला व्यंजक कौन-सी जगह चुनेगा।

हल देखने से पहले अभ्यास करें

ये चार मौलिक प्रश्न सीखने के लिए हैं और इनके अंक नहीं हैं। निश्चित व्यवहार वाले प्रोग्राम में आउटपुट के साथ बीच की ऐरे अवस्थाएँ भी लिखें। प्रश्न 3 वर्गीकरण और सुधार का प्रश्न है: उसका असुरक्षित अंश न चलाएँ।

अभ्यास 1 बदलता हुआ इंडेक्स

आउटपुट बताएँ। समझाएँ कि असाइनमेंट किस जगह को बदलता है और k बदलने के बाद कौन-सी जगह चुनी जाती है।

C
#include <stdio.h>

int main(void)
{
    int rack[5] = {8, 3, 6, 1, 4};
    int k = 2;
    rack[k] = rack[k - 1] + rack[k + 1];
    k = k + 1;
    printf("%d %d %d\n", rack[2], rack[k], k);
    return 0;
}

अभ्यास 2 दो अलग इनिशियलाइज़र सूचियाँ

दोनों अंतिम ऐरे और प्रिंट होने वाली तिकड़ी बताएँ। क्या {2} ऐरे को 2 की कॉपियों से भर देता है?

C
#include <stdio.h>

int main(void)
{
    int first[4] = {2};
    int second[4] = {2, 2, 2, 2};
    first[3] = first[0] + second[1];
    second[0] = first[1];
    printf("%d %d %d\n", first[3], second[0], first[1]);
    return 0;
}

अभ्यास 3 अंतिम इंडेक्स का वर्गीकरण और सुधार

उद्देश्य तीन तत्वों वाले ऐरे के पहले और अंतिम तत्व को जोड़ना है। नीचे का अंश जानबूझकर असुरक्षित है। इसे केवल पढ़ें; आउटपुट वाले प्रश्न की तरह कंपाइल या निष्पादित न करें।

int data[3] = {2, 5, 8};
int total = data[0] + data[3];

क्या C11 total के लिए कोई निश्चित संख्यात्मक मान बताता है? गलत अभिगम पहचानें, फिर बताए उद्देश्य के लिए केवल उसका इंडेक्स बदलें। सुधारी गई गणना का परिणाम दें।

अभ्यास 4 अभिगम से पहले गार्ड

दोनों if का ट्रेस करें। अंतिम ऐरे दें और समझाएँ कि पहले चुना गया इंडेक्स इस प्रोग्राम में गलत ऐरे-अभिगम क्यों नहीं कराता।

C
#include <stdio.h>

int main(void)
{
    int cells[3] = {4, 6, 8};
    int index = -1;
    if (index >= 0 && index < 3) {
        cells[index] = 9;
    }
    index = 2;
    if (index >= 0 && index < 3) {
        cells[index] = 9;
    }
    printf("%d %d %d\n", cells[0], cells[1], cells[2]);
    return 0;
}

सामान्य पूर्णांक इंडेक्स के लिए ऊपरी जाँच को index <= 3 कर दें, तो क्या तीन तत्वों वाला ऐरे अब भी सुरक्षित रहेगा? उत्तर तय करने वाली सीमा समझाएँ।

पूरे हल और गलत उत्तरों का कारण

अभ्यास 1 का हल

शुरुआत में k = 2 और rack = {8, 3, 6, 1, 4} है। असाइनमेंट का गंतव्य इंडेक्स 2 है और स्रोत इंडेक्स 2 - 1 = 1 तथा 2 + 1 = 3 हैं। तीनों 0 से 4 के भीतर हैं।

rack[1] = 3 और rack[3] = 1 पढ़ें; उनका योग 4 है। इसे इंडेक्स 2 पर रखें, जिससे rack = {8, 3, 4, 1, 4} मिलता है। अगला k = k + 1 ऐरे बदले बिना k = 3 कर देता है। प्रिंट में rack[2] = 4, rack[3] = 1 और k = 3 पढ़े जाते हैं। आउटपुट: 4 1 3, फिर नई पंक्ति।

4 4 3 मानता है कि k बदलने पर भी rack[k] पहले चुने हुए तत्व को ही बताता रहता है। 6 1 3 ऐरे पर हुए असाइनमेंट को छोड़ देता है। जोड़ में 8 और 6 लेने से जगह 1 और 3 के बजाय जगह 0 और 2 पढ़ी जाती हैं; k - 1 और k + 1 का इंडेक्स फिर निकालें।

अभ्यास 2 का हल

घोषणाओं से first = {2, 0, 0, 0} और second = {2, 2, 2, 2} मिलता है। केवल पहले ऐरे की सूची में कुछ शुरुआती मान नहीं लिखे गए हैं।

first[3] = first[0] + second[1] में 2 + 2 = 4 मिलता है, इसलिए first = {2, 0, 0, 4} हो जाता है। फिर second[0] = first[1] में first के इंडेक्स 1 वाला शून्य पढ़कर second में रखा जाता है। अंतिम ऐरे first = {2, 0, 0, 4} और second = {0, 2, 2, 2} हैं। आउटपुट: 4 0 0, फिर नई पंक्ति।

4 2 2 लिखे हुए 2 को छोड़ी गई जगहों पर दोहराता है। 4 4 0 वहाँ first[3] पढ़ता है जहाँ कोड में first[1] है। कुछ तत्वों के मान बराबर होने पर भी दोनों ऐरे अलग रहते हैं।

अभ्यास 3 का हल

सही इंडेक्स 0, 1 और 2 हैं। data[3] इस ऐरे के बाहर पढ़ने की कोशिश करता है। अंश में अपरिभाषित व्यवहार है; C11 total के लिए कोई निश्चित संख्यात्मक मान नहीं देता। कोई संख्या, शून्य या क्रैश दिख जाने से भाषा का सही नियम सिद्ध नहीं होता। आंशिक इनिशियलाइज़र वाला नियम ऐरे के बाहर की जगह के बारे में कुछ नहीं बताता।

data[3] की जगह data[2] रखें। सुधरा हुआ प्रोग्राम है:

C
#include <stdio.h>

int main(void)
{
    int data[3] = {2, 5, 8};
    int total = data[0] + data[2];
    printf("%d\n", total);
    return 0;
}

यह पहला मान 2 और अंतिम मान 8 पढ़ता है, 10 निकालता है और 10 के बाद नई पंक्ति प्रिंट करता है। data[1] लेने पर 7 मिलेगा, लेकिन वह पहले और बीच के तत्व का जोड़ होगा, जो प्रश्न का उद्देश्य नहीं है। ऐरे का आकार बढ़ाना केवल इंडेक्स सुधारने के बजाय दिए हुए प्रश्न को बदल देगा।

अभ्यास 4 का हल

शुरुआत में cells = {4, 6, 8} और index = -1 है। पहली तुलना index >= 0 गलत है। && दूसरी तुलना को छोड़ देता है, if की शर्त गलत होती है और cells[index] वाली body नहीं चलती। −1 का उपयोग करके ऐरे तक कोई अभिगम नहीं होता।

index = 2 के बाद दूसरी शर्त की दोनों तुलनाएँ सही हैं: 2 गैर-ऋणात्मक है और 3 से छोटा है। body cells[2] में 9 लिखती है। अंतिम ऐरे {4, 6, 9} है और आउटपुट 4 6 9 है, जिसके बाद नई पंक्ति आती है।

इन तत्वों तक पहुँचने के सही गार्ड में दोनों सीमाएँ चाहिए। index <= 3 से इंडेक्स 3 भी स्वीकार होगा, जबकि वह अंतिम सही इंडेक्स 2 से एक आगे है। दिए हुए दोनों चरणों का परिणाम संयोग से नहीं बदलेगा, लेकिन हर पूर्णांक इंडेक्स के लिए यह सही गार्ड नहीं है। केवल index < 3 जाँचने पर ऋणात्मक इंडेक्स भी स्वीकार होंगे। गार्ड को तत्व तक पहुँचने से पहले निर्णय लेना चाहिए; बाद की जाँच पहले हो चुके गलत अभिगम को ठीक नहीं कर सकती।

आगे बढ़ने से पहले

समझाएँ कि घोषणा में संख्या 4 लिखने से इंडेक्स 4 सही क्यों नहीं होता और {2} तथा {2, 2, 2, 2} चार तत्वों को अलग शुरुआती अवस्थाएँ क्यों देते हैं। जब वर्तमान इंडेक्स न खोते हुए हर तत्व की अवस्था का ट्रेस कर सकें, तो अगले पाठ के लिए तैयार हैं। आगे हम लूप से कई तत्वों तक जाएँगे और समझेंगे कि चलता हुआ योग या गिनती क्या बताता है।

स्रोत टिप्पणी

उदाहरण, ट्रेस, अभ्यास और समझाने वाले वाक्य मौलिक हैं। तथ्यों की जाँच WG14 N1570 C11 समिति-ड्राफ्ट से की गई: ऐरे प्रकार §6.2.5p20; सबस्क्रिप्ट §6.5.2.1p2; सीमाएँ §6.5.6p8; इनिशियलाइज़ेशन §§6.7.9p10, p17, p21; स्थिर ऐरे-आकार की शर्त §6.7.6.2p1; सरल असाइनमेंट §6.5.16.1p2; शॉर्ट सर्किट §6.5.13p4। संदर्भ: https://open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

C11 इस पाठ्यक्रम में पढ़ाने के लिए चुना गया संस्करण है; इसे GATE द्वारा निर्धारित संस्करण नहीं बताया जा रहा। यह पाठ ऐरे की शुरुआती समझ तक सीमित है, पूरी C भाषा या पूरा GATE CS पाठ्यक्रम नहीं है।

सूत्र और नियम

  • int a[4] = {6, 2, 9, 4}; में चार तत्व हैं, जिनके इंडेक्स 0 से 3 हैं
  • इंडेक्स जगह चुनता है; वह वहाँ रखा हुआ मान नहीं है
  • N तत्वों के लिए पूर्णांक तत्व-इंडेक्स में 0 <= i और i < N दोनों सही होने चाहिए
  • चुने हुए एक गंतव्य का ट्रेस करें और न बदले तत्व आगे वैसे ही रखें
  • a[i] से इनिशियलाइज़ हुआ पूर्णांक चर, वह तत्व बदलने के बाद भी अपना कॉपी हुआ मान रखता है
  • धनात्मक स्थिर आकार वाले पूर्णांक ऐरे की इनिशियलाइज़र सूची में बचे तत्व शून्य से शुरू होते हैं
  • बिना इनिशियलाइज़र वाले automatic ऐरे को शून्य मिलने की गारंटी नहीं है
  • हर गणना किया इंडेक्स जाँचें। सही k से सही k - 1 या k + 1 की गारंटी नहीं मिलती
  • गलत अभिगम व्यवहार-वर्गीकरण के प्रश्न हैं, किसी संख्या वाले आउटपुट की पहेली नहीं

इस पाठ के नोट्स

प्रगति सहेजने के लिए साइन इन करें। साइन इन