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





function pointers syntax parameters (5)


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

std::function<bool (int)>

जहां bool एक तर्क-तर्क समारोह का रिटर्न प्रकार है जिसका पहला तर्क प्रकार int

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

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

double Combiner(double a, double b, std::function<double (double,double)> 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<class T>
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);
}

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




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

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<int (char a)> functiontype2;

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




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

#include <stdio.h>

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();
}

इसके अलावा हम फ़ंक्शन पॉइंटर का उपयोग करके पैरामीटर के रूप में फ़ंक्शन को पास कर सकते हैं

#include <stdio.h>

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();
}



घोषणा

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

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

यह बताता है कि पैरामीटर f एक फ़ंक्शन के लिए एक सूचक होगा जिसमें void वापसी प्रकार होता है और जो एक एकल int पैरामीटर लेता है। निम्न फ़ंक्शन ( print ) एक फ़ंक्शन का एक उदाहरण है जिसे पैरामीटर के रूप में 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 इंगित करती है (यानी इस मामले में फ़ंक्शन print )। नतीजतन, ऊपर *f लूप के साथ लूप में प्रिंट की हर घटना को प्रतिस्थापित करें:

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

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




अंतर यह है कि functionOne एक फ़ंक्शन अभिव्यक्ति है और इसलिए केवल उस पंक्ति को तब तक परिभाषित किया जाता है जब functionTwo एक फ़ंक्शन घोषणा होती है और जैसे ही इसके आसपास के फ़ंक्शन या स्क्रिप्ट को निष्पादित किया जाता है ( hoisting कारण)।

उदाहरण के लिए, एक फ़ंक्शन अभिव्यक्ति:

// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.log("Hello!");
};

और, एक समारोह घोषणा:

// Outputs: "Hello!"
functionTwo();

function functionTwo() {
  console.log("Hello!");
}

इसका मतलब यह भी है कि आप फ़ंक्शन घोषणाओं का उपयोग करके फ़ंक्शंस को सशर्त रूप से परिभाषित नहीं कर सकते हैं:

if (test) {
   // Error or misbehavior
   function functionThree() { doSomething(); }
}

उपर्युक्त वास्तव में functionThree को परिभाषित करता है test के मूल्य के बावजूद - जब तक use strict प्रभावी नहीं होता है, इस मामले में यह केवल एक त्रुटि उठाता है।







c function pointers syntax parameters