كتابة دوال شبيهة بـprintf
المعاملات المتغيرة
كتابة دوال شبيهة بـprintf درس مجاني في C Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.
الدوال التي تستقبل سلسلة تنسيق
أقوى استخدام للوسائط المتغيرة هو إنشاء دوال بأسلوب printf تفسّر سلسلة تنسيق.
تحدد سلسلة التنسيق عدد الوسائط التالية ونوع كل منها.
#include <stdio.h>
#include <stdarg.h>
void myprint(const char *fmt, ...) {
printf("format was: %s\n", fmt);
}
int main(void) {
myprint("%d items\n", 5);
return 0;
}اجتياز سلسلة التنسيق
افحص سلسلة التنسيق حرفًا حرفًا. عندما ترى %، يكون الحرف التالي محدد تحويل يحدد نوع القيمة التي يجب قراءتها.
تتم طباعة كل ما عدا ذلك حرفيًا.
#include <stdio.h>
#include <stdarg.h>
void scan(const char *fmt) {
for (const char *p = fmt; *p; p++) {
if (*p == '%') printf("[spec:%c]", *(p+1));
else putchar(*p);
}
putchar('\n');
}
int main(void) {
scan("x=%d y=%s");
return 0;
}قراءة النوع المطابق
عندما يكون المحدد %d، اقرأ قيمة من النوع int. وبالنسبة إلى %s، اقرأ قيمة من النوع char *. يجب أن تتطابق سلسلة التنسيق تمامًا مع الوسائط الفعلية.
#include <stdio.h>
#include <stdarg.h>
void mini(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p == '%' && *(p+1) == 'd') {
printf("%d", va_arg(args, int));
p++;
} else putchar(*p);
}
va_end(args);
}
int main(void) {
mini("count=%d\n", 42);
return 0;
}معالجة محددات متعددة
وسّع الفاحص ليتعامل مع عدة تحويلات. أضف حالات لـ %d و%s و%c، واقرأ النوع الصحيح في كل مرة.
#include <stdio.h>
#include <stdarg.h>
void fmt_print(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p != '%') { putchar(*p); continue; }
p++;
if (*p == 'd') printf("%d", va_arg(args, int));
else if (*p == 's') printf("%s", va_arg(args, char *));
else if (*p == 'c') putchar(va_arg(args, int));
}
va_end(args);
}
int main(void) {
fmt_print("%s is %d\n", "age", 30);
return 0;
}هروب علامة النسبة المئوية
تتعامل دوال التنسيق الحقيقية مع %% باعتبارها علامة نسبة مئوية حرفية. أضف حالة تتيح للمستخدمين طباعة % فعلية.
#include <stdio.h>
#include <stdarg.h>
void fp(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p == '%') {
p++;
if (*p == '%') putchar('%');
else if (*p == 'd') printf("%d", va_arg(args, int));
} else putchar(*p);
}
va_end(args);
}
int main(void) {
fp("%d%% done\n", 75);
return 0;
}تمرير الوسائط إلى vprintf
غالبًا لا تريد إعادة تنفيذ التنسيق. توفر المكتبة القياسية الدالة vprintf، التي تستقبل va_list مباشرةً.
تكتفي الدالة المغلِّفة بتمرير وسائطها.
#include <stdio.h>
#include <stdarg.h>
void logline(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(void) {
logline("value = %d, name = %s\n", 7, "box");
return 0;
}إضافة بادئة
يسهّل أسلوب vprintf إضافة سلوك حول التنسيق القياسي، مثل طباعة وسم قبل كل رسالة.
#include <stdio.h>
#include <stdarg.h>
void info(const char *fmt, ...) {
printf("[INFO] ");
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(void) {
info("server started on port %d\n", 8080);
return 0;
}الكتابة في مخزن باستخدام vsnprintf
لتنسيق النص داخل سلسلة بدلًا من طباعته، استخدم vsnprintf(buf, size, fmt, args).
تلتزم الدالة بالحد size، ما يمنع تجاوز السعة، وتنهي السلسلة دائمًا بمحرف الصفر.
#include <stdio.h>
#include <stdarg.h>
void format_into(char *buf, size_t n, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vsnprintf(buf, n, fmt, args);
va_end(args);
}
int main(void) {
char out[64];
format_into(out, sizeof(out), "id-%d", 123);
printf("%s\n", out);
return 0;
}إرجاع طول
تعيد vsnprintf عدد المحارف التي كان سيجري كتابتها. يمكنك استخدام ذلك لاكتشاف الاقتطاع أو لتحديد حجم المخزن.
#include <stdio.h>
#include <stdarg.h>
int build(char *buf, size_t n, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int len = vsnprintf(buf, n, fmt, args);
va_end(args);
return len;
}
int main(void) {
char b[10];
int needed = build(b, sizeof(b), "%d-%d", 11, 22);
printf("%s (needed %d)\n", b, needed);
return 0;
}اختيار الأسلوب
هناك استراتيجيتان: تحليل سلسلة التنسيق بنفسك للتحكم الكامل، أو تمريرها إلى vprintf/vsnprintf لضمان الصحة وتقليل الشيفرة.
في معظم الشيفرات الفعلية، يكون التمرير الخيار الأكثر أمانًا وبساطة.
#include <stdio.h>
#include <stdarg.h>
void say(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
int main(void) {
say("%s = %.1f\n", "pi", 3.14);
return 0;
}عدم التطابق سلوك غير محدد
إذا وعدت سلسلة التنسيق بنوع لا يتطابق مع الوسيط الفعلي، فسيكون السلوك غير محدد.
قد يتسبب printf("%d", "text") في انهيار البرنامج. احرص دائمًا على توافق سلسلة التنسيق مع الوسائط.
#include <stdio.h>
int main(void) {
int n = 5;
printf("%d\n", n);
return 0;
}اختبار سريع
اختبر مدى فهمك للدوال المغلِّفة بأسلوب printf.
مراجعة
لقد تعلمت إنشاء دوال شبيهة بـ printf:
- استقبل سلسلة تنسيق باعتبارها الوسيط المسمّى، ثم
.... - إما أن تحلل محددات
%بنفسك وتقرأ الأنواع المطابقة، أو - تمرر
va_listإلى vprintf / vsnprintf للحصول على تنسيق آمن وصحيح. - حافظ على توافق سلسلة التنسيق مع أنواع الوسائط لتجنب السلوك غير المحدد.
الأسئلة الشائعة
هل درس «كتابة دوال شبيهة بـprintf» مجاني؟
نعم — نص درس «كتابة دوال شبيهة بـprintf» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.
ماذا ستتعلم في «كتابة دوال شبيهة بـprintf»؟
المعاملات المتغيرة تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟
لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «كتابة دوال شبيهة بـprintf»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟
نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- وحدات الماكرو stdarg
- كتابة دوال شبيهة بـprintf
- مخاوف سلامة الأنواع
- أمثلة عملية