سؤال

لقد كان لدي الكثير من المشاكل في محاولة لمعرفة كيفية استخدام scanf().يبدو أن تعمل بشكل جيد مع الاعداد الصحيحه ، ويجري إلى حد ما على التوالي إلى الأمام scanf("%d", &i).

أين أنا على التوالي في المسائل باستخدام scanf() في الحلقات محاولة قراءة المدخلات.على سبيل المثال:

do {
  printf("counter: %d: ", counter);
  scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
  1. عندما كنت أدخل في صحيحة منظم المدخلات مثل c P101, يبدو أن الحلقة مرة أخرى قبل دفع لي.يبدو أن هذا يحدث حتى مع واحد:

    scanf("%c", &c) 
    

    في حين حلقة.انها سوف تفعل الحلقة مرتين قبل دفع لي مرة أخرى.ما يجعل الحلقة مرتين و كيف يمكنني التوقف عن ذلك ؟

  2. عندما كنت أدخل في أقل قدر من المدخلات التي برمجيا لن يكون آخر حرف أو رقم مثل q, الضغط على المفتاح enter يبدو أن موجه لي أن أدخل أكثر.كيف يمكنني الحصول على scanf() لمعالجة كل واحد مزدوج الشخصية المدخلات ؟

هل كانت مفيدة؟

المحلول

عندما تقوم بإدخال "c P101"البرنامج فعلا يحصل "c P101\n".معظم التحويل محددات تخطي الرائدة فاصل أسطر بما في ذلك ولكن %c لا.في المرة الأولى في كل شيء حتى "\n"قراءة في المرة الثانية حول " " قراءة في command, "c"قراءة في prefix, ، "P"هو اليسار الذي هو ليس رقم التحويل فشل "P101\n"تبقى على تيار.في المرة القادمة "P"يتم تخزينها في الأمر" ، 1"يتم تخزينها في بادئة ، 1 (من المتبقية "01") يتم تخزينها في الإدخال مع "\n"لا يزال على تيار في المرة القادمة.يمكنك إصلاح هذه المشكلة عن طريق وضع مسافة في بداية format string والتي سوف تخطي أي الرائدة بيضاء بما في ذلك أسطر.

وهي مشابهة الشيء يحدث عن الحالة الثانية ، عندما تقوم بإدخال "q", "q\n"يتم إدخالها في مجرى المرة الأولى حول "q"قراءة في المرة الثانية "\n"للقراءة فقط على الدعوة الثالثة الثانية "q"قراءة ، يمكنك تجنب المشكلة مرة أخرى عن طريق إضافة حرف مسافة في بداية سلسلة التنسيق.

أفضل طريقة للقيام بذلك سيكون لاستخدام شيء مثل fgets() إلى عملية خط في وقت واحد ومن ثم استخدام sscanf() للقيام تحليل.

نصائح أخرى

انها حقا مكسورة!لم أكن أعرف ذلك

#include <stdio.h>

int main(void)
{
    int counter = 1;
    char command, prefix;
    int input;

    do 
    {
        printf("counter: %d: ", counter);
        scanf("%c %c%d", &command, &prefix, &input);
        printf("---%c %c%d---\n", command, prefix, input);
        counter++;
    } while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
 c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
 g3---

الإخراج يبدو لتناسب مع روبرت الجواب.

مرة واحدة لديك السلسلة التي تحتوي على الخط.أي"ج P101" ، يمكنك استخدام تحليل قدرات sscanf.

انظر:http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html

السؤال 1 ، وأظن أن لديك مشكلة مع الخاص بك printf(), إذ لا يوجد أي إنهاء " ".

السلوك الافتراضي printf المخزن المؤقت الإخراج حتى خط كامل.هذا إلا إذا كنت صراحة تغيير التخزين المؤقت على stdout.

السؤال 2 ، لقد ضرب واحدة من أكبر المشاكل مع scanf().إلا إذا المدخلات الخاصة بك يطابق تماما مسح السلسلة التي قمت بتحديدها ، النتائج ستكون شيئا مثل ما كنت تتوقع.

إذا كنت قد حصلت على خيار سيكون لديك نتائج أفضل (أقل القضايا الأمنية) من خلال تجاهل scanf() والقيام الخاصة بك تحليل.على سبيل المثال, استخدام fgets() لقراءة كامل الخط إلى سلسلة ، ومن ثم معالجة الحقول الفردية السلسلة — ربما حتى باستخدام sscanf().

ربما باستخدام حلقة في حين لا تفعل...في حين أن الحلقة سوف تساعد.هذه الطريقة الشرط هو اختبار قبل تنفيذ التعليمات البرمجية.جرب ما يلي مقتطف الشفرة:

 while(command != 'q')
    {
        //statements
    }

أيضا, إذا كنت تعرف طول السلسلة قبل الوقت ، '' الحلقات يمكن أن تكون أسهل بكثير للعمل مع من 'حين' الحلقات.هناك أيضا بعض اصعب الطرق لتحديد حيوي طول كذلك.

النهائي خرف: scanf() لا "مص". لا يفعل ما يفعل وهذا هو كل شيء. fgets() خطير جدا (على الرغم من ملاءمة أي مخاطر التطبيقات) ، لأنه لا أصلا تفعل أي التحقق من المدخلات.هو المعروف نقطة استغلال ، على وجه التحديد الهجمات تجاوز سعة المخزن المؤقت ، الكتابة الفضاء في السجلات المخصصة لذلك المتغير.لذلك إذا اخترت استخدام ، قضاء بعض الوقت في وضع بعض خالص خطأ فحص/تصحيح.

آمل أن يساعد هذا شخص ما في المستقبل منذ أفترض أنك قد حصلت عليه التعامل معها من قبل الآن!;)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top