Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

عامل علامة الاستفهام '?'

جزء من قسم Logic & Flow في رحلة Rust على Coddy — الدرس 46 من 66.

عند العمل مع الدوال التي تُرجع Result، غالبًا ما تحتاج إلى معالجة الأخطاء إما عن طريق التعامل معها محليًا أو تمريرها إلى الدالة المستدعية. توفر لغة Rust عاملًا أنيقًا لهذا النمط الشائع: عامل علامة الاستفهام ?.

يوفر المشغل ? طريقة نظيفة لنشر الأخطاء دون كتابة عبارات match مطولة. عندما تضع ? بعد Result، فإنه يقوم تلقائيًا بفك قيمة Ok أو يعود فورًا من الدالة الحالية مع Err:

fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    let number = s.parse::<i32>()?; // إذا فشل التحليل، قم بإرجاع الخطأ
    Ok(number * 2) // إذا نجح، ضاعف الرقم
}

هذا يعادل كتابة تعبير match كامل، ولكنه أكثر إيجازاً بكثير. إذا أرجع s.parse::<i32>() القيمة Ok، فإن ? يستخرج القيمة ويخصصها لـ number. أما إذا أرجع Err، فإن ? يعيد ذلك الخطأ فوراً من الدالة بأكملها.

لاحظ بناء الجملة ::<i32> — يُسمى هذا turbofish، وهو يخبر Rust بنوع البيانات الذي يجب تحليل السلسلة النصية إليه. تُرجع الدالة Result<i32, std::num::ParseIntError>، حيث i32 هو نوع النجاح و std::num::ParseIntError هو نوع الخطأ الذي يتم إرجاعه عند فشل التحليل.

يمكن استخدام العامل ? فقط في الدوال التي تُرجع Result (أو Option)، بما أنه يحتاج إلى القدرة على إرجاع خطأ.

challenge icon

التحدي

سهل

ستتلقى مدخلين. المدخل الأول هو سلسلة نصية يجب تحويلها إلى عدد صحيح، والمدخل الثاني هو سلسلة نصية أخرى يجب تحويلها أيضاً إلى عدد صحيح. قم بإنشاء دالة تسمى add_numbers تأخذ شريحتين نصيتين (string slices) كمعاملات وتعيد Result<i32, std::num::ParseIntError>. داخل الدالة، استخدم عامل التشغيل ? لتحويل كلا السلسلتين وإرجاع مجموعهما مغلفاً بـ Ok. استدعِ الدالة مع المدخلين وقم بمعالجة النتيجة باستخدام match.

المتطلبات:

  • قراءة المدخل الأول (الرقم الأول كسلسلة نصية) وإزالة المسافات البيضاء (trim)
  • قراءة المدخل الثاني (الرقم الثاني كسلسلة نصية) وإزالة المسافات البيضاء (trim)
  • إنشاء دالة add_numbers تأخذ معاملين من نوع &str وتعيد Result<i32, std::num::ParseIntError>
  • داخل الدالة، قم بتحويل السلسلة الأولى إلى i32 باستخدام عامل التشغيل ?
  • قم بتحويل السلسلة الثانية إلى i32 باستخدام عامل التشغيل ?
  • أعد Ok(sum) حيث sum هو ناتج جمع كلا الرقمين المحولين
  • استدعِ الدالة مع سلسلتي المدخلات
  • استخدم تعبير match لمعالجة الـ Result
  • في ذراع Ok(value)، اطبع: Sum: [value]
  • في ذراع Err(_)، اطبع: Parsing error

المدخلات:

  • السطر الأول: سلسلة نصية تمثل رقماً (مثلاً، 15)
  • السطر الثاني: سلسلة نصية تمثل رقماً آخر (مثلاً، 27)

المخرجات:

  • إذا كانت كلتا السلسلتين أرقاماً صالحة: Sum: [result]
  • إذا تعذر تحويل أي من السلسلتين: Parsing error

جرّب بنفسك

use std::io;

// TODO: أنشئ دالة add_numbers هنا
// يجب أن تأخذ معاملين من نوع &str وتعيد Result<i32, std::num::ParseIntError>


fn main() {
    // قراءة المدخل الأول
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let input1 = input1.trim();
    
    // قراءة المدخل الثاني
    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let input2 = input2.trim();
    
    // TODO: استدعِ add_numbers مع input1 و input2
    // TODO: استخدم match للتعامل مع Result
    // اطبع "Sum: [value]" في حالة Ok(value)
    // اطبع "Parsing error" في حالة Err(_)
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Logic & Flow