تخطَّ إلى المحتوى

🇨 شرح لغة C

تحويل النصوص والأرقام

الدرس 27 من 29· ⏱ 2 دقائق قراءة

نص إلى رقم: atoi (السريعة لكن غير الآمنة)

#include <stdlib.h>

int n = atoi("42");     // 42
int m = atoi("abc");    // 0 — بدون أي إشارة لفشل التحويل!

atoi لا تملك طريقة لتمييز فشل التحويل عن نص "0" فعلي، وسلوكها غير معرّف لو تجاوز الرقم مدى int. مناسبة فقط لو أنت متأكد أن النص رقم صحيح دائمًا.

نص إلى رقم: strtol (الآمنة)

#include <stdlib.h>
#include <errno.h>

char *end;
errno = 0;
long n = strtol("42abc", &end, 10);   // n = 42, end يشير إلى "abc"

if (end == "42abc")        /* لا تفعل هذا — قارن end بالمؤشر الأصلي */ ;
  • end بعد الاستدعاء يشير لأوّل حرف لم يُحوَّل — لو ساوى بداية النص فهذا يعني فشل التحويل بالكامل.
  • المعامل الثالث هو الأساس (base): 10 للعشري، 16 للسادس عشري، 0 ليكتشفه تلقائيًا من بادئة النص (0x سادس عشري، 0 ثماني).
  • عند تجاوز المدى تُرجع LONG_MAX/LONG_MIN وتضبط errno = ERANGE — لهذا نصفّر errno قبل الاستدعاء ونتحقّق منه بعده.
char *end;
errno = 0;
long n = strtol(text, &end, 10);
if (end == text) {
    // ما تحوّل ولا رقم
} else if (errno == ERANGE) {
    // القيمة أكبر/أصغر من مدى long
}

رقم إلى نص: sprintf و snprintf

char buf[20];
sprintf(buf, "%d-%d", 5, 3);            // خطر: بدون حد لحجم buf

char safe[20];
int written = snprintf(safe, sizeof(safe), "%d-%d", 5, 3);

sprintf تكتب بدون أي فحص لحجم buf — لو النتيجة أطول من المصفوفة يحدث تجاوز حدود (buffer overflow). snprintf تأخذ حجم المخزن كمعامل ثانٍ وتتوقّف عنده، وترجع عدد الحروف التي كانت ستُكتب لو كان المخزن كافيًا — قارنه بحجم المخزن لمعرفة إن حدث اقتطاع.

💡 استخدم snprintf بدل sprintf دائمًا، تمامًا متل تفضيل fgets على gets.

أخطاء شائعة

  • الاعتماد على atoi مع مدخلات المستخدم دون تحقّق.
  • استخدام sprintf بمخزن حجمه غير مضمون كفايته.
  • تجاهل قيمة errno بعد strtol عند التحقق من تجاوز المدى.

🎯 التالي: مؤشّرات الدوال.

شرح تحويل النصوص والأرقام — لغة C بالعربي
تحويل النصوص والأرقاملغة C بالعربي · The Code Fix

📚 لمزيد من التعمّق في لغة C، راجِع مرجع لغة C الرسمي.

هل كان هذا الدرس مفيدًا؟