الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

التحقق المتقدم من صحة الإدخال !

بدأه khaled_prg في 2 أكتوبر 2010 · 7 رد · 1,112 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

قمت بكتابة الكود التالي الذي يقوم بجمع عددين صحيحين و يتحقق من صحة الإدخال قبل أن يقوم بعملية الجمع, انظر الكود :

#include<iostream>
using namespace std;
int main()
{
    int x,y;

    cout<<"x=";
    cin>>x;
    while(cin.fail()) 
    {
       cin.clear();
       cin.sync();
       cout<<"Une erreur s'est produite ! \a"<<endl;
       cout<<"Valeur impossible !, Veuillez entrer une valeur entier  : "<<endl;
       cout<<"x=";
       cin>>x;
    }
    cin.sync();
    cout<<"y=";
    cin>>y;
    while(cin.fail()) 
    {
       cin.clear();
       cin.sync();
       cout<<"Une erreur s'est produite ! \a"<<endl;
       cout<<"Valeur impossible !, Veuillez entrer une valeur entier  : "<<endl;
       cout<<"y=";
       cin>>y;
    }

    cout<<x<<" + "<<y<<" = "<<x+y<<endl;

    system("pause");
    return 0;
}

المشكلة التي أعاني منها هي :

إذا طلبنا من المستخدم إدخال قيمة لـ x و أدخل المستخدم مجموعة من الحروف و الرموز بشرط أن تبدأ برقم مثل

5GHµ£§

فإن المترجم يعتبر أن قيمة x هي 5 !!!

سؤالي هو :

كيف يمكننا أن نتغلب على هذه المشكلة بحيث يتم رفض كل عبارة تحتوي على رمز أو حرف و تبدأ برقم.

تحياتي.

#2

فى هذه الحاله ستستخدم الداله cin.getline للحصول على قيمة السطر بأكمله و بعد ستقوم بالتحقق من قيمة السطر فإن كانت تحتوى على رمز بخلاف رموز الأرقام فالنص مخالف، أنظر الكود التالي:

#include <iostream>
using namespace std;

bool isNumber(const char* str)
{
	char *pMove = const_cast<char*>(str);

	while(*pMove)
		if (*pMove < 0x30 || *pMove > 0x39)
			return false;
		else
			pMove++;

	return true;
}


int main()
{
	char cbuf[20] = {0};

	cin.getline(cbuf, 20);

	int num = 0;

	if (isNumber(cbuf))
		num = atoi(cbuf);
}

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 2 أكتوبر 2010 في 21:39

2

مدونتي: C++ Tips and Tricks

#3

اخى تعديل أخر للكود

#include <iostream>
#include <limits>
using namespace std;
int main()
{
    int x,y;
    
    cout<<"x=";
    cin>>x;
    cin.ignore(numeric_limits<int>::max(), '\n');
    if(!cin || cin.gcount() != 1) 
    {
       cin.clear();
       cin.sync();
       cout<<"Une erreur s'est produite ! \a"<<endl;
       cout<<"Valeur impossible !, Veuillez entrer une valeur entier  : "<<endl;
       cout<<"x=";
       cin>>x;
    }
    cin.sync();
    cout<<"y=";
    cin>>y;
    cin.ignore(numeric_limits<int>::max(), '\n');
    if(!cin || cin.gcount() != 1) 
    {
       cin.clear();
       cin.sync();
       cout<<"Une erreur s'est produite ! \a"<<endl;
       cout<<"Valeur impossible !, Veuillez entrer une valeur entier  : "<<endl;
       cout<<"y=";
       cin>>y;
    }
    
    cout<<x<<" + "<<y<<" = "<<x+y<<endl;
    
    system("pause");
    return 0;
}
−1

 وممّا زادنـــي شرفــاً وتيهــاً   **  وكدت بأخمصي أطأ الثريّا

دخولي تحت قولك يا عبادي  **   وأن صيّرت أحمد لي نبيّـاً

#4

السلام عليكم

في البداية أشكر كلا من محمد علاء الدين و عمرو الصعيدي لما بذلا من جهد من أجل مساعدتي و أسأل الله سبحانه و تعالى أن يتقبل منهم صالح الأعمال و الأقوال و الأحوال و أن يجعل هذا العمل في ميزان حسناتهم, إنه ولي ذلك و القادر عليه.

بالنسبة لأخي الفاضل محمد علاء الدين :

قمتُ بتجربة الكود الذي كتبتَه و قد أدى المطلوب بنسبة 100%, ولكن عندي بعض الأسئلة حول هذا الكود.

1 -ما معنى هذا السطر و ما الهدف منه !؟

char *pMove = const_cast<char*>(str);

2- لم أفهم شرط حلقة التكرار :

while(*pMove)

هل لأن لمؤشر إذا كان يشير للخانة الأخيرة من المصفوفة ستكون قيمته صفر !؟

3-ألا يجب أن يكون البارامتر الثاني هو 19 بدل 20 :

cin.getline(cbuf, 20);

لأن الخانة الأخيرة سيكون فيها الرمز \0 وبالتالي نحن نملك 19 خانة فقط !

----------------------

بالنسبة لأخي الكريم عمرو الصعيدي :

قمتُ بتجربة الكود الذي كتبتَه ولكنه لم يؤدي المطلوب, إذا كانت القيمة المُدخلة لـ x خاطئة لمرتين متتاليتين فإن البرنامج يُعطي نتائج خاطئة, نفس الشيء بالنسبة لـ y !

تحياتي.

#5
اقتباس
1 -ما معنى هذا السطر و ما الهدف منه !؟

حيث أن str هى مؤشر لثابت نصي لذا لا يمكن تغيير قيمة str (حيث من الممكن ان يكون str يشير لقيمة literal) و بالتالى اقوم بإستخدام const cast للحصول على قيمة المؤشر داخل متغير pMove حتى استطيع تغيير قيمة ذلك المؤشر بالزياده لاحقا.

اقتباس
2- لم أفهم شرط حلقة التكرار :

معنى هذا الشرط انه يتم تنفيذ الكود طالما أن *pMove لا يساوى الصفر و ذلك لأن الصفر فى هذا المكان يعنى false اى تسبب فى انتهاء الحلقه بالإضافه ان الصفر يعنى انتهاء النص.

اقتباس
3-ألا يجب أن يكون البارامتر الثاني هو 19 بدل 20 :

حيث أن الرقم المدخل هو 20 لذا إن أمكن سيتم قراءة 19 حرف بحد أقصى من الداله الـ stream و سيتم وضعها داخل المصفوفه يلى ذلك إضافة الـ null terminator.

و الله ولي التوفيق

مدونتي: C++ Tips and Tricks

#6
اقتباس
حيث أن str هى مؤشر لثابت نصي لذا لا يمكن تغيير قيمة str (حيث من الممكن ان يكون str يشير لقيمة literal) و بالتالى اقوم بإستخدام const cast للحصول على قيمة المؤشر داخل متغير pMove حتى استطيع تغيير قيمة ذلك المؤشر بالزياده لاحقا.

أرجوا منك توضيح الأجزاء ذات اللون الأحمر مع شكري لك مقدما :)

ملاحظة : لا أعرف ما هو const cast ! :blush:

__________________________________

تعديل (أنتظر إجابتك على السؤال الذي بالأعلى ولكن سأضيف بعض التعليقات على كلامك حسب فهمي و أريدك أن تصحح لي هذه التعليقات) :

السبب وراء استخدامك لـ const cast هو أن str عبارة عن سلسلة حرفية ثابتة و لا يمكن لأي مؤشر أن يشير إليها !, لأن المؤشر إذا كان يشير لهذه السلسة فهذا معناه انه يمكننا تغيير "قيم خاناتها" أو "حروفها" اعتمادا على تحريك المؤشر و تغيير قيمته في كل مرة !, هل هذا التفسير صحيح !؟

اقتباس
معنى هذا الشرط انه يتم تنفيذ الكود طالما أن *pMove لا يساوى الصفر و ذلك لأن الصفر فى هذا المكان يعنى false اى تسبب فى انتهاء الحلقه بالإضافه ان الصفر يعنى انتهاء النص.

هل أفهم من كلامك أن :

الخانة الأخيرة من السلسلة الحرفية يكون فيها الرمز \0 و إذا كان المؤشر عند هذه الخانة فإن قيمته ستكون الكود آسكي المقابل للرمز السابق و تساوي 0, هل هذا صحيح !؟

ألا يمكننا استخدام سلسلة حرفية غير ثابتة مما يمكننا من إسنادها لمؤشر حرفي بشكل طبيعي بدل أن نستخدم سلسلة حرفية ثابتة !؟, انظر الكود :

bool isNumber(char* str)
{
        char *pMove = str;

        while(*pMove)
                if (*pMove < 0x30 || *pMove > 0x39)
                        return false;
                else
                        pMove++;

        return true;
}

دمتَ فخرا للمنتدى :wub:

تم تعديل هذه المشاركة بواسطة khaled_prg في 5 أكتوبر 2010 في 15:28

مواضيع مشابهة