كيفية التحقق من صحة الإدخال باستخدام scanf

StackOverflow https://stackoverflow.com/questions/456303

  •  19-08-2019
  •  | 
  •  

سؤال

وكيف يمكنني التحقق من صحة إدخال المستخدم باستخدام scanf. الآن لدي شيئا من هذا القبيل، ولكن لا يعمل.

ملحوظة: لدي atoi فقط للتحقق من أن التحقق من صحة scanf يعمل

.
scanf("%[0987654321.-]s",buf);

i = atoi(buf);

if(i)
    index = i;
هل كانت مفيدة؟

المحلول

وعن طريق scanf() عادة ما يكون فكرة سيئة لإدخال المستخدم منذ فشل يترك مؤشر FILE في موقف غير معروف. ذلك لأن scanf لتقف على "مسح تنسيق" وهناك ما هو أكثر قليلا <م> غير منسق من إدخال المستخدم.

وأود أن أقترح استخدام fgets() للحصول على خط في، تليها sscanf() على السلسلة للتحقق في الواقع ومعالجته.

وهذا يسمح لك أيضا للتحقق من سلسلة لتلك الأحرف التي تريدها (إما عن طريق حلقة أو مع تعبير عادي)، وهو أمر لا تناسب الأسرة scanf من الوظائف حقا.

وعلى سبيل المثال، وذلك باستخدام scanf() مع "%d" أو "%f" سوف تتوقف عند أول حرف غير رقم وهكذا لن قبض زائدة أخطاء مثل "127hello"، والتي سوف أعطيكم 127. واستخدامه مع %s غير يحدها- هو مجرد <م> التسول لتجاوز سعة المخزن المؤقت.

إذا كنت حقا يجب استخدام تنسيق [] محدد (في scanf <م> أو sscanf)، وأنا لا أعتقد أنه من المفترض أن تعقبها s.

و، عن حل مساهمة قوية باستخدام هذه النصيحة، انظر> وأ href = "https://stackoverflow.com/questions/4023895/how-to-read-string-entered-by-user-in-c/ 4023921 # 4023921 "> هنا . مرة واحدة لديك خط الإدخال كسلسلة، يمكنك sscanf لقلوبكم المحتوى.

نصائح أخرى

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

bool is_double(char const* s) {
    int n;
    double d;
    return sscanf(s, "%lf %n", &d, &n) == 1 && !s[n];
}

وsscanf سيعود البنود تحويلها (بدون '٪ ن'). سيتم تعيين n لكمية من إدخال الأحرف معالجتها. إذا تم معالجة كافة المدخلات، ق [ن] سيعود تنتهي 0 الحرف. المسافة بين المتخصصين شكل حسابين لاختياري زائدة بيضاء.

والاختبارات التالية لعدد صحيح، نفس التقنيات المستخدمة:

bool is_int(char const* s) {
    int n;
    int i;
    return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}

وكان هناك سؤال في ذلك هنا ، والتي تشمل أيضا أكثر C ++ "طرق العش للقيام بذلك، مثل استخدام تيارات سلسلة وظائف من دفعة، مثل lexical_cast وهلم جرا. وينبغي عموما أن يفضل على وظائف مثل scanf، لأنه من السهل جدا أن ننسى لتمرير بعض '٪' إلى scanf، أو بعض العناوين. سوف scanf لا تعترف بذلك، ولكن بدلا من ذلك سوف تفعل أشياء التعسفي، في حين lexical_cast، على سبيل المثال، سوف رمي استثناء إذا كان أي شيء غير صحيح.

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

char *string;
char *endptr;
long result;

scanf("%as", string);
errno = 0;
result = strtol(string, &endptr, 10);
if (ERANGE == errno)
    printf("Input number doesn't fit into long\n");
else if (*endptr)
    printf("%s is not a valid long number - it contains invalid char %c\n",
        string, *endptr);
else
    printf("Got %ld\n", result);

في هذا scanf() المتكررة وأوعز بتخصيص string كبيرة بما فيه الكفاية تلقائيا باستخدام تنسيق التعديل "أ" (هذا هو تمديد جنو). إذا لم تكن على GNU، وتخصيص string يدويا والحد من حجم الحد الأقصى في شكل scanf().

وهذا الأسلوب يتيح أفضل معالجة الأخطاء.

ما الذي حددته في الوسيطة الأولى إلى scanf و<م> محددات تحويل . سوف scanf محاولة لتحويل المدخلات إلى تنسيق ولكن في بعض الأحيان كنت قد يفاجأ ما سوف تطابق ضد:)

والاختيار الأول يجب عليك فعله هو على قيمة الإرجاع من scanf (سوف تعطيك عدد من المدخلات مطابقة). إذا كنت لا تحصل على الرقم الذي تتوقع ثم أنت تعلم أن هناك شيئا خطأ مع المدخلات. في الحالة الخاصة بك ينبغي أن يكون 1.

if( scanf("%[0987654321.-]s", buf) == 1 )
{
      if( sanit_check( buf ) ) 
      {
      /* good input */
      }
      else
      {
      /* invalid input */
      }
}
else 
{
/* invalid input */
}

وأبعد من ذلك سوف تحتاج إلى القيام كنت تملك الشيكات التعقل على التحويل التي طلبتم scanf القيام به.

إذا كنت تحاول قراءة عدد فقط، استخدم:

int i;
scanf( "%d", &i );

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

و"BUF" لابد أن يكون المؤشر. يبدو أنك تمر من حيث القيمة.

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