سكانف

scanf ، اختصارًا لـ scan formatted، هي دالة من مكتبة C القياسية تقرأ وتحلل النص من المدخلات القياسية .

تقبل الدالة مُعامل سلسلة تنسيق يُحدد تخطيط النص المُدخل . تقوم الدالة بتحليل النص المُدخل وتحميل القيم في متغيرات بناءً على نوع البيانات .

توجد وظائف مماثلة، بأسماء أخرى، قبل لغة C، كما هو الحال readfفي ALGOL 68 .

تُعد سلاسل تنسيق الإدخال مكملة لسلاسل تنسيق الإخراج (انظر printf )، والتي توفر إخراجًا منسقًا ( القوالب ).

تاريخ

أصبحت مكتبة الإدخال/الإخراج المحمولة لمايك ليسك ، بما في ذلك scanf، جزءًا رسميًا من نظام يونكس في الإصدار 7. [ 1 ]

لقراءة المدخلات، تستخدم لغة C++ عادةً دالة printf() std::cin، بينما تستخدم لغة Javajava.util.Scanner فئة printf() . تم تقديم نسخة مُحدثة من دالة printf() في لغة C++، استنادًا إلى مكتبة fmtlib [ 2 ] ، والتي أضافت (في C++20 ) و printf() و printf () في C++23 . مع ذلك، لم يتم تقديم نسخة مُحدثة مماثلة، على الرغم من اقتراح نسخة مُحدثة استنادًا إلى مكتبة scnlib [ 3 ] .std::format()std::print()std::println()::scanf()

الاستخدام

تقوم هذه scanfالدالة بقراءة المدخلات للأرقام وأنواع البيانات الأخرى من المدخلات القياسية .

يقرأ كود C التالي عددًا متغيرًا من الأعداد العشرية غير المنسقة من المدخلات القياسية ويطبع كل منها على سطر منفصل:

#include <stdio.h>int main ( void ) {عدد صحيح n ؛بينما ( scanf ( "%d" , & n )) {printf ( "%d \n " , n );}أرجع 0 ؛}

لإدخال البيانات:

456 123 789 456 12456 1 2378

الناتج هو:

456 123 789 456 12 456 1 2378

لطباعة كلمة:

#include <stdio.h>int main ( void ) {char word [ 20 ];إذا ( تم قراءة ( "%19s " , كلمة )) {puts ( word );}أرجع 0 ؛}

بغض النظر عن نوع البيانات التي يرغب المبرمج في أن يقرأها البرنامج، &nيجب أن تكون الوسائط (كما في المثال أعلاه) مؤشرات تشير إلى الذاكرة. وإلا، فلن تعمل الدالة بشكل صحيح لأنها ستحاول الكتابة فوق أجزاء خاطئة من الذاكرة، بدلاً من الإشارة إلى موقع الذاكرة الخاص بالمتغير الذي تحاول الحصول على مدخلاته.

في المثال الأخير، لم يُستخدم عامل عنوان ( &) للوسيط: لأن هو اسم مصفوفة من ، وبالتالي فهو (في جميع السياقات التي يُقيّم فيها إلى عنوان) يُعادل مؤشرًا إلى العنصر الأول من المصفوفة. بينما يُقيّم التعبير عدديًا إلى القيمة نفسها، إلا أنه من الناحية الدلالية، يحمل معنى مختلفًا تمامًا، إذ يُمثل عنوان المصفوفة بأكملها وليس عنصرًا منها. يجب مراعاة هذه الحقيقة عند إسناد المخرجات إلى السلاسل النصية.wordchar&wordscanf

بما scanfأن هذه اللغة مصممة للقراءة فقط من المدخلات القياسية، فإن العديد من لغات البرمجة ذات الواجهات ، مثل PHP ، لديها مشتقات مثل sscanfو fscanfولكن ليس scanfاللغة نفسها.

مواصفات سلسلة التنسيق

تتشابه عناصر التنسيق في هذه الدالة scanfإلى حد كبير مع تلك الموجودة في دالة printf printf، وهي الدالة العكسية لها. وكما هو الحال في printf، فإن امتداد POSIX n$مُعرّف. [ 4 ]

نادرًا ما تحتوي سلسلة التنسيق على ثوابت (أي أحرف ليست عناصر نائبة للتنسيق )، ويعود ذلك أساسًا إلى أن البرنامج عادةً لا يُصمم لقراءة البيانات المعروفة، مع scanfأنه يقبلها إذا تم تحديدها صراحةً. والاستثناء هو حرف أو أكثر من أحرف المسافة البيضاء ، حيث يتم تجاهل جميع أحرف المسافة البيضاء في المدخلات. [ 4 ]

فيما يلي بعض العناصر النائبة الأكثر استخدامًا:

  • %a : قم بمسح رقم ذي فاصلة عائمة في تدوينه الست عشري.
  • %d : قم بمسح عدد صحيح كرقم عشري ذي إشارة .
  • %i : يقوم هذا الأمر بمسح عدد صحيح كرقم مُوَقَّع. وهو مشابه للأمر السابق %d، لكنه يُفسِّر العدد على أنه سداسي عشري عند إضافة فاصلة عشرية قبله 0x، وثماني عند إضافة فاصلة عشرية قبله . على سبيل المثال، ستُقرأ 0السلسلة النصية 31 باستخدام الأمر السابق ، و25 باستخدام الأمر السابق . يشير العلم في الأمر السابق إلى التحويل إلى سداسي عشري والتحويل إلى ثماني .031%d%ih%hishorthhchar
  • %u : ابحث عن عدد عشري unsigned int(لاحظ أنه في معيار C99، تكون علامة السالب اختيارية، لذا إذا تمت قراءة علامة سالبة، فلن تحدث أخطاء وستكون النتيجة هي المتمم الثنائي لعدد سالب، والذي من المحتمل أن يكون قيمة كبيرة جدًا. انظر . strtoul()) وبالمثل، يبحث عن و .%huunsigned short%hhuunsigned char
  • %f : مسح عدد ذي فاصلة عائمة في تدوين عادي ( نقطة ثابتة ).
  • %g, %G : مسح عدد عشري إما بالصيغة العادية أو الأسية. %gيستخدم الأحرف الصغيرة ويستخدم %Gالأحرف الكبيرة.
  • %x, %X : قم بمسح عدد صحيح كرقم سداسي عشري غير موقع .
  • %o : قم بمسح عدد صحيح كرقم ثماني .
  • %s : مسح سلسلة نصية . يتوقف المسح عند وجود مسافة بيضاء . يتم تخزين حرف فارغ في نهاية السلسلة، مما يعني أن المخزن المؤقت المقدم يجب أن يكون أطول بحرف واحد على الأقل من طول الإدخال المحدد.
  • %c : امسح حرفًا (char). لا تتم إضافة أي حرف فارغ .
  • المسافات البيضاء : أي مسافة بيضاء تؤدي إلى فحص وجود صفر أو أكثر من المسافات البيضاء . لا يشترط تطابق عدد ونوع المسافات البيضاء في أي اتجاه.
  • %lf : امسح ضوئياً كرقم عشري مزدوج . تنسيق "Float" مع مُحدد "long".
  • %Lf : امسح كرقم عشري مزدوج طويل . استخدم "Float" لتنسيق مُحدد "long long".
  • %n لا يُتوقع أي شيء. يتم تخزين عدد الأحرف المُستهلكة حتى الآن من المُدخلات عبر المؤشر التالي، والذي يجب أن يكون مؤشرًا إلى عدد صحيح. هذا ليس تحويلًا ولا يزيد العدد الذي تُرجعه الدالة.

lيمكن استخدام ما سبق مع مُعدِّلات رقمية ، بالإضافة إلى Lمُعدِّلات "طويل" و"طويل جدًا" التي تُشير إلى "طويل" و"طويل جدًا" بين رمز النسبة المئوية والحرف. كما يُمكن وضع قيم رقمية بين رمز النسبة المئوية والأحرف، تسبق المُعدِّلات longإن وُجدت، لتحديد عدد الأحرف المراد مسحها ضوئيًا. تشير علامة النجمة الاختيارية ( **) بعد رمز النسبة المئوية مباشرةً إلى أن البيانات المقروءة بواسطة مُحدِّد التنسيق هذا لن تُخزَّن في متغير. لا ينبغي تضمين أي وسيط خلف سلسلة التنسيق لهذا المتغير المُهمل.

لا يوجد المُعدِّل ffفي دالة printf في دالة scanf، مما يُسبب اختلافات بين أنماط الإدخال والإخراج. llالمُعدِّلان hhغير موجودين في معيار C90، ولكنهما موجودان في معيار C99. [ 5 ]

مثال على سلسلة التنسيق هو

"%7d%s %c%lf"

يقوم تنسيق السلسلة أعلاه بمسح الأحرف السبعة الأولى كعدد صحيح عشري، ثم يقرأ الباقي كسلسلة نصية حتى يعثر على مسافة أو سطر جديد أو علامة جدولة، ثم يستهلك المسافات البيضاء حتى يعثر على أول حرف غير مسافة بيضاء، ثم يستهلك ذلك الحرف، وأخيرًا يمسح الأحرف المتبقية كعدد عشري مزدوج . لذلك، يجب على البرنامج القوي التحقق من scanfنجاح الاستدعاء واتخاذ الإجراء المناسب. إذا لم يكن الإدخال بالتنسيق الصحيح، فستظل البيانات الخاطئة موجودة في دفق الإدخال ويجب تجاهلها قبل قراءة إدخال جديد. هناك طريقة بديلة، تتجنب ذلك، وهي استخدام fgetsثم فحص السلسلة المقروءة. يمكن تنفيذ الخطوة الأخيرة بواسطة sscanf، على سبيل المثال.

في حالة الأحرف العشرية العديدة a و e و f و g ، تختار العديد من التطبيقات دمج معظمها في محلل واحد. يقوم Microsoft MSVCRT بذلك مع e و f و g ، [ 6 ] بينما يقوم glibc بذلك مع الأحرف الأربعة جميعها. [ 4 ]

يتضمن معيار ISO C99 inttypes.hملف رأس يحتوي على عدد من وحدات الماكرو لاستخدامها في scanfالبرمجة المستقلة عن النظام الأساسي. يجب وضع هذه الوحدات خارج علامات الاقتباس المزدوجة، على سبيل المثال:scanf("%"SCNd64"\n",&t);

تتضمن أمثلة وحدات الماكرو ما يلي:

الماكرووصف
SCNd32عادةً ما يعادل I32d ( Win32/Win64 ) أو d
SCNd64عادةً ما يكون مكافئًا لـ I64d ( Win32/Win64 ) أو lld ( منصات 32 بت ) أو ld ( منصات 64 بت ).
SCNi32عادةً ما يعادل I32i ( Win32/Win64 ) أو i
SCNi64عادةً ما يكون مكافئًا لـ I64i ( Win32/Win64 ) أو lli ( منصات 32 بت ) أو li ( منصات 64 بت ).
SCNu32عادةً ما يعادل I32u ( Win32/Win64 ) أو u
SCNu64عادةً ما يكون مكافئًا لـ I64u ( Win32/Win64 ) أو llu ( منصات 32 بت ) أو lu ( منصات 64 بت ).
SCNx32عادةً ما يعادل I32x ( Win32/Win64 ) أو x
SCNx64عادةً ما يكون مكافئًا لـ I64x ( Win32/Win64 ) أو llx ( منصات 32 بت ) أو lx ( منصات 64 بت ).

نقاط الضعف

scanfيُعدّ هذا النظام عرضةً لهجمات سلاسل التنسيق . لذا، يجب توخي الحذر الشديد لضمان احتواء سلسلة التنسيق على قيود لأحجام السلاسل والمصفوفات. في معظم الحالات، يكون حجم سلسلة الإدخال من المستخدم عشوائيًا ولا يمكن تحديده قبل scanfتنفيذ الدالة. هذا يعني أن %sالعناصر النائبة التي لا تحدد طولها غير آمنة بطبيعتها وقابلة للاستغلال في ثغرات تجاوز سعة المخزن المؤقت . تتمثل مشكلة أخرى محتملة في السماح بسلاسل تنسيق ديناميكية، مثل سلاسل التنسيق المخزنة في ملفات التكوين أو غيرها من الملفات التي يتحكم بها المستخدم. في هذه الحالة، لا يمكن تحديد الطول المسموح به لأحجام السلاسل المدخلة إلا إذا تم فحص سلسلة التنسيق مسبقًا وفرض قيود عليها. يرتبط بهذا وجود عناصر نائبة إضافية أو غير متطابقة للتنسيق لا تتوافق مع قائمة الوسائط المتغيرة الفعلية . قد يتم استخراج هذه العناصر النائبة جزئيًا من المكدس أو قد تحتوي على مؤشرات غير مرغوب فيها أو حتى غير آمنة، وذلك اعتمادًا على التنفيذ المحدد للوسائط المتغيرة .

انظر أيضاً

مراجع

  1. ماكيلروي، دكتور في الطب (1987). قارئ أبحاث يونكس: مقتطفات مشروحة من دليل المبرمج، 1971-1986 (ملف PDF) (تقرير فني). مختبرات بيل. 139.
  2. فيكتور زفيروفيتش (25 مارس 2022). "المخرجات المنسقة" . open-std.org . WG 21.
  3. ^ إلياس كوسونين، فيكتور زفيروفيتش (15 أكتوبر 2024). "تحليل النص" . open-std.org . مجموعة العمل 21.
  4. 1 2 3دليل مبرمج لينكس – وظائف المكتبة من Manned.orgscanf(3)  
  5. معيار C99، §7.19.6.2 "دالة fscanf" alinea 11.
  6. "scanf Type Field Characters" . docs.microsoft.com . 26 أكتوبر 2022.