सी स्ट्रिंग हैंडलिंग

सी प्रोग्रामिंग भाषा में अपने मानक लाइब्रेरी में सी स्ट्रिंग हैंडलिंग (लिपि स्ट्रिंग और बाइट स्ट्रिंग) पर संचालन को प्रयुक्त करने वाले फंक्शन का एक समूह है। प्रतिलिपि बनाना, संयोजन, टोकनीकरण और खोज जैसे विभिन्न ऑपरेशन समर्थित हैं। लिपि स्ट्रिंग के लिए, मानक लाइब्रेरी इस विधि का उपयोग करती है कि स्ट्रिंग को रिक्त किया जाता है। $n$ वर्णों की एक स्ट्रिंग को $n + 1$ तत्वों की एक सरणी (डेटा संरचना) के रूप में दर्शाया जाता है, जिनमें से अंतिम स्ट्रिंग NUL "है।

प्रोग्रामिंग भाषा में स्ट्रिंग के लिए एकमात्र समर्थन यह है कि कंपाइलर उद्धृत स्ट्रिंग स्थिरांक को शून्य-समाप्त स्ट्रिंग में अनुवादित करता है।

परिभाषाएँ
एक स्ट्रिंग को पहली शून्य कोड इकाई (जिसे प्रायः एनयूएल कोड इकाई कहा जाता है।) द्वारा समाप्त की गई कोड इकाइयों के एक सन्निहित अनुक्रम के रूप में परिभाषित किया गया है। इसका मतलब है। कि एक स्ट्रिंग में शून्य कोड इकाई नहीं हो सकती है, क्योंकि पहली बार देखी गई इकाई स्ट्रिंग के अंत को चिह्नित करती है। एक स्ट्रिंग की लंबाई शून्य कोड इकाई से पहले कोड इकाइयों की संख्या है। एक स्ट्रिंग द्वारा कब्जा की गई मेमोरी सदैव लंबाई से एक अधिक कोड इकाई होती है, क्योंकि शून्य टर्मिनेटर को संग्रहीत करने के लिए स्थान की आवश्यकता होती है।

सामान्यतः, स्ट्रिंग शब्द का अर्थ एक स्ट्रिंग है। जहां कोड इकाई  प्रकार की होती है, जो सभी आधुनिक मशीनों पर बिल्कुल 8 बिट होती है। C90 (सी संस्करण) विस्तृत स्ट्रिंग को परिभाषित करता है। जो   प्रकार की एक कोड इकाई का उपयोग करता है, जो आधुनिक मशीनों पर 16 या 32 बिट है। यह यूनिकोड के लिए था लेकिन इसके बजाय यूनिकोड के लिए सामान्य स्ट्रिंग में यूटीएफ-8 का उपयोग करना आम होता जा रहा है।

पहली कोड इकाई में एक पॉइंटर पास करके स्ट्रिंग को फ़ंक्शंन में पास किया जाता है। चूँकि  और   अलग-अलग प्रकार के हैं व्यापक स्ट्रिंग को प्रोसेस करने वाले फ़ंक्शन सामान्य स्ट्रिंग को प्रोसेस करने वाले फ़ंक्शंन से भिन्न होते हैं। और उनके अलग-अलग नाम होते हैं।

संकलन के दौरान स्ट्रिंग अक्षर (सी स्रोत कोड में ) को सरणियों में बदल दिया जाता है। परिणाम कोड इकाइयों की एक सरणी है। जिसमें सभी वर्ण और एक पिछली शून्य कोड इकाई सम्मिलित है। C90 में   एक विस्तृत स्ट्रिंग उत्पन्न करता है। एक स्ट्रिंग शाब्दिक में शून्य कोड इकाई हो सकती है। (एक तरीका स्रोत में   डालना है। ), लेकिन इससे स्ट्रिंग उस बिंदु पर समाप्त हो जाएगी। शेष शाब्दिक को मेमोरी में रखा जाएगा (अंत में एक और शून्य कोड इकाई को जोड़कर) लेकिन यह जानना असंभव है। कि उन कोड इकाइयों को स्ट्रिंग शाब्दिक से अनुवादित किया गया था, इसलिए ऐसा स्रोत कोड एक स्ट्रिंग शाब्दिक नहीं है।

लिपि एनकोडिंग
प्रत्येक स्ट्रिंग उपयुक्त प्रकार ( या  ) की शून्य कोड इकाई की पहली घटना पर समाप्त होती है। नतीजतन, एक बाइट स्ट्रिंग (char*) में ASCII या किसी ASCII एक्सटेंशन में गैर-NUL वर्ण हो सकते हैं लेकिन यूटीएफ-16 जैसे एन्कोडिंग में वर्ण नहीं हो सकते हैं। (यद्यपि 16-बिट कोड इकाई गैर-शून्य हो, इसकी उच्च या निम्न बाइट शून्य हो सकता है। )। जिन एन्कोडिंग को विस्तृत स्ट्रिंग में संग्रहीत किया जा सकता है, उन्हें   की चौड़ाई द्वारा परिभाषित किया गया है। अधिकांश कार्यान्वयन में   कम से कम 16 बिट है, और इसलिए सभी 16-बिट एन्कोडिंग, जैसे यूसीएस -2, को संग्रहीत किया जा सकता है। यदि   32-बिट है, तो 32-बिट एन्कोडिंग, जैसे यूटीएफ-32 संग्रहीत किया जा सकता है। (मानक के लिए एक "प्रकार जो किसी भी विस्तृत वर्ण को धारण करता है। " की आवश्यकता होती है, जो UCS-2 से यूटीएफ-16 में बदलाव के बाद से विंडोज़ पर अब सच नहीं है। इसे मानक में एक दोष के रूप में पहचाना गया और C++ में ठीक किया गया।) C++11 और C11 स्पष्ट चौड़ाई char16_t और char32_t के साथ दो प्रकार जोड़ते हैं।

परिवर्तनीय-चौड़ाई एन्कोडिंग का उपयोग बाइट स्ट्रिंग और वाइड स्ट्रिंग दोनों में किया जा सकता है। स्ट्रिंग की लंबाई और ऑफसमूह को बाइट्स या  में मापा जाता है, न कि "अक्षरों" में, जो शुरुआती प्रोग्रामर के लिए भ्रमित करने वाला हो सकता है। यूटीएफ-8 और Shift JIS का उपयोग प्रायः C बाइट स्ट्रिंग में किया जाता है, जबकि यूटीएफ-16 का उपयोग प्रायः C वाइड स्ट्रिंग में किया जाता है। जब   16 बिट होता है।   जैसे फ़ंक्शंन का उपयोग करके चर-चौड़ाई वाले वर्णों के साथ स्ट्रिंग को छोटा करना स्ट्रिंग के अंत में अमान्य अनुक्रम उत्पन्न कर सकता है। यह असुरक्षित हो सकता है। यदि काटे गए हिस्सों की व्याख्या उस कोड द्वारा की जाती है। जो मानता है। कि इनपुट वैध है।

यूनिकोड शाब्दिक के लिए समर्थन जैसे char foo[512] = "φωωβαρ"; (यूटीएफ-8) या wchar_t foo[512] = L"φωωβαρ"; (यूटीएफ-16 या यूटीएफ-32, wchar_t पर निर्भर करता है। ) कार्यान्वयन परिभाषित है, [6] और इसके लिए आवश्यक हो सकता है। कि स्रोत कोड एक ही एन्कोडिंग में हो, विशेष रूप से चार के लिए जहां कंपाइलर उद्धरणों के बीच जो कुछ भी है। उसे कॉपी कर सकते हैं। कुछ कंपाइलरों या संपादकों को यूटीएफ-8 के प्रत्येक बाइट के लिए सभी गैर-ASCII वर्णों को अनुक्रमों के रूप में, और/या यूटीएफ-16 के प्रत्येक शब्द के लिए \uNNNN दर्ज करने की आवश्यकता होगी। C11 (और C++11) के बाद से, एक नया char foo[512] = u8"φωωβαρ"; शाब्दिक सिंटैक्स उपलब्ध है। जो बाइटस्ट्रिंग शाब्दिक के लिए यूटीएफ-8 की गारंटी देता है। C++20 और C23 के बाद से, एक   प्रकार जोड़ा गया था जो यूटीएफ-8 वर्णों को संग्रहीत करने के लिए है। और यू-8 उपसर्ग वर्ण और स्ट्रिंग अक्षर के प्रकारों को क्रमशः   और   में बदल दिया गया था।

फंक्शन का अवलोकन
C स्ट्रिंग पर चलने वाले अधिकांश फ़ंक्शन  हेडर (C++ में  ) में घोषित किए जाते हैं जबकि C वाइड स्ट्रिंग पर चलने वाले फ़ंक्शन   हेडर (C++ में  ) में घोषित किए जाते हैं। इन हेडर में मेमोरी बफ़र्स को संभालने के लिए उपयोग किए जाने वाले फ़ंक्शन की घोषणाएं भी सम्मिलित हैं। इस प्रकार यह नाम एक मिथ्या नाम है।

में घोषित फ़ंक्शंन बेहद लोकप्रिय हैं क्योंकि सी मानक लाइब्रेरी के एक भाग के रूप में, उन्हें सी का समर्थन करने वाले किसी भी प्लेटफ़ॉर्म पर काम करने की गारंटी दी जाती है। हालाँकि, इन फ़ंक्शंन के साथ कुछ सुरक्षा समस्याएं सम्मिलित हैं जैसे कि उपयोग न किए जाने पर संभावित बफर ओवरफ़्लो सावधानीपूर्वक और उचित तरीके से, जिससे प्रोग्रामर सुरक्षित और संभवतः कम पोर्टेबल वेरिएंट पसंद करते हैं जिनमें से कुछ लोकप्रिय नीचे सूचीबद्ध हैं। इनमें से कुछ फ़ंक्शन एक  स्ट्रिंग पॉइंटर को स्वीकार करके और स्ट्रिंग के भीतर एक गैर-कॉन्स्ट पॉइंटर को वापस करके कॉन्स्ट-शुद्धता का उल्लंघन भी करते हैं। इसे ठीक करने के लिए, कुछ को मानक लाइब्रेरी के C++ संस्करण में दो अतिभारित फ़ंक्शंन में विभाजित किया गया है।

ऐतिहासिक दस्तावेज़ीकरण में C स्ट्रिंग के लिए "बाइट" के स्थान पर प्रायः "लिपि" शब्द का उपयोग किया जाता था, जिससे कई लोगों को यह विश्वास हो जाता है। कि ये फ़ंक्शन किसी तरह यूटीएफ-8 के लिए काम नहीं करते हैं। वास्तव में सभी लंबाई को बाइट्स के रूप में परिभाषित किया गया है। और यह सभी कार्यान्वयनों में सच है, और ये फ़ंक्शन यूटीएफ -8 के साथ-साथ सिंगल-बाइट एन्कोडिंग के साथ भी काम करते हैं। इसे स्पष्ट करने के लिए बीएसडी दस्तावेज़ को ठीक कर दिया गया है, लेकिन पॉज़िक्स, लिनक्स और विंडोज़ दस्तावेज़ अभी भी कई स्थानों पर "वर्ण" का उपयोग करते हैं। जहां "बाइट" या wchar_t सही शब्द है।

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

फंक्शन
{| class="wikitable" ! ! बाइट स्ट्रिंग ! वाइड स्ट्रिंग ! विवरण ! rowspan=5 | स्ट्रिंग प्रकलन (कंप्यूटर) ! rowspan=11 | स्ट्रिंग परीक्षण !विविध ! rowspan=5 | मेमोरी प्रकलन (कंप्यूटर)
 * strcpy
 * wcscpy
 * एक स्ट्रिंग को दूसरे में कॉपी करता है।
 * strncpy
 * wcsncpy
 * स्रोत से कॉपी करके या शून्य जोड़कर बिल्कुल n बाइट्स लिखता है।
 * strcat
 * wcscat
 * एक स्ट्रिंग को दूसरे से जोड़ता है।
 * strncat
 * wcsncat
 * एक स्ट्रिंग से दूसरे स्ट्रिंग में n बाइट्स से अधिक नहीं जोड़ता
 * strxfrm
 * wcsxfrm
 * वर्तमान स्थान के अनुसार एक स्ट्रिंग को रूपांतरित करता है।
 * strxfrm
 * wcsxfrm
 * वर्तमान स्थान के अनुसार एक स्ट्रिंग को रूपांतरित करता है।
 * वर्तमान स्थान के अनुसार एक स्ट्रिंग को रूपांतरित करता है।
 * strlen
 * wcslen
 * स्ट्रिंग की लंबाई लौटाता है।
 * strcmp
 * wcscmp
 * दो तारों की तुलना करता है। (तीन-तरफा तुलना)
 * strncmp
 * wcsncmp
 * दो स्ट्रिंग में बाइट्स की एक विशिष्ट संख्या की तुलना करता है।
 * strcoll
 * wcscoll
 * वर्तमान स्थान के अनुसार दो स्ट्रिंग की तुलना करता है।
 * strchr
 * wcschr
 * एक स्ट्रिंग में बाइट की पहली घटना ढूँढता है।
 * strrchr
 * wcsrchr
 * एक स्ट्रिंग में बाइट की अंतिम घटना ढूँढता है।
 * strspn
 * wcsspn
 * एक स्ट्रिंग में प्रारंभिक बाइट्स की संख्या लौटाता है। जो दूसरी स्ट्रिंग में हैं।
 * strcspn
 * wcscspn
 * एक स्ट्रिंग में प्रारंभिक बाइट्स की संख्या लौटाता है। जो दूसरी स्ट्रिंग में नहीं हैं।
 * strpbrk
 * wcspbrk
 * एक स्ट्रिंग में एक समूह में बाइट की पहली घटना ढूँढता है।
 * strstr
 * wcsstr
 * एक स्ट्रिंग में एक सबस्ट्रिंग की पहली घटना ढूँढता है।
 * strtok
 * wcstok
 * एक स्ट्रिंग को टोकन में विभाजित करता है।
 * wcspbrk
 * एक स्ट्रिंग में एक समूह में बाइट की पहली घटना ढूँढता है।
 * strstr
 * wcsstr
 * एक स्ट्रिंग में एक सबस्ट्रिंग की पहली घटना ढूँढता है।
 * strtok
 * wcstok
 * एक स्ट्रिंग को टोकन में विभाजित करता है।
 * wcstok
 * एक स्ट्रिंग को टोकन में विभाजित करता है।
 * strerror
 * N/A
 * त्रुटि कोड से प्राप्त संदेश वाली एक स्ट्रिंग लौटाता है।
 * memset
 * wmemset
 * एक बफ़र को बार-बार बाइट से भरता है।
 * memcpy
 * wmemcpy
 * एक बफ़र को दूसरे बफ़र में कॉपी करता है।
 * memmove
 * wmemmove
 * एक बफ़र को दूसरे संभवतः ओवरलैपिंग बफ़र में कॉपी करता है।
 * memcmp
 * wmemcmp
 * दो बफ़र्स की तीन-तरफ़ा तुलना करता है।
 * memchr
 * wmemchr
 * बफ़र में बाइट की पहली घटना ढूँढता है।
 * colspan=4 | और को ऐसे फ़ंक्शंन से बदलने की अच्छी तरह से स्थापित आवश्यकता के अतिरिक्त जो बफर ओवरफ़्लो की स्वीकृति नहीं देते हैं, कोई स्वीकृत मानक उत्पन्न नहीं हुआ है। यह आंशिक रूप से कई सी प्रोग्रामर की गलत धारणा के कारण है कि   और   में वांछित व्यवहार है। हालाँकि, इसके लिए कोई भी फ़ंक्शन डिज़ाइन नहीं किया गया था (उनका उद्देश्य शून्य-पैडेड निश्चित-आकार स्ट्रिंग बफ़र्स में हेरफेर करना था, एक डेटा प्रारूप जो आधुनिक सॉफ़्टवेयर में सामान्यतः कम उपयोग किया जाता है) और व्यवहार और तर्क गैर-सहज ज्ञान युक्त हैं और प्रायः विशेषज्ञ प्रोग्रामर द्वारा भी गलत तरीके से लिखे गए हैं।
 * memchr
 * wmemchr
 * बफ़र में बाइट की पहली घटना ढूँढता है।
 * colspan=4 | और को ऐसे फ़ंक्शंन से बदलने की अच्छी तरह से स्थापित आवश्यकता के अतिरिक्त जो बफर ओवरफ़्लो की स्वीकृति नहीं देते हैं, कोई स्वीकृत मानक उत्पन्न नहीं हुआ है। यह आंशिक रूप से कई सी प्रोग्रामर की गलत धारणा के कारण है कि   और   में वांछित व्यवहार है। हालाँकि, इसके लिए कोई भी फ़ंक्शन डिज़ाइन नहीं किया गया था (उनका उद्देश्य शून्य-पैडेड निश्चित-आकार स्ट्रिंग बफ़र्स में हेरफेर करना था, एक डेटा प्रारूप जो आधुनिक सॉफ़्टवेयर में सामान्यतः कम उपयोग किया जाता है) और व्यवहार और तर्क गैर-सहज ज्ञान युक्त हैं और प्रायः विशेषज्ञ प्रोग्रामर द्वारा भी गलत तरीके से लिखे गए हैं।
 * colspan=4 | और को ऐसे फ़ंक्शंन से बदलने की अच्छी तरह से स्थापित आवश्यकता के अतिरिक्त जो बफर ओवरफ़्लो की स्वीकृति नहीं देते हैं, कोई स्वीकृत मानक उत्पन्न नहीं हुआ है। यह आंशिक रूप से कई सी प्रोग्रामर की गलत धारणा के कारण है कि   और   में वांछित व्यवहार है। हालाँकि, इसके लिए कोई भी फ़ंक्शन डिज़ाइन नहीं किया गया था (उनका उद्देश्य शून्य-पैडेड निश्चित-आकार स्ट्रिंग बफ़र्स में हेरफेर करना था, एक डेटा प्रारूप जो आधुनिक सॉफ़्टवेयर में सामान्यतः कम उपयोग किया जाता है) और व्यवहार और तर्क गैर-सहज ज्ञान युक्त हैं और प्रायः विशेषज्ञ प्रोग्रामर द्वारा भी गलत तरीके से लिखे गए हैं।

सबसे लोकप्रिय प्रतिस्थापन  और   फ़ंक्शंन हैं, जो दिसंबर, 1998 में Openबीएसडी 2.4 में दिखाई दिए।[95] ये फ़ंक्शन सदैव गंतव्य बफर में एक एनयूएल लिखते हैं, यदि आवश्यक हो तो परिणाम को छोटा कर देते हैं, और आवश्यक बफर के आकार को वापस कर देते हैं, जो ट्रंकेशन का पता लगाने की स्वीकृति देता है और एक नया बफर बनाने के लिए एक आकार प्रदान करता है जो ट्रंकेट नहीं होगा। कथित तौर पर अप्रभावी होने, [100] सी स्ट्रिंग (स्ट्रिंग के कुछ बेहतर वैकल्पिक रूप के बजाय) के उपयोग को प्रोत्साहित करने, और अन्य संभावित त्रुटियों को छिपाने के आधार पर उनकी आलोचना की गई है।  नतीजतन, उन्हें जीएनयू सी लाइब्रेरी (लिनक्स पर सॉफ्टवेयर द्वारा उपयोग किया जाता है) में सम्मिलित नहीं किया गया है, हालांकि उन्हें ओपनबीएसडी, फ्रीबीएसडी, नेटबीएसडी, सोलारिस, ओएस एक्स और क्यूएनएक्स के लिए सी लाइब्रेरी के साथ-साथ वैकल्पिक सी लाइब्रेरी में भी प्रयुक्त किया गया है। लिनक्स के लिए, जैसे कि libबीएसडी, 2008 में पेश किया गया, और musl, 2011 में पेश किया गया।  जीएनयू सी लाइब्रेरी समर्थन की कमी ने विभिन्न सॉफ्टवेयर लेखकों को इसका उपयोग करने और अन्य एसडीएल, जीएलआईबी, एफएफएमपीईजी, आरसिंक और यहां तक ​​​​कि आंतरिक रूप से लिनक्स कर्नेल में प्रतिस्थापन को बंडल करने से नहीं रोका है। इन फंक्शन के लिए ओपन सोर्स कार्यान्वयन उपलब्ध हैं।

कभी-कभी या  का उपयोग किया जाता है, क्योंकि वे   की तुलना में अधिक कुशल हो सकते हैं क्योंकि वे बार-बार NUL की जांच नहीं करते हैं (आधुनिक प्रोसेसर पर यह कम सच है)। चूँकि उन्हें एक पैरामीटर के रूप में बफर लंबाई की आवश्यकता होती है, इस पैरामीटर की सही समूहिंग बफर ओवरफ्लो से बच सकती है।

अपने 2004 Microsoft सुरक्षा विकास जीवनचक्र के हिस्से के रूप में, माइक्रोसॉफ्ट ने और   (कई अन्य के साथ) सहित "सुरक्षित" फंक्शन का एक परिवार पेश किया। इन फंक्शन को ISO/IEC WDTR 24731 द्वारा प्रस्तावित वैकल्पिक C11 (अनुलग्नक K) के हिस्से के रूप में कुछ मामूली बदलावों के साथ मानकीकृत किया गया था। ये फ़ंक्शन विभिन्न जांच करते हैं, जिसमें यह भी सम्मिलित है कि स्ट्रिंग बफर में फिट होने के लिए बहुत लंबी है या नहीं। यदि जांच विफल हो जाती है, तो उपयोगकर्ता द्वारा निर्दिष्ट "रनटाइम-बाधा हैंडलर" फ़ंक्शन को कॉल किया जाता है, जो सामान्यतः प्रोग्राम को बंद कर देता है।  कुछ फ़ंक्शन रनटाइम-बाधा हैंडलर को कॉल करने से पहले विनाशकारी संचालन करते हैं; उदाहरण के लिए,   गंतव्य को खाली स्ट्रिंग पर समूह करता है, जिससे त्रुटि स्थितियों से पुनर्प्राप्त करना या उन्हें डीबग करना मुश्किल हो सकता है। इन फ़ंक्शंन ने काफी आलोचना को आकर्षित किया क्योंकि शुरुआत में इन्हें केवल विंडोज़ पर प्रयुक्त किया गया था और साथ ही माइक्रोसॉफ्ट विजुअल सी ++ द्वारा चेतावनी संदेश भी तैयार किए जाने लगे, जिसमें प्रोग्रामर को मानक फ़ंक्शंन के बजाय इन फ़ंक्शंन का उपयोग करने का सुझाव दिया गया। कुछ लोगों का अनुमान है कि यह माइक्रोसॉफ्ट द्वारा डेवलपर्स को अपने प्लेटफॉर्म में लॉक करने का एक प्रयास है। हालाँकि इन फ़ंक्शंन का ओपन-सोर्स कार्यान्वयन उपलब्ध है, ये फ़ंक्शंन सामान्य यूनिक्स सी लाइब्रेरीों में सम्मिलित नहीं हैं। इन फंक्शन के साथ अनुभव ने उन्हें अपनाने और उपयोग में त्रुटियों के साथ महत्वपूर्ण समस्याएं दिखाई हैं, इसलिए सी मानक के अगले संशोधन के लिए अनुबंध K को हटाने का प्रस्ताव है। अवांछित कंपाइलर अनुकूलन से बचने के एक तरीके के रूप में memset_s के उपयोग का भी सुझाव दिया गया है।

यह भी देखें

 * – बैकस्लैश एस्केप सीक्वेंस सहित स्रोत कोड सिंटैक्स
 * स्ट्रिंग फ़ंक्शन
 * पर्ल संगत नियमित अभिव्यक्ति (पीसीआरई)

बाहरी संबंध

 * Fast memcpy in C, multiple C coding examples to target different types of CPU instruction architectures