نص إلى رقم: 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عند التحقق من تجاوز المدى.
🎯 التالي: مؤشّرات الدوال.