Friday, June 19, 2009

27.. सीखिए सी : फंक्शन - सामान्य परिचय

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

एक उदाहरण लेते हैं, रोटी बनाने का उदाहरण। नरम-गरम, सुस्वादु रोटी बनाना एक अत्यंत मुश्किल काम है। पर यदि हम उसके बनने की प्रक्रिया को छोटे-छोटे चरणों में बांटकर देखें तो वह बहुत ही सरल प्रतीत होगी – रोटी बनाने के चरण ये होते हैं, –

1. बाजार से गेहूं लाना।
2. गेंहूं से कंकड़-कचरा बीनना।
3. गेंहूं को चक्की में ले जाकर पिसवाना।
4. आटे को गूंथना।
5. रोटी बेलना।
6. बेली हुई रोटी को तवे पर सेंकना।
7. तवे पर सिंकी रोटी को आंच पर फुलाना।
8. तैयार रोटी पर घी मलना।

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

यही अभिगम सी प्रोग्रामिंग में भी अपनाया जाता है। किसी भी समस्या को अधिक सरल छोटी समस्याओं में तोड़ा जाता है, और फिर प्रत्येक छोटी समस्या के लिए कोड लिखा जाता है। फिर इन कोडों को समायोजित किया जाता है, जिससे मूल समस्या का हल प्राप्त हो जाता है।

इस प्रक्रिया को अंजाम देने में हमें सी की फंक्शन नामक संरचना मदद करती है। फंक्शन वास्तव में एक छोटा सी प्रोग्राम ही होता है। प्रत्येक फंक्शन मूल समस्या के किसी एक छोटे पहलू का ही समाधान कर सकता है। पर कई फंक्शन मिलकर पूरी समस्या का हल कर डालते हैं।

हर सी प्रोग्राम में एक मूल फंक्शन होता है जो अन्य सभी फंक्शनों को समायोजित करता है और उन्हें यथा समय और यथा स्थान बुलाता है और उनसे आवश्यक काम करा लेता है। इस मूल फंक्शन को main फंक्शन कहा जाता है। आप इस फंक्शन से परिचित हैं, क्योंकि अब तक हमने जितने भी प्रोग्राम लिखे हैं उन सबमें वह विद्यामान रहा है। सच तो यह है कि सी के सभी प्रोग्राम में वह अनिवार्य रूप से रहता है।

आइए, इन सब बातों को हम वास्तविक कोड का उदाहरण लेकर समझते हैं। हम ऐसा एक प्रोग्राम लिखेंगे, जो दो संख्याओं को जोड़कर उनका योगफल हमें बताएगा।

पहले हम फंक्शनों का प्रयोग बिना किए यह प्रोग्राम लिखेंगे।

प्रोग्राम – 25
---------------------------------
/*function ka udaharan - 1*/

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

void main()
{
int a, b, c;
clrscr();
printf("\nDo sankhyaein darj kijiye: ");
scanf("%d%d", &a, &b);
printf("\n%d aur %d", a,b);
flushall();
c=a+b;
printf("\nAapne jo sandhyaein darj kien, unka yogphal hai, %d", c);

getchar();
}
---------------------------------

आउटपुट
---------------------------------
Do sankhyaein darj kijiye: 4 5
Aapne jo sandhyaein darj kien, unka yogphal hai, 9
---------------------------------

यह सीधा सा प्रोग्राम है जो दो संख्याओं का योगफल देता है। इसमें हमने फंक्शन का प्रयोग नहीं किया है। आइए देखें इस प्रोग्राम में हम फंक्शन का प्रयोग कैसे कर सकते हैं।

इस प्रोग्राम में एक ही मुख्य समस्या है, दो संख्याओं का योगफल प्राप्त करना। इसलिए हम इसी के लिए फंक्शन लिखेंगे। जो इस प्रकार होगा –

int yogphal (int a, int b)
{
int c;
c=a+b;
return c;
}

उपर्युक्त कोड खंड एक सरल फंक्शन है। वह केवल एक काम करता है, यानी दो संख्याओं का योगफल निकालकर उसे return करता है, यानी वापस भेजता है। आइए अब इस फंक्शन की चीर-फाड़ करते हैं।

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

हर फंक्शन का एक टाइप (प्रकार) होता है, अर्थात वह किसी एक प्रकार की राशि को return करता है, यानी वापस भेजता है। यह टाइप सी की राशियों के विभिन्न टाइपों में से कोई हो सकता है, मसलन, int, char, float, long, इत्यादि। इनके अलावा यह टाइप अधिक जटिल प्रोयक्ता-परिभाषित टाइप भी हो सकता है, जैसे सरणी (array),struct, union, आदि। इनके बारे में हमने अभी सीखा नहीं है, आगे सीखेंगे।

फंक्शन के टाइप यानी प्रकार को दर्शाने के लिए उसके नाम से पहले उस टाइप के लिए जो कुंजी शब्द हो, उसे लिख दिया जाता है। हमारा उपर्युक्त फंक्शन दो int राशियों को जोड़ता है, जिससे योगफल के रूप में एक int राशि ही प्राप्त होती है, जिसे ही यह फंक्शन लौटा है। इसलिए हमारे उपर्युक्त फंक्शन का टाइप int है। इसलिए हम लिखेंगे –

int yogphal

फंक्शन किन्हीं राशियों पर कुछ कार्य करता है। ये राशियां उसे बुलानेवाला दूसरा फंक्शन उसे देता है। फंक्शन को कोई राशि देने की रीति होती है उन्हें फंक्शन के गोल कोष्ठकों में रखना। फंक्शन के गोल कोष्टकों में राशियों को रखते समय उनका प्रकार स्पष्ट करना आवश्यक है। हमारे उदाहरण में, yogphal फंक्शन दो int प्रकार की संख्याओं को जोड़ता है। इसलिए उसे दो int प्रकार की राशियां दी जाएंगी। इसलिए उसे ये राशियां देने की विधि यह होगी –

int yogphal (int a, int b)

इस पंक्ति में आया प्रथम शब्द int फंक्शन के प्रकार को सूचित करता है। yogphal फंक्शन का नाम है। और उसके गोल कोष्ठक में जो दो int प्रकार की राशियां, वे उसे बुलाने वाले फंक्शन ने उसे दी है।

इसके बाद आते हैं धनु कोष्ठक, जिनके अंदर फंक्शन के कोड की उक्तियां रहती हैं। हमारे फंक्शन में ये उक्तियां हैं –

int c;
c=a+b;
return c;

अब पूरे फंक्शन का हुलिया एक बार फिर देख लीजिए –

int yogphal (int a, int b)
{
int c;
c=a+b;
return c;
}

आप सोच रहे होंगे, कि यह फंक्शन काम कैसे करता होगा। हर फंक्शन तभी काम करेगा जब कोई अन्य फंक्शन, जिसमें main भी शामिल है, उसे बुलाए, और उसे आवश्यक राशियां प्रदान करे। फंक्शन के हमारे इस उदाहरण में यह काम main करेगा, इस तरह –

void main()
{
int a, b, c;
clrscr();
printf("\nDo sankhyaein darj kijiye: ");
scanf("%d%d", &a, &b);
flushall();
c=yogphal (a,b);
printf("\nAapne jo sandhyaein darj kien, unka yogphal hai, %d", c);

getchar();
}

यह पहले वाला ही प्रोग्राम है, केवल एक अंतर है। इसमें दोनों संख्याओं को जोड़ने वाला व्यंजक नहीं है, उसके स्थान पर यह पंक्ति है –

c=yogphal(a, b);

इसी पंक्ति में yogphal फंक्शन का आह्वान किया गया है। आह्वान करने की रीति यह है – फंक्शन का नाम लिखकर उसके गोल गोष्ठकों में उन राशियों को रखना जिन्हें हम उस फंक्शन को उपलब्ध कराना चाहते हैं। इस बार इन राशियों का प्रकार सूचक शब्द (int, char, आदि) लिखने की जरूरत नहीं है, क्यों इन राशियों को घोषित करते समय हमने उनका प्रकार भी प्रोग्राम को बता दिया है, जिसे कंप्यूटर याद रखता है।

आपने ध्यान दिया होगा कि फंक्शन का आह्वान करते समय, उसे एक अन्य राशि c के साथ = चिह्न द्वारा जोड़ा गया है, यानी यह फंक्शन एक तरह से c में कोई मान आरोपित कर रहा है, उसी तरह जैसे इस व्यंजक में –

c=5;

फंक्शन कोई न कोई मान वापस लौटाता है। हमारा yogphal फंक्शन भी एक मान लौटाता है। यदि आप yogphal फंक्शन को जांचें, तो आपको उसकी अंतिम पंक्ति के रूप में यह उक्ति नजर आएगी –

return c;

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

main प्रोग्राम की c राशि yogphal फंक्शन द्वारा लौटाई गई इस राशि को प्राप्त करती है।

इस पंक्ति के बाद main प्रोग्राम में c का मान वही होगा जो yogphal फंक्शन ने उसे दिया है।

इसका प्रमाण है, main फंक्शन की यह पंक्ति जो c के मान को कंप्यूटर स्क्रीन पर छापती है –

printf("\nAapne jo sandhyaein darj kien, unka yogphal hai, %d", c);

कंप्यूटर स्क्रीन में c की जगह a और b का योगफल छपता है।

यह रहा पूरे प्रोग्राम का कोड।

प्रोग्राम – 26
---------------------------------
/*function ka udaharan - 2*/

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

int yogphal (int a, int b)
{
int c;
c=a+b;
return c;
}

void main()
{
int a, b, c;
clrscr();
printf("\nDo sankhyaein darj kijiye: ");
scanf("%d%d", &a, &b);
flushall();
c=yogphal (a,b);
printf("\nAapne jo sandhyaein darj kien, unka yogphal hai, %d", c);

getchar();
}
---------------------------------

आउटपुट
---------------------------------
Do sankhyaein darj kijiye: 4 5
Aapne jo sandhyaein darj kien, unka yogphal hai, 9
---------------------------------

यह प्रोग्राम भी वही आउटपुट देता है, जो प्रोग्राम – 25 ने दिया था, पर इसके कोड में काफी अंतर है। इसमें संख्याओं को जोड़ने का काम main में नहीं किया गया है, बल्कि yogphal फंक्शन में किया गया है।

ध्यान दीजिए कि हमने फंक्शन yogphal के कोड को main के कोड से पहले रखा है। यह बहुत जरूरी है। अन्यथा कंप्यूटर को पता नहीं चल पाएगा कि yogphal फंक्शन जैसे किसी फंक्शन का अस्तिव है तथा उसमें घोषित राशियों के लिए (इस उदाहरण में int c) उसे कितनी स्मृति आरक्षित करनी है।

फंक्शन की अवधारणा प्रोग्रामन भाषाओं की एक अत्यंत महत्वपूर्ण अवधारणा है। इसलिए हम उसे विस्तार से अनेक लेखों में समझेंगे। इस लेख को हम यहीं समाप्त करते हैं।

यदि आप चाहें, तो इस लेख में दिए गए प्रोग्राम - 26 को इस तरह परिवर्तित करके देख सकते हैं कि वह योगफल की जगह दो संख्याओं का गुणनफल निकाल कर दे। इससे आपको फंक्शन लिखने का अभ्यास भी हो जाएगा।

Thursday, June 18, 2009

26. सीखिए सी : switch संरचना

पिछले एक लेख में हमने बताया था कि सी भाषा में विशाखन की मुख्य संरचना if...else वाली संरचना है। लेकिन जब बहुत सारे विकल्प हों, तो if...else संरचना अव्यवस्थित हो जाती है और उसे ठीक तरह से लिखना कठिन हो जाता है। आप अब तक समझ गए होंगे, कि जितने विकल्प होंगे, उतने ही else कथन भी होंगे, और इनमें से प्रत्येक में काफी मात्रा में कोड की पंक्तियां भी धनु कोष्ठकों में रह सकती हैं। इसलिए प्रोग्राम में if...else के कई कोड खंडों की भीड़-भाड़ हो जाती है और यह पता लगाना कठिन हो जाता है कि किसी कोड खंड का संबंध किस else उक्ति से है।

इसलिए सी में अधिक जटिल विशाखन को अंजाम देने के लिए एक अन्य संरचना भी है, जिसे switch संरचना कहते हैं। इसका रूप इस तरह होता है –

switch (sanket)
{
case 'saket का मान 1’ :
उक्तियां;
break;
case ‘sanket का मान 2’ :
उक्तियां;
break;
case ‘sanket का मान 3’ :
उक्तियां;
break;
.
.
.
.
case ‘sanket का मान n’ :
उक्तियां;
break;
default :
उक्तियां;
}

आप देख सकते हैं कि switch के धनु कोष्ठकों के भीतर अनेक case खंड है। प्रत्येक case खंड एक विकल्प का प्रतिनिधित्व करता है, यानी जितने विकल्प होंगे, उतने case खंड भी होंगे। इनके अलावा एक अंतिम विकल्प भी हो सकता है, जिसे default प्रतिनिधित्व करता है। जब कोई भी वांछित विकल्प न प्राप्त होने पर यदि कुछ कोड़ पंक्तियों का निष्पादन आवश्यक हो, तो इन्हें default के अंतर्गत रखा जा सकता है।

switch संरचना की शुरुआत इस पंक्ति से होती है।
switch (sanket)

यहां sanket सामान्यतः int या char प्रकार की कोई राशि होती है। इसे switch कथन से पहले घोषित किया जाता है और प्रोग्राम के दौरान यह कोई मान प्राप्त करता है, जिसे sanket का मान 1, sanket का मान 2, sanket का मान 3,.... sanket का मान n के रूप में ऊपर के उदाहरण में दर्शाया गया है।

इसके बाद switch कथन का कोड खंड आता है, जो धनु कोष्ठकों में घिरा रहता है। इन धनु कोष्ठकों के अंदर case शब्द के जरिए सभी विकल्पों और उनसे संबंधित कोड खंडों को रखा जाता है। जितने विकल्प होंगे, उतने case कथन तथा उसके कोड़ खंड भी होंगे। प्रत्येक कोड खंड की अंतिम उक्ति break उक्ति होगी। case कथन और उसके कोड खंड को लिखने की विधि यह है –

case ‘sanket का मान 1’ :
कोड खंड
break;

सबसे पहले case शब्द को लिखा जाता है। उसके बाद एकल उद्धरण चिह्नों में sanket राशि द्वारा प्राप्त किया जानेवाला कोई मान रखा जाता है।

उसके बाद कोलन (: ) होता है।

कोलन के बाद उस case से संबंधित कोड खंड रहता है। इस कोड खंड की अंतिम उक्ति break उक्ति होती है, ताकि वांछित विकल्प के कोड के निष्पादन के बाद प्रोग्राम switch संरचना से बाहर आ जाए।

switch में कई case खंड होते हैं, पर इन case खेडों में से प्रोग्राम के दौरान केवल एक case खंड का ही निष्पादन होता है।

मान लीजिए कि किसी प्रोग्राम में sanket के ये चार मान हो सकते हैं - a, b, c, d। तो switch संरचना इस तरह बनेगी –

switch (sanket)
{
case ‘a’ :
उक्तियां;
break;

case ‘b’ :
उक्तियां;
break;

case ‘c’ :
उक्तियां;
break;

case ‘d’ :
उक्तियां;
break;
}

और इस switch संरचना का निष्पादन इस तरह होगा –

मान लीजिए प्रोग्राम में sanket का मान c आता है। तब switch संरचना के case ‘a’ और case ‘b’ से संबंधित कोड खंडों का निष्पादन नहीं होगा। प्रोग्राम सीधे case ‘c’ के कोड खंड का निष्पादन करेगा। चूंकि case 'c' की अंतिम उक्ति break कथन है, इसलिए उसके निष्पादन से switch संरचना टूट जाएगी और case 'd' के कोड खंड का निष्पादन नहीं होगा। इसके बजाए प्रोग्राम switch संरचना के बाद वाली पंक्तियों का निषपादन करने लगेगा।

है न यह विशाखन को अंजाम देने के लिए if...else से बढ़िया तरीका?

आइए, एक उदाहरण के जरिए switch संरचना को समझते हैं। इस उदाहरण में हम एक कैलक्युलेटर का प्रोग्राम लिखेंगे। यह कैलक्युलेटर योग, व्यवकलन, गुणन और विभाजन, ये चार संक्रियाएं कर सकेगा। इस तरह हमारे प्रोग्राम की switch संरचना में चार विकल्प होंगे, यानी चार case खंड होंगे। प्रयोक्ता से पूछा जाएगा कि उसे कौन सी गणितीय संक्रिया करनी है। उसे + (योग के लिए), - (व्यवकलन के लिए), * (गुणन के लिए), और / (विभाजन के लिए) में से कोई एक चिह्न चुनकर अपनी पसंद जाहिर करनी होगी। उसके बाद उसे दो संख्याएं भी चुननी होंगी, जिन पर प्रयोक्ता द्वारा चुनी गई गणितीय संक्रिया लागू की जाएगी। तत्पशचात प्रोग्राम प्रयोक्ता से पूछेगा कि वह और भी कोई गणितीय संक्रिया करना चाहता है या नहीं? इसका उत्तर प्रयोक्ता को y (हां के लिए) या n (नहीं के लिए) दर्ज करना होगा। प्रोग्राम में एक do...while लूप भी है। दरअसल switch संरचना को इसी do...while लूप के भीतर रखा गया है। यह do...while लूप प्रयोक्ता द्वारा व्यक्त किए गए y या n के अनुसार या तो switch कथन को तोड़ देता है (प्रयोक्ता देवारा n चुने जान पर) या उसे दुहराता है (प्रयोक्ता द्वरा y चुने जाने पर।

प्रोग्राम – 24
---------------------------------
/*switch sanrachana ka udaharan - calculator program*/

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

void main()
{
float a,b,c;
char sanket, pasand;
clrscr();

do
{
printf("Ank ganitiya prachalak chuniye\n");
printf("+ yog ke liye\n");
printf("- vyavakalan ke liye\n");
printf("* gunan ke liye\n");
printf("/ vibhajan ke liye\n");
scanf("%c",&sanket);
flushall();
printf("\nDo sankhyaen darj kijiye\n");
scanf("%f %f",&a,&b);
flushall();

switch(sanket)
{
case '+': c=a+b;
printf("Inka yog hai, %f\n",c);
break;

case '-': c=a-b;
printf("Inka antar hai, %f\n",c);
break;

case '*': c=a*b;
printf("Inka gunanphal hai, %f\n",c);
break;

case '/': c=a/b;
printf("Inka vibhajanphal hai, %f\n",c);
break;
}

printf("\nKya aap aur ganit karna chahtehai?(y ya n)\n");
scanf("%c",&pasand);
flushall();
}while(pasand!='n');

}
---------------------------------

आउटपुट
---------------------------------
Ank ganitiya prachalak chuniye
+ yog ke liye
- vyavakalan ke liye
* gunan ke liye
/ vibhajan ke liye +
Do sankhyaen darj kijiye 4 5
Inka yog hai, 9.00000
Kya aap aur ganit karna chahtehai? y
Ank ganitiya prachalak chuniye
+ yog ke liye
- vyavakalan ke liye
* gunan ke liye
/ vibhajan ke liye *
Do sankhyaen darj kijiye 3 8
Inka yog hai, 24.00000
Kya aap aur ganit karna chahtehai?n
---------------------------------

इस प्रोग्राम में ध्यान देनेवाली बातें निम्नलिखित हैं –
1. a, b, c को float प्रकार की राशियों के रूप में घोषित किया गया है।
2. दूसरे scanf उक्ति के जरिए एक साथ दो राशियों का मान पकड़ा गया है, यानी प्रयोक्ता द्वारा दर्ज की गई दोनों संख्याओं को। आपने ऐसा पहले printf के साथ किया है, अब आपको मालूम हुआ यह कमाल scanf भी कर सकता है। ध्यान देने की बात यही है, कि scanf के कोष्ठकों में दुहरे उद्धरण चिह्नों के अंदर और अल्प विराम के बाद &चिह्न के साथ ये रेशियां सही क्रम में आएं तथा उद्धरण चिह्नों में उनके लिए सही सूचक प्रतीक लगाए जाएं, अर्थात, यदि राशि int प्रकार की हो, तो %d, यदि वह char प्रकार की हो तो %c, इत्यादि।
3. जैसा कि पहले समझाया गया है, प्रत्येक scanf के बाद flushall() का प्रयोग किया गया है ताकि वह प्रोयक्ता द्वारा दबाई गई ऐंटर कुंजी को इनपुट न मान ले।
4. switch कथन को do...while के भीतर रखा गया है।
5. do...while लूप तब तक चलता रहता है जब तक प्रयोक्ता pasand के लिए n नहीं दर्ज करता।

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