2012-01-26 30 views
18

मैं इस फ़ंक्शन को सी प्रोग्राम में उपयोग करने का प्रयास कर रहा हूं जिसे लिनक्स और विंडोज में संकलित करने में सक्षम होना चाहिए। सबसे पहले मैंने strtok_r का उपयोग करने की कोशिश की, लेकिन फिर जब मैंने विंडोज़ पर संकलित किया, तो इसने फ़ंक्शन के बारे में शिकायत नहीं की और कहा कि यह मानता है कि यह एक बाहरी कार्य है, लेकिन फिर विफल रहा। मैं फिर strtok_s का इस्तेमाल किया और यह संकलित! तब मैंने लिनक्स पर कोशिश की लेकिन अब यह शिकायत कर रहा है कि "strtok_s 'के लिए एक अनिर्धारित संदर्भ है।सी में strtok_r और strtok_s के बीच क्या अंतर है?

क्या एक खिड़कियां केवल कार्य करती हैं और दूसरा एक लिनक्स फ़ंक्शन ??? मैं इसे दोनों पर संकलित करने के लिए क्या कर सकता हूं?

+0

['strtok_r()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok_r.html) पॉज़िक्स है; ['strtok_s()'] (http://msdn.microsoft.com/en-us/library/ftsafwz3.aspx) विंडोज है। सादे 'strtok()' का प्रयोग करें जो सभी कार्यान्वयन * (सहायक सी 8 9) * में उपलब्ध है। – pmg

+3

समस्या यह है कि मुझे स्ट्रिंग को स्ट्रिंग करने की आवश्यकता है जबकि स्ट्रिंगोकिंग एक और स्ट्रिंग है, यही कारण है कि मुझे इसे सहेजने के बाद से इसकी आवश्यकता है। – petranaya

+1

@pmg - जब तक आपको थ्रेड या बफर ओवररन सुरक्षा –

उत्तर

8

ये दोनों कार्य स्ट्रिंग पार्सिंग के लिए वास्तव में बदसूरत, अनजान मुहावरे हैं, और आमतौर पर सूक्ष्म तरीकों से आपके विशेष अनुप्रयोग की आवश्यकताओं को पूरा करने में विफल रहते हैं। मानक सी में सादे strtok के लिए भी मोरेसो। बस उन्हें बाहर फेंक दें और char सरणी पर फिर से चलाने के लिए अपना कोड लिखें और आवश्यकतानुसार इसे तोड़ दें। strchr, strspn, और strcspn ऐसा करने में सहायक हो सकता है या आप सरणी पर स्क्रैच से काम कर सकते हैं।

+1

क्या आप इन कार्यों को खराब क्यों कर सकते हैं इसके बारे में कुछ और बता सकते हैं? यह चरित्र द्वारा चरित्र के माध्यम से जाने और चीजों की खोज करने से मुझे अधिक सहज लगता है। – petranaya

+3

(1) विभाजक चार ओवरराइट/खो गया है, इसलिए जब तक आपके पास केवल एक संभावित विभाजक नहीं है, तो आप जानकारी खो रहे हैं। (2) कई लगातार विभाजकों को एक के रूप में माना जाता है, जो समझ में आता है कि आपका विभाजक व्हाइटस्पेस है, लेकिन उदाहरण के लिए यह कॉमा नहीं है .. –

+3

कृपया ध्यान दें कि निश्चित रूप से * कुछ * स्थितियों में, 'स्ट्रोक' अर्थशास्त्र केवल वही है जो आप चाहते हैं और एकमात्र मुद्दा राज्य की स्थिति है (जो 'strtok_r' और' strtok_s' ठीक है)। मुझे लगता है कि हर बार जब मैंने उनका उपयोग करने की कोशिश की, तो मेरे पार्सिंग की ज़रूरतों का कम से कम एक पहलू है जो वे समर्थन नहीं करते हैं, और यह सीधे कोड लिखना आसान होता है। –

4

strtok_r

strtok_s विंडोज पर strtok के एक बफर लंघन लिए सुरक्षित संस्करण POSIX सिस्टम पर strtok की एक धागा सुरक्षित संस्करण है। विंडोज़ पर मानक स्ट्रोकोक थ्रेड सुरक्षित है, इसलिए strtok_s होना चाहिए।

+0

'strtok_r' POSIX का हिस्सा है और वर्षों से (दशकों?) –

+0

@R - हाँ क्षमा करें यह सी मानक नहीं है, –

+0

संपादित करेगा मुझे अभी भी लगता है कि उत्तर बहुत उपयोगी नहीं है क्योंकि इसमें केवल ओपी (ज्यादातर) पहले से ही पता था, समस्या को हल करने के लिए नहीं। –

29

strtok_s बस strtok_r का विंडोज संस्करण है जो हर जगह मानक है।

#if defined(_WIN32) || defined(_WIN64) 
/* We are on Windows */ 
# define strtok_r strtok_s 
#endif 

प्रोटोटाइप के रूप में और कार्यक्षमता में ही है, आप कर सकते हैं:

एक (आम मुझे लगता है कि होगा) जिस तरह से एक कार्यक्रम पोर्टेबल बनाने के लिए जब यह की तरह strtok_s/strtok_r पूर्वप्रक्रमक उपयोग करने के लिए है कार्यों के लिए आता है अब केवल strtok_r का उपयोग करें।

+0

यह शायद सिगविन पर संकलन करते समय तोड़ देगा जो खुद को विंडोज़ के रूप में रिपोर्ट करता है लेकिन इसमें पहले से परिभाषित 'strtok_r' जैसे पॉज़िक्स इंटरफेस हैं। '#ifndef HAVE_STRTOK_R' (और बिल्ड स्क्रिप्ट में इसका पता लगाने) जैसे कुछ का उपयोग करना बेहतर होगा। –

+0

यदि आप विजुअल स्टूडियो या लिनक्स के तहत संकलित करते हैं तो बहुत अच्छी युक्ति! –

+5

@ आर ..: सिग्विन वास्तव में इस कारण से '_WIN32' (या' _WIN64') को परिभाषित नहीं करता है - इसका सामान्य रूप से कोड की पहचान करने के लिए उपयोग किया जाता है जो गैर-यूनिक्स जैसा है। सिग्विन '__CYGWIN__' और '__unix__' को –

8

मेरे पास अन्य उत्तरों पर टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है, इसलिए मुझे अपना खुद का प्रदान करना होगा।

इस बयान को संबोधित करने के लिए:

"strtok_s एक बफर विंडोज पर strtok के सुरक्षित संस्करण लंघन है खिड़कियों पर मानक strtok सुरक्षित थ्रेड है ...।"

यह सच नहीं है। strtok_s एमएसवीसी कंपाइलर के लिए थ्रेड सुरक्षित संस्करण है। strtok धागा सुरक्षित नहीं है!

इस बयान के समाधान के लिए: "। यह शायद cygwin जो खिड़कियों के रूप में रिपोर्ट लेकिन strtok_r पहले से परिभाषित की तरह POSIX इंटरफेस है पर संकलन करता है, तो टूट जाएगा"

फिर से, सच नहीं है। अंतर यह है कि आप किस कंपाइलर का उपयोग करते हैं। माइक्रोसॉफ्ट के विजुअल सी ++ कंपाइलर का उपयोग करते समय, एमएसवीसी, फंक्शन strtok_s है। जीएनयू कंपाइलर कलेक्शन, जीसीसी जैसे एक और कंपाइलर, एक अलग मानक पुस्तकालय कार्यान्वयन जैसे strtok_r का उपयोग कर सकते हैं। कौन सा फ़ंक्शन उपयोग करने की पहचान करते समय संकलक को लक्षित करें, प्लेटफ़ॉर्म को लक्षित न करें।

मेरी राय में, जोआचिम पिलेबोर्ग का उत्तर इस पृष्ठ पर सबसे अच्छा है।

#if defined(_WIN32) /* || defined(_WIN64) */ 
#define strtok_r strtok_s 
#endif 

दोनों _WIN32 और _WIN64 MSVC संकलक द्वारा प्रदान की पूर्व-निर्धारित मैक्रो हैं: हालांकि, यह एक छोटे से संपादित की जरूरत है।एक 64 बिट लक्ष्य संकलित करते समय _WIN64 परिभाषित किया गया है। _WIN32 को 32 और 64 बिट दोनों लक्ष्यों के लिए परिभाषित किया गया है। यह एक समझौता है कि माइक्रोसॉफ्ट ने पीछे की संगतता के लिए बनाया है। Win32 एपीआई निर्दिष्ट करने के लिए _WIN32 बनाया गया था। अब आपको विंडोज एपीआई निर्दिष्ट करने के लिए _WIN32 पर विचार करना चाहिए - यह 32 बिट लक्ष्य के लिए विशिष्ट नहीं है।

+1

आप पहले बिंदु के बारे में गलत हैं: strtok ** ** विंडोज पर थ्रेड-सुरक्षित है, क्योंकि दो अलग-अलग थ्रेड सुरक्षित रूप से उसी प्रक्रिया के भीतर उस फ़ंक्शन का उपयोग कर सकते हैं, भले ही स्ट्रोक के पास हो अन्य समस्याओं [जैसा कि एक अन्य उत्तर] में बताया गया है (http://stackoverflow.com/a/16821026/656988) @JameyKirby द्वारा। – AntoineL

4

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

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