تحويل String إلى int في Rust: دليل كامل مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا لا يسمح Rust بتحويل السلسلة النصية إلى رقم ببساطة؟



إذا كنت قادماً من Python أو JavaScript، فأنت معتاد على السحر مثل int("42") أو parseInt("42"). في Rust، لن تنجح هذه الخدعة — سيطلب منك المترجم تحديد النوع الذي تريد تحويل السلسلة النصية إليه بالضبط. لماذا؟ لأن Rust هي لغة لا تغفر الإهمال. إنها تجبرك على التفكير في الحالات الحدودية: ماذا لو كانت السلسلة النصية تحتوي على شيء غير رقمي؟ ماذا لو كان الرقم كبيراً جداً بالنسبة للنوع المختار؟



في هذه المقالة، سنتناول السؤال الأكثر شيوعاً على Stack Overflow بين المبتدئين في Rust: كيفية تحويل String إلى int. ستحصل ليس فقط على كود جاهز، بل على فهم كامل لما يحدث تحت الغطاء.



طريقة parse() — الأداة الرئيسية للتحويل



الطريقة الأساسية لتحويل سلسلة نصية إلى رقم في Rust هي طريقة parse()، المتاحة للنوع String و &str. وهي مطبقة عبر trait FromStr وتعيد Result<T, E>.



مثال أساسي: String → i32



fn main() {    let number_string = String::from("42");    let number: i32 = number_string.parse().unwrap();    println!("الرقم: {}", number); // الإخراج: الرقم: 42}


لاحظ استخدام unwrap(). هذه طريقة سريعة "لاستخراج" القيمة من Result، لكنها خطيرة: إذا لم تكن السلسلة النصية رقماً، سيصاب البرنامج بالذعر ويسقط.



معالجة الأخطاء الصحيحة



في الكود الحقيقي، يجب ألا تستخدم unwrap() دون تفكير. إليك الطريقة الصحيحة:



use std::num::ParseIntError;

fn main() { let input = String::from("hello"); match input.parse::<i32>() { Ok(number) => println!("نجاح: {}", number), Err(e) => println!("خطأ في التحويل: {}", e), }}


أو صيغة أكثر إيجازاً باستخدام if let:



fn main() {    let input = String::from("2024");        if let Ok(year) = input.parse::<i32>() {        println!("السنة: {}", year);    } else {        println!("فشل تحليل السلسلة النصية");    }}


الأنواع الصحيحة المتاحة للتحويل



يقدم Rust مجموعة غنية من الأنواع الصحيحة. يمكنك تحويل السلسلة النصية إلى أي منها:



  • i8, i16, i32, i64, i128 — أعداد صحيحة بإشارة
  • u8, u16, u32, u64, u128 — أعداد صحيحة بدون إشارة
  • isize, usize — الحجم يعتمد على البنية


مثال على التحويل إلى أنواع مختلفة:



fn main() {    let val = "255";        let a: u8  = val.parse().unwrap();   // 255    let b: i16 = val.parse().unwrap();   // 255    let c: u32 = val.parse().unwrap();   // 255        // لكن هذا سيسبب خطأ — 255 لا يسع في i8    // let d: i8 = val.parse().unwrap(); // PANIC!}


تقنيات متقدمة: from_str والأنواع المخصصة



طريقة parse() تستدعي داخلياً from_str() من trait FromStr. يمكنك تطبيق هذا trait على الهياكل الخاصة بك:



use std::str::FromStr;use std::num::ParseIntError;

#[derive(Debug)]struct Version { major: u32, minor: u32,}

impl FromStr for Version { type Err = ParseIntError; fn from_str(s: &str) -> Result<Self, Self::Err> { let parts: Vec<&str> = s.split('.').collect(); if parts.len() != 2 { // ننشئ خطأنا الخاص، لكن للمثال نستخدم ParseIntError return Err("1.0".parse::<u32>().unwrap_err()); } let major = parts[0].p

المدونات

توصيات الكتب