आप सी में पैरामीटर के रूप में फ़ंक्शन कैसे पास करते हैं?

मैं एक ऐसा फ़ंक्शन बनाना चाहता हूं जो डेटा के सेट पर पैरामीटर द्वारा पारित फ़ंक्शन निष्पादित करता हो। आप सी में पैरामीटर के रूप में फ़ंक्शन कैसे पास करते हैं?

0
ro fr bn
@MooingDuck मैं आपके सुझाव से सहमत नहीं हूं, और आपके सुझाव में निष्कर्ष का समर्थन करने के लिए तर्क की कमी है। मैं व्यक्तिगत रूप से फ़ंक्शन पॉइंटर्स पर टाइपपीफ का उपयोग करके कभी नहीं पसंद करता हूं, और मुझे लगता है कि यह कोड को स्पष्ट और पढ़ने में आसान बनाता है।
जोड़ा लेखक andrewrk, स्रोत
हम इसे फ़ंक्शन पॉइंटर कहते हैं
जोड़ा लेखक AminM, स्रोत
यदि आप चर के रूप में फ़ंक्शंस/सरणी का उपयोग कर रहे हैं, तो हमेशा typedef का उपयोग करें।
जोड़ा लेखक Mooing Duck, स्रोत
@andrewrk: आप शून्य funcA (शून्य (* funcB) (int) पसंद करते हैं) और शून्य (* funcA ())() typedef void funcB() ; शून्य funcA (funcB) और funcb funcA() ? मैं उल्टा नहीं देखता हूँ।
जोड़ा लेखक Mooing Duck, स्रोत
ओह, मैंने अभी देखा है कि टिप्पणी "चर के रूप में सरणी" कहती है। हाँ, यह गलत है। मैं चर के रूप में सरणी पॉइंटर्स मतलब था।
जोड़ा लेखक Mooing Duck, स्रोत
फ़ंक्शन का नाम फ़ंक्शन पर एक पोंटर होना चाहिए। अधिकांश लोग सी कवर qsort सीखना जल्दी या बाद में यह वास्तव में करता है?
जोड़ा लेखक mckenzm, स्रोत

5 उत्तर

आपको एक फ़ंक्शन पॉइंटर पास करने की आवश्यकता है। वाक्यविन्यास थोड़ा बोझिल है, लेकिन इससे पहले कि आप इससे परिचित हो जाएं, यह वास्तव में शक्तिशाली है।

0
जोड़ा

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

typedef void (*functiontype)();

एक समारोह घोषित करता है जो शून्य लौटाता है और कोई तर्क नहीं लेता है। इस प्रकार के लिए फ़ंक्शन पॉइंटर बनाने के लिए अब आप कर सकते हैं:

void dosomething() { }

functiontype func = &dosomething;
func();

एक ऐसे फ़ंक्शन के लिए जो एक int देता है और एक char लेता है जो आप करेंगे

typedef int (*functiontype2)(char);

और इसका इस्तेमाल करने के लिए

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

पुस्तकालय हैं जो फ़ंक्शन पॉइंटर्स को अच्छे पठनीय प्रकारों में बदलने में मदद कर सकते हैं। बूस्ट फ़ंक्शन लाइब्रेरी बहुत बढ़िया है और यह अच्छी तरह से योग्य है प्रयास है!

boost::function functiontype2;

उपर्युक्त की तुलना में बहुत अच्छा है।

0
जोड़ा
यदि आप "एक फ़ंक्शन पॉइंटर को एक प्रकार में बदलना चाहते हैं", तो आपको बूस्ट लाइब्रेरी की आवश्यकता नहीं है। बस typedef का उपयोग करें; यह आसान है और किसी भी अतिरिक्त पुस्तकालय की आवश्यकता नहीं है।
जोड़ा लेखक wizzwizz4, स्रोत

नीचे दिखाए गए अनुसार किसी फ़ंक्शन का पैरामीटर किसी अन्य फ़ंक्शन पर पैरामीटर के रूप में पास करें

#include 

void print();
void execute(void());

int main()
{
    execute(print);//sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void f())//receive address of print
{
    f();
}

Also we can pass function as parameter using function pointer

#include 

void print();
void execute(void (*f)());

int main()
{
    execute(&print);//sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void (*f)())//receive address of print
{
    f();
}
0
जोड़ा

चूंकि सी ++ 11 आप इसे करने के लिए कार्यात्मक लाइब्रेरी का उपयोग कर सकते हैं संक्षिप्त और सामान्य फैशन। वाक्यविन्यास है, उदाहरण के लिए,

std::function

जहां bool एक-तर्क फ़ंक्शन का रिटर्न प्रकार है जिसका पहला तर्क int प्रकार है।

मैंने नीचे एक उदाहरण प्रोग्राम शामिल किया है:

// g++ test.cpp --std=c++11
#include 

double Combiner(double a, double b, std::function func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

कभी-कभी, हालांकि, टेम्पलेट फ़ंक्शन का उपयोग करना अधिक सुविधाजनक होता है:

// g++ test.cpp --std=c++11

template
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}
0
जोड़ा
सवाल सी के बारे में है; सी ++ यहां लागू नहीं होता है।
जोड़ा लेखक Super Cat, स्रोत
हो सकता है कि सी ++ के लिए सवाल यहां संदर्भित नहीं किया जाना चाहिए क्योंकि यह प्रश्न सी है।
जोड़ा लेखक Michael Fulton, स्रोत

घोषणा

फ़ंक्शन पैरामीटर लेने वाले फ़ंक्शन के लिए प्रोटोटाइप निम्न जैसा दिखता है:

void func ( void (*f)(int) );

यह बताता है कि पैरामीटर f एक फ़ंक्शन के लिए एक सूचक होगा जिसमें शून्य वापसी प्रकार होता है और जो एक int पैरामीटर लेता है। निम्न फ़ंक्शन ( प्रिंट ) एक फ़ंक्शन का एक उदाहरण है जिसे पैरामीटर के रूप में func पर भेजा जा सकता है क्योंकि यह उचित प्रकार है:

void print ( int x ) {
  printf("%d\n", x);
}

फ़ंक्शन कॉल

फ़ंक्शन पैरामीटर के साथ फ़ंक्शन को कॉल करते समय, पास किया गया मान किसी फ़ंक्शन के लिए पॉइंटर होना चाहिए। इसके लिए फ़ंक्शन का नाम (बिना ब्रांड्स के) का उपयोग करें:

func(print);

प्रिंट कोड को पास करने के लिए func को कॉल करेगा।

फ़ंक्शन बॉडी

किसी पैरामीटर के साथ, func अब पैरामीटर के मान का उपयोग करने के लिए फ़ंक्शन बॉडी में पैरामीटर के नाम का उपयोग कर सकता है। आइए मान लें कि func उस कार्य को लागू करेगा जो इसे संख्या 0-4 पर पारित किया गया है। गौर करें, सबसे पहले, लूप सीधे प्रिंट को कॉल करने जैसा कैसा दिखता है:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

चूंकि func की पैरामीटर घोषणा कहती है कि f वांछित फ़ंक्शन पर पॉइंटर का नाम है, तो हमें पहले याद है कि यदि f एक पॉइंटर है फिर * f वह चीज़ है जो f इंगित करती है (यानी इस मामले में फ़ंक्शन <कोड> प्रिंट )। नतीजतन, ऊपर दिए गए लूप में * f के साथ प्रिंट की हर घटना को प्रतिस्थापित करें:

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

From http://math.hws.edu/bridgeman/courses/331/f05/handouts/c-c++-notes.html

0
जोड़ा
@ जोनाथन रेनहार्ट हां, यह एएनएसआई सी में था
जोड़ा लेखक M.M, स्रोत
@JonathonReinhart उस मामले में मैं समारोह प्रकार टाइप किया जाएगा।
जोड़ा लेखक M.M, स्रोत
@ जोनाथन रेनहार्ट अच्छी तरह से देखा; यह स्पष्ट रूप से ध्यान दिया जाना चाहिए कि पॉइंटर टाइपिफ़ीड्स कोड को खराब कर देता है और इसलिए इसका उपयोग नहीं किया जाना चाहिए।
जोड़ा लेखक M.M, स्रोत
@ जोनाथन रेनहार्ट, 'टाइपिफ' एप्रेच के साथ क्या फायदे होंगे? यह संस्करण बहुत साफ दिखता है हालांकि अतिरिक्त बयान भी नहीं है। यहां बहुत स्टार्टर है।
जोड़ा लेखक Abhinav Gauniyal, स्रोत
@ एमएम क्या वह मानक सी है? मैंने पहले इसके साथ खेला है, लेकिन सोचा कि यह एक जीएनयू एक्सटेंशन था।
जोड़ा लेखक Jonathon Reinhart, स्रोत
देख रहे हैं ( stackoverflow.com/questions/4574985/&hellip ;), फ़ंक्शन पॉइंटर घोषित करते समय * को शामिल करने का एकमात्र अंतर सही है? क्योंकि आप फंक्शन टाइपिफ़ से फ़ंक्शन को परिभाषित नहीं कर सकते हैं। टाइपपीफ-इन फ़ंक्शन पॉइंटर्स के बारे में बहुत सारी जानकारी है, लेकिन फ़ंक्शन प्रकार नहीं।
जोड़ा लेखक Jonathon Reinhart, स्रोत
@ एमएम असहमत। कॉलबैक-आधारित एपीआई पर विचार करें, जहां कॉलबैक पंजीकृत हैं और संदर्भ संरचना में संग्रहीत हैं। यदि आप फ़ंक्शन पॉइंटर्स के लिए टाइपिफ़ का उपयोग करते हैं और अपने प्रोटोटाइप को बदलना चाहते हैं, तो आपको इसे हर जगह बदलने के बजाय फ़ंक्शन पॉइंटर टाइपपीफ को बदलना होगा। यह एक ऐसे व्यक्ति से आ रहा है जो अति-टाइपिंगफिंग (अर्थात् structs पर) से असहमत है।
जोड़ा लेखक Jonathon Reinhart, स्रोत
वास्तव में? शीर्ष-रेटेड उत्तर फ़ंक्शन पॉइंटर्स के लिए typedef का उपयोग करने का एक संदर्भ नहीं बनाता है? क्षमा करें, नीचे वोट देना है।
जोड़ा लेखक Jonathon Reinhart, स्रोत
क्या फ़ंक्शन संदर्भों के विरुद्ध कुछ भी है, ताकि हमारे पास कुछ जटिल वाक्यविन्यास न हो? पिछली बार मैंने चेक किया है, ये पूरी तरह से काम किया ..
जोड़ा लेखक lorro, स्रोत
आपके पहले और अंतिम कोड उदाहरणों में, * अनिवार्य नहीं है। फ़ंक्शन पैरामीटर परिभाषा और f फ़ंक्शन कॉल दोनों f को बिना * के ले सकते हैं। ऐसा करने के लिए यह एक अच्छा विचार हो सकता है जैसा कि आप करते हैं, यह स्पष्ट करने के लिए कि पैरामीटर एफ एक फ़ंक्शन पॉइंटर है। लेकिन यह अक्सर पठनीयता को दर्द होता है।
जोड़ा लेखक Gauthier, स्रोत
उदाहरण के लिए [सी 99, 6.9.1§14] देखें। दोनों सही हैं, मैं बस विकल्प का उल्लेख करना चाहता था।
जोड़ा लेखक Gauthier, स्रोत
क्या होगा यदि आप एक फ़ंक्शन पॉइंटर पास करना चाहते हैं जो एक पॉइंटर को तर्क के रूप में लौटाता है। मैंने कोशिश की:
जोड़ा लेखक azmath, स्रोत