परिचय: Rust में संख्या और स्ट्रिंग को सीधे क्यों नहीं जोड़ा जा सकता?
\n\nयदि आप Python या JavaScript से आए हैं, तो आप str(42) या 42 + "" जैसा कुछ लिखने के आदी हैं। Rust में ऐसी चाल नहीं चलेगी। कंपाइलर सख्ती से पूछेगा: "तुम कौन सा टाइप चाहते हो? Integer? String? फैसला करो!"
प्रश्न "How do I convert from an integer to a string?" Stack Overflow पर Rust अनुभाग में सबसे लोकप्रिय प्रश्नों में से एक है। हज़ारों डेवलपर्स सोच में पड़ जाते हैं कि जब वे यह लिखने की कोशिश करते हैं तो उनका कोड कंपाइल क्यों नहीं होता:
\n\nlet number = 42;\nlet text = number; // त्रुटि: expected `&str`, found `i32`\n\nआज हम इस रूपांतरण के अंदरूनी तंत्र को देखेंगे। आप न केवल यह सीखेंगे कि यह कैसे करना है, बल्कि यह भी कि यह कैसे काम करता है traits, allocations और यहां तक कि assembler के स्तर पर। चलिए शुरू करते हैं!
\n\nसबसे आसान तरीका: to_string() विधि
\n\nRust में, अधिकांश आधुनिक भाषाओं की तरह, पूर्णांक प्रकारों में to_string() विधि होती है। यह भ्रामक रूप से सरल दिखता है:
fn main() {\n let num: i32 = 255;\n let s: String = num.to_string();\n println!("{}", s); // आउटपुट: "255"\n}\n\nयह सभी पूर्णांक प्रकारों के लिए काम करता है: i8, u32, i64, usize आदि।
अंदर क्या होता है?
\n\nto_string() विधि कंपाइलर का जादू नहीं है। इसे Display trait के माध्यम से कार्यान्वित किया गया है। Rust की मानक लाइब्रेरी में यह कार्यान्वयन है:
// मानक लाइब्रेरी से सरलीकृत संस्करण\nimpl<T: fmt::Display> ToString for T {\n #[inline]\n fn to_string(&self) -> String {\n use fmt::Write;\n let mut buf = String::new();\n // यहाँ Display trait की fmt() विधि कॉल की जाती है\n let _ = buf.write_fmt(format_args!("{}", self));\n buf.shrink_to_fit(); // मेमोरी ऑप्टिमाइज़ेशन\n buf\n }\n}\n\nमुख्य बिंदु: to_string() हीप (heap) पर एक नई String बनाता है। प्रत्येक कॉल एक मेमोरी आवंटन है। सैकड़ों-हज़ारों रूपांतरणों के लिए यह प्रदर्शन में बाधा बन सकता है।
विकल्प: format! मैक्रो
\n\nदूसरा लोकप्रिय तरीका format! मैक्रो है। यह println! की तरह काम करता है, लेकिन कंसोल पर आउटपुट देने के बजाय एक String लौटाता है:
fn main() {\n let num = 1024;\n let s = format!("{}", num);\n println!("स्ट्रिंग की लंबाई: {}", s.len()); // 4\n}\n\nto_string() और format! के बीच अंतर न्यूनतम है। to_string() आंतरिक रूप से format_args! और write_fmt को कॉल करता है। मूलतः, ये एक ही हैं। चुनाव शैली और पठनीयता का मामला है।
format! का उपयोग कब करें?
\n- \n
- जब संख्या को स्ट्रिंग के बीच में डालना हो:
format!("संख्या: {}", num)\n - जब फ़ॉर्मेट जटिल हो (हेक्साडेसिमल, विभाजकों के साथ):
format!("{:#x}", 255)→ "0xff" \n - जब कोड की अभिव्यक्ति महत्वपूर्ण हो \n
Display trait बनाम ToString: क्या तेज़ है?
\n\nयदि आप कोई लाइब्रेरी या उच्च-लोड कोड लिख रहे हैं, तो सीधे Display trait का उपयोग write! के माध्यम से बफर में करें। यह पहले से आवंटित मेमोरी को पुन: उपयोग करने की अनुमति देता है:
use std::fmt::Write;\n\nfn main() {\n let num = 42;\n let mut buffer = String::with_capacity(20); // पहले से मेमोरी आवंटित करें\n\n // बफर में संख्या लिखें\n write!(buffer, "{}", num).unwrap();\n println!("{}", buffer); // "42"\n\n // साफ़ करें और फिर से उपयोग करें\n buffer.clear();\n write!(buffer, "{}", 256).unwrap();\n println!("{}", buffer); // "256"\n}\n\nयह दृष्टिकोण उन लूपों में 2-3x प्रदर्शन लाभ देता है जहाँ बार-बार संख्याओं को स्ट्रिंग में बदलने की आवश्यकता होती है, क्योंकि मेमोरी आवंटन केवल एक बार होता है।