2010-04-12 16 views
59

यदि मेरे पास कोई ऐसा फ़ंक्शन है जो परिणाम int उत्पन्न करता है और परिणाम string, मैं उन्हें फ़ंक्शन से कैसे वापस कर सकता हूं?मैं सी में किसी फ़ंक्शन से एकाधिक मान कैसे वापस कर सकता हूं?

जहां तक ​​मैं कह सकता हूं कि मैं केवल एक चीज़ लौटा सकता हूं, जैसा फ़ंक्शन नाम से पहले के प्रकार से निर्धारित किया गया है।

+6

'स्ट्रिंग' से आपका मतलब है "मैं सी ++ का उपयोग कर रहा हूं और यह 'std :: string' class" है या "मैं सी का उपयोग कर रहा हूं और यह एक' char *' पॉइंटर या 'char [] 'है सरणी। " –

+0

अच्छी तरह से, मेरे विशेष मामले में, वे दो चींटियां थीं: एक 'स्कोर' के लिए जो मैं तुलना कर रहा था, और 'इंडेक्स' के लिए एक जहां अधिकतम स्कोर मिला था। मैं सिर्फ एक सामान्य उदाहरण – sepiroth

+0

के लिए एक स्ट्रिंग उदाहरण का उपयोग करना चाहता था संदर्भ के अनुसार स्ट्रिंग पास करें और int वापस दें। सबसे तेज़ तरीका। कोई structs आवश्यक है। –

उत्तर

86

मुझे नहीं पता कि आपका string क्या है, लेकिन मुझे लगता है कि यह अपनी याददाश्त का प्रबंधन करता है।

1: लौटें एक struct जो सभी प्रकार आप की जरूरत में शामिल है

आप दो समाधान है।

struct Tuple { 
    int a; 
    string b; 
}; 

struct Tuple getPair() { 
    Tuple r = { 1, getString() }; 
    return r; 
} 

void foo() { 
    struct Tuple t = getPair(); 
} 

2: मूल्यों को पारित करने के लिए पॉइंटर्स का उपयोग करें।

void getPair(int* a, string* b) { 
    // Check that these are not pointing to NULL 
    assert(a); 
    assert(b); 
    *a = 1; 
    *b = getString(); 
} 

void foo() { 
    int a, b; 
    getPair(&a, &b); 
} 

जो भी आप उपयोग करना चुनते हैं वह बड़े पैमाने पर व्यक्तिगत प्राथमिकता पर निर्भर करता है कि आप जो भी अर्थशास्त्र चाहते हैं।

+6

मुझे लगता है कि यह इस बात पर निर्भर करता है कि वापसी मूल्य कितने संबंधित हैं। यदि int एक त्रुटि कोड है और स्ट्रिंग परिणाम है, तो इन्हें एक संरचना में एक साथ नहीं रखा जाना चाहिए। यह सिर्फ मूर्ख है। उस स्थिति में, मैं int को वापस कर दूंगा और स्ट्रिंग को 'char *' और 'size_t' के रूप में लंबाई तक पास कर दूंगा जब तक कि फ़ंक्शन के लिए अपनी स्वयं की स्ट्रिंग आवंटित करने और/या' NULL 'को वापस करने के लिए यह बिल्कुल महत्वपूर्ण नहीं है। –

+0

@ क्रिस मैं आपके साथ पूरी तरह से सहमत हूं, लेकिन मुझे उन चर के उपयोग अर्थशास्त्र के बारे में कोई जानकारी नहीं है। –

3

एक संरचना बनाएं और अंदर दो मान सेट करें और संरचना चर वापस लौटें।

struct result { 
    int a; 
    char *string; 
} 

आपको अपने कार्यक्रम में char * के लिए स्थान आवंटित करना होगा।

2

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

5

दो अलग दृष्टिकोण: सूचक द्वारा अपनी वापसी मूल्यों में

  1. दर्रा, और उन्हें समारोह के अंदर संशोधित करते हैं। आप अपने कार्य को शून्य के रूप में घोषित करते हैं, लेकिन यह पॉइंटर्स के रूप में पारित मानों के माध्यम से लौट रहा है।
  2. अपनी वापसी मानों को एकत्रित करने वाली संरचना को परिभाषित करें।

मुझे लगता है कि # 1 क्या हो रहा है इसके बारे में थोड़ा और स्पष्ट है, हालांकि यदि आपके पास बहुत अधिक रिटर्न मूल्य हैं तो यह थकाऊ हो सकता है। उस स्थिति में, विकल्प # 2 काफी अच्छी तरह से काम करता है, हालांकि इस उद्देश्य के लिए विशेष structs बनाने में कुछ मानसिक उपरि शामिल है।

+1

सी में संदर्भ नहीं हैं ;-), हालांकि पोस्टर 'स्ट्रिंग' का उपयोग करता है, इसलिए सी ++ मानना ​​सुरक्षित हो सकता है ... –

+0

पूरी तरह से इसके बारे में भूल गया! मैंने पॉइंटर्स का उपयोग करने के लिए अपना जवाब संशोधित किया, लेकिन मैं स्पष्ट रूप से बहुत लंबे समय तक सी ++ भूमि में रहा हूं। :) –

4

चूंकि आपके परिणाम प्रकारों में से एक एक स्ट्रिंग है (और आप सी का उपयोग कर रहे हैं, सी ++ नहीं), मैं आउटपुट पैरामीटर के रूप में पॉइंटर्स पास करने की अनुशंसा करता हूं। का उपयोग करें:

void foo(int *a, char *s, int size); 

और इसे इस तरह कहते हैं:

int a; 
char *s = (char *)malloc(100); /* I never know how much to allocate :) */ 
foo(&a, s, 100); 

सामान्य में, पसंद करते हैं समारोह, नहीं समारोह के अंदर ही बुला में आवंटन करने के लिए, ताकि आप के रूप में खुला हो सकता है विभिन्न आवंटन रणनीतियों के लिए संभव है।

6

Option 1: एक int और स्ट्रिंग के साथ एक संरचना घोषित करें और एक संरचना चर वापस लौटें।

struct foo {  
int bar1; 
char bar2[MAX]; 
}; 

struct foo fun() { 
struct foo fooObj; 
... 
return fooObj; 
} 

Option 2: आप सूचक के माध्यम से दो में से एक गुजरती हैं और सूचक के माध्यम से वास्तविक पैरामीटर में परिवर्तन करने और हमेशा की तरह अन्य लौट सकते हैं:

int fun(char *param) { 
int bar; 
... 
strcpy(param,"...."); 
return bar; 
} 

या

char* fun(int *param) { 
char *str = /* malloc suitably.*/ 
... 
strcpy(str,"...."); 
*param = /* some value */ 
return str; 
} 

Option 3: विकल्प 2 के समान। आप पॉइंटर के माध्यम से दोनों पास कर सकते हैं और फ़ंक्शन से कुछ भी वापस नहीं कर सकते:

void fun(char *param1,int *param2) { 
strcpy(param,"...."); 
*param2 = /* some calculated value */ 
} 
+0

विकल्प 2 के संबंध में, आपको स्ट्रिंग की लंबाई में भी पास होना चाहिए। 'int मजेदार (char * param, size_t len)' –

+0

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

1

फ़ंक्शन के संदर्भ में पैरामीटर पास करके।

उदाहरण:

void incInt(int *y) 
{ 
    (*y)++; // Increase the value of 'x', in main, by one. 
} 
इसके अलावा वैश्विक चर का उपयोग करके

लेकिन यह अनुशंसित नहीं है।

उदाहरण:

int a=0; 

void main(void) 
{ 
    //Anything you want to code. 
} 
+2

'शून्य मुख्य (शून्य) 'ओह यह कैसे आता है! –

+0

आपका क्या मतलब है? @ क्रिस लुट – Badr

+3

'मुख्य' को स्टेटस कोड वापस करना है। * निक्स के तहत, इसे 'int main (int argc, char * argv [])' घोषित करना अधिक सामान्य है, मेरा मानना ​​है कि विंडोज के समान सम्मेलन हैं। – Duncan

-3

अरे पीटर मेरा मानना ​​है कि आप सी

में
1

एक दृष्टिकोण संकेत की मदद से 2 मूल्यों लौट सकते हैं मैक्रो का उपयोग करने के लिए है। एक हेडर फाइल में इस जगह multitype.h

#include <stdlib.h> 

/* ============================= HELPER MACROS ============================= */ 

/* __typeof__(V) abbreviation */ 

#define TOF(V) __typeof__(V) 

/* Expand variables list to list of typeof and variable names */ 

#define TO3(_0,_1,_2,_3) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; TOF(_3) v3; 
#define TO2(_0,_1,_2) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; 
#define TO1(_0,_1)  TOF(_0) v0; TOF(_1) v1; 
#define TO0(_0)   TOF(_0) v0; 

#define TO_(_0,_1,_2,_3,TO_MACRO,...) TO_MACRO 

#define TO(...) TO_(__VA_ARGS__,TO3,TO2,TO1,TO0)(__VA_ARGS__) 

/* Assign to multitype */ 

#define MTA3(_0,_1,_2,_3) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; _3 = mtr.v3; 
#define MTA2(_0,_1,_2) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; 
#define MTA1(_0,_1)  _0 = mtr.v0; _1 = mtr.v1; 
#define MTA0(_0)   _0 = mtr.v0; 

#define MTA_(_0,_1,_2,_3,MTA_MACRO,...) MTA_MACRO 

#define MTA(...) MTA_(__VA_ARGS__,MTA3,MTA2,MTA1,MTA0)(__VA_ARGS__) 

/* Return multitype if multiple arguments, return normally if only one */ 

#define MTR1(...) {               \ 
    typedef struct mtr_s {             \ 
     TO(__VA_ARGS__)               \ 
    } mtr_t;                 \ 
    mtr_t *mtr = malloc(sizeof(mtr_t));          \ 
    *mtr = (mtr_t){__VA_ARGS__};            \ 
    return mtr;                \ 
    } 

#define MTR0(_0) return(_0) 

#define MTR_(_0,_1,_2,_3,MTR_MACRO,...) MTR_MACRO 

/* ============================== API MACROS =============================== */ 

/* Declare return type before function */ 

typedef void* multitype; 

#define multitype(...) multitype 

/* Assign return values to variables */ 

#define let(...)                \ 
    for(int mti = 0; !mti;)              \ 
    for(multitype mt; mti < 2; mti++)           \ 
     if(mti) {                \ 
     typedef struct mtr_s {            \ 
      TO(__VA_ARGS__)              \ 
     } mtr_t;                \ 
     mtr_t mtr = *(mtr_t*)mt;            \ 
     MTA(__VA_ARGS__)              \ 
     free(mt);                \ 
     } else                 \ 
     mt 

/* Return */ 

#define RETURN(...) MTR_(__VA_ARGS__,MTR1,MTR1,MTR1,MTR0)(__VA_ARGS__) 

यह एक समारोह से चार चर भी लौट सकते हैं और उन्हें करने के लिए चार चर को असाइन करना संभव बनाता है। एक उदाहरण के रूप में, आप उन्हें इस तरह का उपयोग कर सकते हैं:

(55, 3.9, 24.15) 

समाधान है क्योंकि यह variadic मैक्रो और तक- के लिए C99 या आवश्यकता है बाद में के रूप में पोर्टेबल नहीं हो सकता है:

multitype (int,float,double) fun() { 
    int a = 55; 
    float b = 3.9; 
    double c = 24.15; 

    RETURN (a,b,c); 
} 

int main(int argc, char *argv[]) { 
    int x; 
    float y; 
    double z; 

    let (x,y,z) = fun(); 

    printf("(%d, %f, %g\n)", x, y, z); 

    return 0; 
} 

यह यह क्या प्रिंट है कथन परिवर्तनीय घोषणाएं। लेकिन मुझे लगता है कि यह यहां पोस्ट करने के लिए काफी दिलचस्प था। एक और मुद्दा यह है कि यदि आप उन्हें गलत मान निर्दिष्ट करते हैं तो संकलक आपको चेतावनी नहीं देगा, इसलिए आपको सावधान रहना होगा।

अतिरिक्त उदाहरण, और यूनियनों का उपयोग कर कोड का एक स्टैक-आधारित संस्करण, मेरे github repository पर उपलब्ध है।

+0

एक बड़ी पोर्टेबिलिटी समस्या गैर मानक फीचर '__typeof__' –

+0

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

संबंधित मुद्दे

 संबंधित मुद्दे