Wednesday, April 8, 2009

सीखिए सी - 5: सी प्रोग्राम की विशेषताएं - 2 और 3

# include < stdio.h >

यह सी प्रोग्राम की दूसरी विशेषता है।

यह उक्ति पूर्वसंकलक (प्रीकंपाइलर) के लिए है। किसी भी सी प्रोग्राम को संकलित करने से पहले एक पूर्वसंकलक उस प्रोग्राम को जांचता है, और उसमें कुछ कोड पंक्तियां जोड़ता है।

लगभग सभी सी प्रोग्रामों की कुछ आम आवश्यकताएं होती हैं, जैसे कंप्यूटर की स्मृति में विद्यमान सामग्री को स्क्रीन पर लाना (आउटपुट), प्रयोक्ता द्वारा दी गई सूचनाओं को अथवा प्रोग्राम द्वारा निर्मित सूचनाओं को स्मृति में सहेजना (इनपुट)। इसके अलावा कुछ ऐसे प्रकार्य (फंक्शन) भी हैं, जिनकी बार-बार आवश्यकता पड़ती है, जैसे, फाइलों में लिखना, उन्हें पढ़ना, उनमें कुछ जोड़ना, उन्हें खोलना, बंद करना या डिलीट करना, नई फाइल बनाना आदि, अथवा गणित से जुड़े कुछ प्रकार्य, जैसे, किसी संख्या का वर्गमूल निकालना, किसी कोण का साइन, कोसाइन आदि का पता लगाना, इत्यादि। इस तरह के अन्य सामान्य प्रकार्य भी हैं। इन सबके लिए हर बार नए सिरे से कोड लिखने की आवश्यकता को कम करने के लिए सी के पूर्वसंकलक में इनसे संबंधित कोड पहले से ही विद्यमान रहते हैं। इन्हें अलग-अलग लाइब्रेरियों में व्यवस्थित किया गया है और उन लाइब्रेरियों में विद्यमान फंक्शनों के प्रोटोटाइपों (यह क्या है नीचे समझाया गया है) की अलग सूची भी बनाई गई हैं, जिन्हें हेडर फाइलें कहा जाता है। stdio.h ऐसा ही एक हेडर फाइल का नाम है।

stdio एक संक्षेपण है और उसका पूरा रूप है standard input and output. इस हेडर फाइल में ऐसे प्रकार्यों (फंक्शनों) के प्रोटोटाइप हैं, जो इनपुट और आटपुट को सुगम बनाते हैं। प्रोग्राम 1 में जो printf() फंक्शन का प्रयोग किया गया है, वह इसी हेडर का एक फंक्शन है। इस फंक्शन का पूरा संकलित कोड पूर्वसंकलक में पहले से मौजूद है। इसलिए हमें इनपुट या आटपुट के कोड स्वयं लिखने की आवश्यकता नहीं है। हमें केवल उस फंक्शन का नाम भर अपने प्रोग्राम में लेना है और उससे संबंधित सी लाइब्रेरी के हेडर फाइल का उल्लेख # include उक्ति में कर देना है। बाकी काम पूर्वसंकलक कर देता है।

आप ध्यान दें कि stdio के आगे .h है। यह बताता है कि यह एक हेडर फाइल है। हेडर फाइल में सी में पहले से ही मौजूद फंकश्नों के नामों की सूची रहती है। यदि आप stdio.h फाइल को खोलकर देखें, तो उसमें आपको बीसियों फंक्शनों के नाम दिखाई देंगे, इनमें आपको printf() भी मिलेगा।

stdio.h में आपको printf() का कोड नहीं मिलेगा, वह संकलित रूप में अलग-अलग सी लाइब्रेरियों में रहता है। हेडर फाइलों में केवल फंक्शन के प्रोटोटाइप (अर्थात एक विशेष शैली में लिखा हुआ फंक्शन का नाम, घबराइए नहीं, फंक्शन प्रोटोटाइप क्या बला होते हैं, इसकी चर्चा नीचे दी गई है) होते हैं। इन फंक्शन प्रोटोटाइपों को देखकर पूर्वसंकलक आपके प्रोग्राम के संकलन के पहले उस फंक्शन से संबंधति कोड को आपके प्रोग्राम में ठीक स्थान पर लगा देता है, और उसके बाद आपके प्रोग्राम का संकलन होता है और .obj और .exe फाइलें बनती हैं।

एक चीज और ध्यान देने की है, वह है stdio.h को घेरे हुए कोणीय कोष्ठक (अर्थात < और >)। ये महत्वपूर्ण हैं। इनसे पूर्वसंकलक को पता चलता है कि stdio.h फाइल के लिए उसे वहां खोजना है, जहां संकलक ने सभी सी लाइब्रेरियों और उनके हेडर फाइलों को संचित किया है। आप stdio.h को दुहरे उद्धरण चिह्नों से भी घेर सकते हैं, ऐसे #include “stdio.h”। ऐसा करने से पूर्वसंकलक stdio.h फाइल के लिए पहले उस निर्देशिका (डाइरेक्ट्ररी) में ढूंढ़ता है जिसमें आपका प्रोग्राम संचित है। यदि उसे वह वहां न मिले, तो पूर्वसंकलक stdio.h फाइल के लिए अन्य निर्देशिकाओं में खोज करता है। कई बार प्रोग्रामरों को अपने लिखे हुए कुछ फलनों (फंक्शनों) का बारबार भिन्न-भिन्न प्रोग्रामों में उपयोग करना पड़ता है। सुविधा के लिए वे इन सब फलनों को एक हेडर फाइल में संचित करके उसे कोई नाम दे देते हैं, जैसे jaihindi.h। अब वे अपने प्रोग्रामों में

#include “jaihindi.h”

वाला पूर्वसंकलक निर्देश जोड़कर इन फंक्शनों को सीधे आह्वान कर सकते हैं, और उनका कोड उन्हें दुबारा लिखना नहीं पड़ता।
इस तरह के हेडर फाइलों को प्रयोक्ता-परिभाषित हेडर फाइल कहा जाता है, और ये पूर्वसंकलक में पहले से ही विद्यमान हेडर फाइलों से भिन्न होते हैं। हेडर फाइलों को उद्धरण चिह्नों (“ और ”) अथवा कोणीय कोष्ठकों (< और >) से घेरकर हम पूर्वसंकलक को बताते हैं कि यह प्रयोक्ता द्वारा लिखा गया हेडर फाइल हैं या सी का अपना कोई हेडर फाइल, और उसे पूर्वसंकलक को कहां ढूंढ़ना है, उस निर्देशिका में जिसमें वह प्रोग्राम संचित है जिसमें यह निर्देश आया है, अथवा उस निर्देशिका में जिसमें सी की सभी हेडर फाइलें संचित हैं।

#include वाले पूर्वसंकलक उक्ति के बारे में कुछ और महत्वपूर्ण बातें।

1. इसे अलग पंक्ति में लिखना जरूरी है और # वाला चिह्न पंक्ति के प्रथम स्थान पर आना चाहिए।
अर्थात, इसे यों लिखना गलता होगा:-

abcddx #include ......

2. सी की उक्तियों के अंत में ; (अर्ध विराम चिह्न) रहता है, लेकिन पूर्वसंकलक से संबंधित उक्तियों के अंत में अर्ध विराम चिह्न ; नहीं रहता है। इसलिए यों लिखना गलत है:-

#include “stdio.h”;

और अब सी की कुछ प्रमुख हेडर फाइलों की चर्चा हो जाए, जिनका आप बारबार उपयोग करेंगे।

math.h
इसमें वर्ग मूल निकालने, किसी संख्या का घात निकालने, किसी कोण का साइन, कोसाइन, टेंजेंट, कोटेंजेंट आदि निकालने, इत्यादि के फंक्शनों के प्रोटोटाइप रहते हैं।

conio.h
यह भी stdio.h के समान है और इसमें भी इनपुट-आउटपुट से संबंधित फंक्शनों के प्रोटोटाइप रहते हैं। इस हेडर के फंक्शनों का उपयोग सी++ में अधिक होता है, न कि सी में।

string.h
इसमें स्मृति और स्ट्रिंग से संबंधित फंक्शनों के प्रोटाटाइप रहते हैं, उदाहरण के लिए, किसी दिए गए स्ट्रिंग में से कुछ वर्णों को छांटकर उपस्ट्रिंग बनाने के फंक्शन, किसी स्ट्रिंग को तोड़कर दो स्ट्रिंगों में बांटने के फंक्शन, किसी स्ट्रिंग के वर्णों को उलटने के फंक्शन (यानी jaihindi को idnihiaj बना देना), इत्यादि फंक्शनों के प्रोटोटाइप रहते हैं।

फंक्शन और फंक्शन प्रोटोटाइप
इस लेख में फंक्शन प्रोटोटाइप बारबार आया है, और आप सोच रहे होंगे ये क्या होते हैं। तो आपको संक्षिप्त में बता देते हैं। जब आप किसी फंक्शन का उपयोग करते हैं, तो वह कुछ डेटा टाइपों पर कार्य करता है, उन पर गणना करता है, या उन्हें अन्य रीति से बदलता है, और फिर बदली हुई चीज को उसे बुलानेवाले फंक्शन को लौटा देता है। यह सब कंप्यूटर की स्मृति का उपयोग करके किया जाता है। इसलिए किसी भी फंक्शन का उपयोग करने से पहले संकलक को उसके लिए पर्याप्त स्मृति आवंटित करना होता है। अब संकलक को कैसे पता चले कि किसी फंक्शन को कितनी स्मृति चाहिए होगी। यहीं फंक्शन प्रोटोटाइप का महत्व है। संकलक फंक्शन प्रोटोटाइप को देखकर समझ जाता है कि यह फंक्शन किस तरह के डेटा टाइपों पर कार्य करता है और किस डेटा टाइप को अपने परिणाम के रूप में लौटा है, और इस जानकारी के आधार पर वह फंक्शन के लिए स्मृति आवंटित करता है।

फंक्शन, डेटा टाइप आदि पर आगे चर्चा होगी, और इन्हें पूरी तरह समझे बिना आप ठीक से समझ भी नहीं पाएंगे कि प्रोटोटाइप क्या हैं। मैंने सिर्फ आपकी जिज्ञासा शांत करने के लिए यहां थोड़ा सा संकेत भर कर दिया है।

सी के फंक्शन क्या होते हैं, इसे आम जीवन के एक उदाहरण से स्पष्ट करने की कोशिश करता हूं।

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

अब आपको एक फंक्शन प्रोटोटाइप का हुलिया भी दिखा दूं। वह ऐसा दिखेगा:-

int calculate (char);

यह calculate नामक किसी फंक्शन का प्रोटोटाइप है। इसमें जो पहले int आया है, वह ऊपर के उदाहरण के आटे के बराबर है, गोल कोष्ठकों में जो char आया है, वह गेहूं के बराबर है। और ध्यान दीजिए, उसके अंत में ; (अर्ध विराम है) जो सी की हर उक्ति के अंत में होता है।

लेख बहुत लंबा हो गया है, इसलिए यहीं समाप्त करता हूं। यदि इसकी बहुत सी बातें समझ में न आए तो घबराइए मत। आगा-आगे सब साफ हो जाएगा, बस अंत तक साथ बने रहिए।

5 comments:

  1. बालसुब्रमण्यम जी,

    बहुत सही शब्दों में आपने हेडर फाइलों एवं उनको जोड़ने के कारणों तथा जोड़ने के सही धंग का वर्णन किया है। इस तरह के लेख हिन्दी में लिखे जाने चाहिये। प्रथम् दृष्ट्या लगता है कि इसकपढ़ने वाले बहुत कम हैं किन्तु ऐसा नहीं है। कोई भी काम धीरे-धीरे ही होता है। एक बार लोगों का विश्वास जाग गया कि हिन्दी में भी सी-प्रोग्रामिंग के बारे में अच्छी जानकारी उपलब्ध है तो लोग बार-बार आयेंगे।

    आगे भी ऐसे ही लिखते रहे।

    ReplyDelete
  2. बहुत बढिया जानकारी...

    ReplyDelete
  3. थेंकस्. बहोत बहोत आभार.माननीयश्री મારે સ્કૂલમાં સી ભાષા શીખવવાની છે. પણ સરકારી ટેક્સબુકમાં જે સમજ ન પડી તે તમે ખુબ જ ઓછા શબ્દો દ્વારા સમજાવી દીધું. - પ્રદિપ પટેલ, અમદાવાદ

    ReplyDelete
  4. आप बहुत अच्छे शिक्षक हैं।

    ReplyDelete