2010-12-12 12 views
5

शुद्ध एएनएसआई-सी में जेनेरिक सरणी को दोहराना संभव है?शुद्ध एएनएसआई-सी: जेनेरिक सरणी

मेरे पास यह संरचना है जिसमें एक सरणी है (इस समय फ्लोट्स के लिए) और सरणी में उत्परिवर्तन के लिए आकार और क्षमता जैसे कुछ चर।

typedef struct _CustomArray 
{ 
    float* array; //the array in which the objects will be stored 
    int size; //the current size of the array 
    int capacity; //the max capacity of the array 
} CustomArray; 

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

इस समय इस सरणी बनाने के लिए कार्य है:

CustomArray* CustomArray_Create(int initCapacity, /*type elementType*/) 
{ 
    CustomArray* customArray_ptr; //create pointer to point at the structure 
    float* internalArray = (float*)malloc(sizeof(float) * initCapacity); //create the internal array that holds the items 
    if(internalArray != NULL) 
    { 
     CustomArray customArray = { internalArray, 0, initCapacity }; //make the struct with the data 
     customArray_ptr = &customArray; //get the adress of the structure and assign it to the pointer 
     return customArray_ptr; //return the pointer 
    } 
    return NULL; 
} 

पैरामीटर के रूप में एक डेटाप्रकार देने के लिए क्या यह संभव है इसलिए मैं उस डेटाप्रकार के लिए स्मृति malloc और गतिशील रूप से एक सरणी में है कि दिया डेटाप्रकार के रूप में यह डाल सकता ?

अग्रिम धन्यवाद,

Marnix वैन Rijswijk

+0

लगता शुद्ध सी में नहीं है आप डेटा प्रकार कि जिस तरह से पारित कर सकते हैं:

आप रुचि रखते हैं, यहाँ कोड है। विषम सरणी सूची का समर्थन करने वाली भाषाओं में देख रहे हैं, उदाहरण के लिए सी #, यह केवल गैर मूल डेटा प्रकारों के लिए काम करता है, जो कक्षाएं हैं और int, float आदि पर नहीं हैं क्योंकि सी वस्तु उन्मुख नहीं है, इसलिए यह बेहद असंभव है कि आपको यह सुविधा मिल जाएगी। –

+2

अंडरस्कोर के साथ पहचानकर्ता शुरू न करें: ऐसे नाम कार्यान्वयन के लिए आरक्षित हैं (कंपाइलर + libc); अंडरस्कोर और ऊपरी मामले का उपयोग करना दोगुना-खराब है: ये नाम किसी भी संदर्भ में आरक्षित हैं क्योंकि यह नई भाषा सुविधाओं का उपयोग करता है (उदाहरण के लिए '_Pragma', '_Complex',' _Bool', ...); एक आसान कामकाज पीछे की ओर अंडरस्कोर का उपयोग करना है, जो उपसर्ग-आधारित नेमस्पेसिंग – Christoph

+1

के साथ भी अच्छा खेलता है साइट पर ऑब्जेक्ट ओरिएंटेड व्यवहार कैसे बना सकता है इस बारे में साइट पर कई सवाल हैं: [ऑब्जेक्ट-ओरिएंटेशन इन सी] (http://stackoverflow.com/q/415452/2509) और [क्या आप सी में ऑब्जेक्ट ओरिएंटेड कोड लिख सकते हैं?] (http://stackoverflow.com/q/351733/2509) और अन्य। आप अपने वांछित परिणाम को 'आकार' के न्यायसंगत उपयोग और लिंक में चर्चा की गई फ़ंक्शन पॉइंटर तंत्र के साथ पूरा कर सकते हैं, लेकिन यह अधिक काम करेगा कि यह लायक है। 'Qsort' और 'bsearch' का इंटरफ़ेस एक समझौता है। – dmckee

उत्तर

8

आपका कोड एक गंभीर समस्या ... आप एक स्थानीय चर का पता लौट रहे हैं (CustomArray) है और जब फ़ंक्शन कि चर नष्ट हो जाता है तो आप नहीं कर सकते प्रयोग किया जाता है पॉइंटर के साथ इसका इस्तेमाल करते रहें। आपको उस संरचना को भी मॉलोक करना होगा ताकि फ़ंक्शन लौटने के बाद स्मृति अभी भी उपलब्ध रहे।

के साथ कुछ की तरह उदाहरण के लिए प्रकार एक पैरामीटर आप कुछ हद तक करीब मैक्रो का उपयोग कर सकते हैं बनाने ... के बारे में:

#include <stdlib.h> 
#define DefArray(type) \ 
typedef struct T_##type##Array {\ 
    type *array; \ 
    int size, capacity; \ 
} type##Array; \ 
static type##Array *type##ArrayCreate(int capacity)\ 
{\ 
    type##Array *s = malloc(sizeof(type##Array));\ 
    if (!s) return NULL;\ 
    s->array = malloc(sizeof(type) * capacity);\ 
    if (!s->array) { free(s); return NULL; }\ 
    s->size=0; s->capacity = capacity;\ 
    return s;\ 
} 

तो फिर तुम इसे इस तरह का उपयोग कर सकते

#include "customarray.h" 
DefArray(float); 
DefArray(double); 

void foo() 
{ 
    floatArray *fa = floatArrayCreate(100); 
    ... 
} 

ध्यान दें कि आप अपने सभी कस्टम कार्यों को परिभाषित करने के लिए मैक्रोज़ का उपयोग करना है। ध्यान दें कि यह दृष्टिकोण प्रत्येक मॉड्यूल में कोड को डुप्लिकेट करेगा (मैं एक बड़ा मुद्दा नहीं कहूंगा लेकिन यदि आप सी ++ का उपयोग नहीं कर सकते हैं तो शायद आपका लक्ष्य प्लेटफॉर्म बहुत छोटा है)। थोड़ा अधिक जटिल दृष्टिकोण के साथ आप कार्यान्वयन के लिए अलग .h फ़ाइल और .c फाइलें उत्पन्न कर सकते हैं।

+0

बहुत अच्छा है, मैं भी यह सुनिश्चित करने के लिए कोशिश करूँगा। इसके लिए धन्यवाद। –

+0

यह काम करता है, और यह मुझे चीजों को करने का एक नया तरीका भी दिखाता है। बहुत बढ़िया। –

+3

हेहे ... मेटाप्रोग्रामिंग की दुनिया में आपका स्वागत है (कोड लिखने वाला कोड लिखना)। सी प्रीप्रोसेसर मेटाप्रोग्रामिंग का एक बहुत ही कमजोर रूप है, सी ++ टेम्पलेट मशीनरी थोड़ा बेहतर है। वास्तविक जादू के लिए आपको बाहरी जनरेटर का उपयोग करना होगा (उदाहरण के लिए पाइथन/पर्ल में उदाहरण के लिए सी/सी ++ जेनरेटर लिखना आसान है) या अन्य मेटाप्रोग्रामिंग उपलब्ध है (उदा। लिस्प)। – 6502

2

लड़के, यह वास्तव में सी के लिए एक नौकरी ++ तरह लगता है।

मुझे लगता है कि आप सी में इस निकटतम आ सकते हैं, इस प्रकार को पास नहीं करना है, बल्कि आकार (आकार (प्रकार))।

आप अपने कार्य को अधिक सामान्य बना सकते हैं ताकि यह ऐसा करने के लिए जो कुछ भी करने की ज़रूरत हो, वह सरणी में प्रत्येक आइटम का आकार है। इस प्रकार bsearch() काम जैसे कार्यों।

+0

हम्म धन्यवाद, मैं इसे सी ++ के लिए और अधिक नौकरी जानता हूं। लेकिन मैं सोच रहा था कि यह संभव था। : [दुख की बात यह नहीं है। –

+0

क्या आकार को देखकर डेटा प्रकार पर धारणाएं सुरक्षित रखना सुरक्षित है? –

+0

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

2

इसे प्राप्त करने का एक तरीका तथाकथित X-macros का उपयोग करना है।

Here इस तकनीक का उपयोग कर एक (संभवतः छोटी गाड़ी) जेनेरिक वेक्टर कार्यान्वयन है।

यह तो के रूप में

// defining generic parameters 
#define PREFIX tv 
#define ITEM token 
#define NAME token_vector 
#include "vector.h" 

... 
token_vector tv = tv_new(100); 
*(tv.front) = some_token; 
tv_push_back(&tv, other_token); 
0

कुछ साल पहले मैंने सी में जेनेरिक प्रोग्रामिंग के साथ गड़बड़ी की, बस इसके बिल्ली के लिए।

असल में, मैंने प्रीप्रोसेसर का शोषण समाप्त कर दिया। मुझे लगता है कि मैं हल्के ढंग से सफल था: मैंने कई सबसे महत्वपूर्ण जेनेरिक डेटा संरचनाओं के लिए कुछ मैक्रो नोटेशन पूरा किया।

क्या मैं निश्चित रूप से गए पूरा नहीं (किसी भी स्वत: रास्ते में कम से कम) रिकर्सिवली मैक्रो चल रहा था - अर्थात बनाने एक सरणी के-सरणियों या सरणी के-हैश आदि है यह दिलचस्प खांसी की वजह से पागल खांसी सी प्रीप्रोसेसर मैक्रोज़ के अर्थशास्त्र। https://github.com/christianfriedl/CGenerics/blob/master/src/cgArray.h