स्ट्रिंग्स, अच्छी शैली लौटाने वाले कार्य?


11

मेरे सी कार्यक्रमों में मुझे अक्सर अपने एडीटी का एक स्ट्रिंग प्रतिनिधित्व करने का एक तरीका चाहिए। यहां तक ​​कि अगर मुझे किसी भी तरह से स्क्रीन पर स्ट्रिंग को प्रिंट करने की आवश्यकता नहीं है, तो डिबगिंग के लिए इस तरह की विधि करना साफ-सुथरा है। तो इस तरह का फंक्शन अक्सर सामने आता है।

char * mytype_to_string( const mytype_t *t );

मुझे वास्तव में एहसास होता है कि मेरे पास (कम से कम) तीन विकल्प हैं, जो स्ट्रिंग को वापस करने के लिए मेमोरी को संभालने के लिए हैं।

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

वैकल्पिक 2: फ़ंक्शन के अंदर मॉलोक के साथ ढेर पर स्ट्रिंग आवंटित करें। वास्तव में स्वच्छ जब से मैं एक बफर या अधिलेखित के आकार के बारे में सोचने की जरूरत नहीं होगी। हालांकि, मुझे स्ट्रिंग को मुफ्त () करने के लिए याद रखना होगा, और फिर मुझे एक अस्थायी चर को भी असाइन करना होगा ताकि मैं मुक्त हो सकूं। और फिर ढेर आवंटन ढेर आवंटन की तुलना में बहुत धीमा है, इसलिए यदि यह एक लूप में दोहराया जाता है, तो एक अड़चन हो।

वैकल्पिक 3: सूचक को एक बफर में पास करें, और कॉलर को उस बफर को आवंटित करने दें। पसंद:

char * mytype_to_string( const mytype_t *mt, char *buf, size_t buflen ); 

यह कॉल करने वाले के लिए अधिक प्रयास लाता है। मैं यह भी देखता हूं कि यह विकल्प मुझे तर्कों के क्रम पर एक अन्य विकल्प देता है। मेरे पास कौन सा तर्क होना चाहिए पहला और आखिरी? (वास्तव में छह संभावनाएं)

तो, मुझे कौन सा पसंद करना चाहिए? कोई क्यों? क्या सी डेवलपर्स के बीच किसी प्रकार का अलिखित मानक है?


3
बस एक अवलोकन नोट, अधिकांश ऑपरेटिंग सिस्टम विकल्प 3 का उपयोग करते हैं - कॉलर किसी भी तरह बफर आवंटित करता है; बफर सूचक और क्षमता बताता है; यदि बफर अपर्याप्त है तो कैली बफर भरता है और स्ट्रिंग की वास्तविक लंबाई भी लौटाता है। उदाहरण: sysctlbynameOS X और iOS
rwong

जवाबों:


11

मैंने जो तरीके देखे हैं उनमें 2 और 3 हैं।

उपयोग किए गए बफर वास्तव में उपयोग करने के लिए काफी सरल है:

char[128] buffer;
mytype_to_string(mt, buffer, 128);

हालांकि अधिकांश कार्यान्वयन उपयोग किए गए बफर की मात्रा वापस कर देंगे।

विकल्प 2 धीमी हो जाएगा और गतिशील रूप से जुड़े पुस्तकालयों का उपयोग करते समय खतरनाक होता है जहां वे अलग-अलग रनटाइम (और अलग-अलग ढेर) का उपयोग कर सकते हैं। तो आप मुक्त नहीं कर सकते कि दूसरे पुस्तकालय में क्या रखा गया है। इसके बाद इससे free_string(char*)निपटने के लिए एक फ़ंक्शन की आवश्यकता होती है ।


धन्यवाद! मुझे लगता है कि मुझे वैकल्पिक 3 सबसे अच्छा लगता है। हालांकि मैं चीजों को करने में सक्षम होना चाहता हूं: printf("MyType: %s\n", mytype_to_string( mt, buf, sizeof(buf));और इसलिए मैं इस्तेमाल की गई लंबाई को वापस नहीं करना चाहता, बल्कि स्ट्रिंग के लिए सूचक भी। गतिशील पुस्तकालय टिप्पणी वास्तव में महत्वपूर्ण है।
Øystein Schønning-Johansen

क्या यह टर्मिनेटर sizeof(buffer) - 1को संतुष्ट करने के लिए नहीं होना चाहिए \0?
माइकल-ओ

1
@ माइकल-ओ नो नल शब्द बफ़र साइज़ में शामिल है जिसका अर्थ है कि जो अधिकतम स्ट्रिंग लगाई जा सकती है वह आकार में पारित होने से 1 कम है। यह वह पैटर्न है जो सुरक्षित स्ट्रिंग snprintfउपयोग की तरह मानक पुस्तकालय में कार्य करता है ।
शाफ़्ट फ्राक

@ratchetfreak स्पष्टीकरण के लिए धन्यवाद। उस ज्ञान के साथ उत्तर का विस्तार करना अच्छा होगा।
माइकल-ओ

0

# 3 के लिए अतिरिक्त डिजाइन विचार

जब संभव हो, तो mytype.h फ़ाइल के लिए आवश्यक अधिकतम आकार भी प्रदान करें mytype_to_string()

#define MYTYPE_TO_STRING_SIZE 256

अब उपयोगकर्ता तदनुसार कोड कर सकते हैं।

char buf[MYTYPE_TO_STRING_SIZE];
puts(mytype_to_string(mt, buf, sizeof buf));

गण

सरणियों के आकार, जब पहली, VLA प्रकार के लिए अनुमति देता है।

char * mytype_to_string( const mytype_t *mt, size_t bufsize, char *buf[bufsize]); 

एकल आयाम के साथ इतना महत्वपूर्ण नहीं है, फिर भी 2 या अधिक के साथ उपयोगी नहीं है।

void matrix(size_t row, size_t col, double matrix[row][col]);

मुझे याद है कि पहले साइज़ पढ़ना अगले सी में एक पसंदीदा मुहावरा है। उस संदर्भ को खोजने की आवश्यकता है ...।


0

@ Ratchetfreak के उत्कृष्ट उत्तर के अतिरिक्त, मैं यह बताना चाहूंगा कि वैकल्पिक # 3 मानक सी लाइब्रेरी फ़ंक्शंस के समान समान प्रतिमान / पैटर्न का अनुसरण करता है।

उदाहरण के लिए, strncpy

char * strncpy ( char * destination, const char * source, size_t num );

उसी प्रतिमान के बाद नए डेवलपर्स (या यहां तक ​​कि आपके भविष्य के स्वयं) के लिए संज्ञानात्मक भार को कम करने में मदद मिलेगी जब उन्हें अपने फ़ंक्शन का उपयोग करने की आवश्यकता होती है।

केवल क्या आप अपनी पोस्ट में है के साथ अंतर हो जाएगा कि destinationसी पुस्तकालयों में तर्क तर्क सूची में पहले सूचीबद्ध हो जाता है। इसलिए:

char * mytype_to_string( char *buf, const mytype_t *mt, size_t buflen ); 

-2

इस तथ्य के अलावा कि आप जो करने का प्रस्ताव कर रहे हैं वह एक खराब कोड गंध है, वैकल्पिक 3 मुझे सबसे अच्छा लगता है। मुझे @ gnasher729 की तरह भी लगता है कि आप गलत भाषा का उपयोग कर रहे हैं।


वास्तव में क्या आप एक कोड गंध मानते हैं? कृपया विस्तार से बताएं।
हल्क

-3

ईमानदार होने के लिए, आप एक अलग भाषा में स्विच करना चाह सकते हैं, जहां एक स्ट्रिंग वापस करना एक जटिल नहीं है, काम गहन और त्रुटि प्रवण ऑपरेशन।

आप C ++ या ऑब्जेक्टिव-सी पर विचार कर सकते हैं, जहाँ आप अपने कोड का 99% अपरिवर्तित छोड़ सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.