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

مشكلة .. شيبت رأسي !

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

السلام عليكم ورحمة الله و بركاته

لدي تمرين .. و أقسم بالله العظيم أنه ليس تمرين منزلي:

اكتب ثلاث دوال تكافئ الدوال التالي:

الدالة الأولى تكافئ strlen

الدالة الثانية تكافئ strcpy

الدالة الثالثة (شيبت رأسي !!!) تكافئ srtcmp

1-استطعت كتابة دالة تكافئ الدالة الأولى:

void str_len(char strg[])
{
int i=0;
while(strg!='\0')
i++;
cout<<"dim="<<i<<endl;
}

وقد وجدت في بعض الكتب دالة تكافئ strlen:

int len(char str[])
{
int i;
for(i=0;str;i++);
return i;
}

هل رأيت كيف كتب for ؟؟ غريـــبة والله !!! و العجيب أنه وضع الفاصلة المنقوطة بعد الحلقة for .. مع أن البرنامج شغال 100% ! ياريت لو يقوم أحد الإخوان بتوضيح هذه النقطة.

2-الدالة الثانية:

void str_copie (char s1[],char s2[])
{
int i=0;
while(s1!='\0')
{
s2=s1;
i++;
}
s2='\0';
}

ما في مشكلة .. ولله الحمد.

3-الدالة الثالثة .. لم أستطع كتابة دالة تكافئها .. وهذه محاولتي:

void str_cmp(char str_1[],char str_2[])
{
    int i=0,s1=0,s2=0;
    while(str_1!='\0' && str_2!='\0')
    {
        if(str_1>str_2)
        s1++;       
        if(str_2<str_1)
        s2++;     
        if(str_1==str_2)
        s1=s2=1;  
        i++;    
     }     
     if(s1>s2)
     cout<<"s1>s2"<<endl;
     if(s1<s2)
     cout<<"s1<s2"<<endl;
     if(s1==s2 && s1==1)
     cout<<"s1=s2"<<endl;
}

أرجوا من الإخوان الخبراء .. توضيح كيفية استخدام حلقة for الأولى و المساعدة من أجل كتابة دالة تكافئ الدالة strcmp

دمتم في رعاية الله و حفظه.

#2
bool
CompareStrings(const char* s1, const char* s2, int s1_start_index,
               int s2_start_index, int count, bool ignoreCase)
{
     // surface check
     if (s1 == NULL || s2 == NULL || count == 0)
          return false;

     // used to store value of string + start_index
     char* s1_case = (char*)(void*)s1 + s1_start_index;
     char* s2_case = (char*)(void*)s2 + s2_start_index;

     // tmp character for search
     char tmp1 = 0, tmp2 = 0;

     // loop until count is zero
     while(count--)
     {
          // get first character from source string
          tmp1 = ignoreCase? *s1_case++ | 0x20: *s1_case++;
          // get first character from destination string
          tmp2 = ignoreCase? *s2_case++ | 0x20: *s2_case++;

          // if not match
          if (tmp1 != tmp2)
               // return sorry!
               return false;
     }

     // they match
     return true;
}

s1: هو النص الأول

s2: هو النص الثانى

s1_start_index: هو موقع داخل النص s1 حيث سيبدأ البحث (الـ index يبدأ من الصفر من اول النص)

s2_start_index: هو موقع داخل النص s2 حيث سيبدأ البحث (الـ index يبدأ من الصفر من اول النص)

count: عدد الحروف التى سيتم مقارنتها بين النصين بدءأ من المواقع المذكوره بالأعلى

ignoreCase: اجعلها true لتجاهل حالة الأحرف اثناء المقارنه و false لعدم تجاهل حالة الأحرف.

البحث يتم بإستخدام Linear search و هى ليست افضل حلول المقارنه حيث توجد طرق خرى اسرع و لكن اكثر تعقيدا.

---------

لداله طول النص جرب هذه

int StrLen(const char* str)
{
     char* tmp = (char*)(void*)str;

     while(*tmp++)
     {/*do nothing*/}

     return --tmp - str;
}

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

تم تعديل هذه المشاركة بواسطة Muhammad alaa في 22 مارس 2010 في 20:13

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

#3

السؤال الثاني:

بالنسبة لـfor فقط لان السلسلة النصيه تتوقف مباشرتا عندما تنتهي الحروف مباشرتا فلذلك وضع الفاصله المنقوطه لتدور الحلقه حتى تصل نهاية النص ثم يأخذ رقم العداد فقط

السؤال الثالث:

هذا كود المقارنه : جربه

int str_cmp(char str_1[],char str_2[])
{
int i=0;
while(str_1||str_2)
if(str_1!=str_2[i++]) return -1;
return 0;

}
tvquran_6.gif

#4

هذه دالة لحساب طول نص ستفهم مأشكل عليك منها ان شاء الله

int str_len(char str[])
{
    int i=0;
while(str[++i]); return i;
}
tvquran_6.gif

#5
اقتباس
s1: هو النص الأول

s2: هو النص الثانى

s1_start_index: هو موقع داخل النص s1 حيث سيبدأ البحث (الـ index يبدأ من الصفر من اول النص)

s2_start_index: هو موقع داخل النص s2 حيث سيبدأ البحث (الـ index يبدأ من الصفر من اول النص)

count: عدد الحروف التى سيتم مقارنتها بين النصين بدءأ من المواقع المذكوره بالأعلى

ignoreCase: اجعلها true لتجاهل حالة الأحرف اثناء المقارنه و false لعدم تجاهل حالة الأحرف.

البحث يتم بإستخدام Linear search و هى ليست افضل حلول المقارنه حيث توجد طرق خرى اسرع و لكن اكثر تعقيدا.

أشكرك أخي محمد علاء ..بس بصراحة الكود متعقد وصعيــــــــــب !!! لاتزعل من صراحتي فأنا مبتدأ ...

اقتباس
بالنسبة لـfor فقط لان السلسلة النصيه تتوقف مباشرتا عندما تنتهي الحروف مباشرتا فلذلك وضع الفاصله المنقوطه لتدور الحلقه حتى تصل نهاية النص ثم يأخذ رقم العداد فقط

سؤالي هو : لماذا نضع الفاصلة المنقوطة بعد الحلقة for مع أنها ليست أمر !!!

اقتباس
هذا كود المقارنه : جربه

جاري التجربة ..

ملاحظة:أرجوا من الإخوة محمد علاء و فهد أن يساعدوني في إجابة الأسئلة التي طرحتها في موصوع "أرجوا المساعدة"

تم تعديل هذه المشاركة بواسطة khaled_prg في 22 مارس 2010 في 21:35

#6
اقتباس
سؤالي هو : لماذا نضع الفاصلة المنقوطة بعد الحلقة for مع أنها ليست أمر !!

أقراء المشاركة جيدا فقد كتبت لك الإجابه

tvquran_6.gif

#7
اقتباس
أقراء المشاركة جيدا فقد كتبت لك الإجابه

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

#8

هذه نسخه مبسطه من دالة المقارنه

bool
CompareStrings2(const char* s1, const char* s2)
{
	// used to store value of string
	char* s1_case = (char*)(void*)s1;
	char* s2_case = (char*)(void*)s2;

	// loop until count is zero
	while(*s1_case)
		// if not match
		if (*s1_case++ != *s2_case++)
			// return sorry!
			return false;

	// they match
	return true;
}

اقتباس
مشكلتي في النقطة الفاصلة .. كنت أعتقد أنها تأتي بعد الأوامر فحسب .. وهذه المرة كتبناها بعد الحلقات التكرارية !!!

عندما تكتب جملة for او while يليها statement واحده فقط مثلما يوجد داخل كود طول النص فى مشاركتك الأولى فإنك تضع فاصله منقوطه بعد انتهاء هذه الـ statement لتعلم المترجم بإنتهاء الجمل التى سيتم تنفيذها لها الـ loop

while(strg!='\0')
i++;

اذا ماذا يحدث إذا كانت حلقة التكرار لا يوجد كود لها ؟

فى هذه الحاله اما انك ستكتب حلقة التكرار يليها قوسين فارغين (مثلما فعلتها انا فى دالة طول النص)

while(*tmp++)
     {/*do nothing*/}

او انك ستقوم بوضع الفاصله المنقوطه بعد نص حلقة التكرار مباشرة لتعلم المترجم انه لا توجد statement ليتم تنفيذها (إلا بالطبع الموجوده داخل شرط التكرار) و هذا ما تراه داخل كود for الموجود بمشاركتك و ايضا بكود طول النص للأخ فهد.

* جزء من الكود الموجود بالمشاركه الأولى

for(i=0;str;i++);

* جزء من كود الأخ فهد

while(str[++i]);

إذا قمت بمراجعة قواعد اللغه ستجد ان جملة for و while و do-while يمكن كتابتهم بالصور التاليه

* جملة for

for (int i = 0; i < 5; i++)
   statement;

for (int i = 0; i < 5; i++)
{
     statement 1;
     statement 2;
     statement 3;
}

* جملة while

while ( i < 5)
   statement;

while ( i < 5)
{
     statement 1;
     statement 2;
     statement 3;
}

* جملة do-while

do
   statement;
while ( i < 5);

do
{
     statement 1;
     statement 2;
     statement 3;
}
while ( i < 5);

كما ترى من اسلوب كتابة كل منهم فإذا قمت بحذف الـ statements منهم ستجد احداهم كتبت بأقواس فارغه و الأخرى انتهت بقاصله منقوطه لتدل على عدم وجود كود يتبع هذه الحلقه.

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

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

#9

يا سلاااااااااااااااااااااام !!! هي كده الخبره .. والله بلاش ...

ماشاء اله فتبارك الله عليك يا أخ علاء .. الله ينفعنا بعلمك .. وفقك المولى في الدارين

أشكرك مرة أخرى على التوضيح الأكثر من رائع ...

و لا أنسى مشرفنا الغالي "فهد" .. فجزاه الله ألف خير ...

اقتباس
هذه نسخه مبسطه من دالة المقارنه

مشكلتي الوحيدة هي أنني لم أدرس المؤشرات بعد !!! لذا لا يمكنني فهم الكود الذي طرحته .

بالنسبة للكود الذي طرحه الأخ فهد:

int str_cmp(char str_1[],char str_2[])
{
int i=0;
while(str_1||str_2)
if(str_1!=str_2[i++]) 
return -1
;return 0;
}

كود جميل و لكنني لم أفهمهم 100% .. أحتاج شرح بسيط للكود . وخصوصا كلمة return مكتوبة مرتين !!! بالإضافة إلى الأوامر التابعة للدالة.

تم تعديل هذه المشاركة بواسطة khaled_prg في 23 مارس 2010 في 13:52

#10

حاولت كتابة الأكواد بطريقة ترجعية

بالنسبة لدالة المقارنة فحاولت عدم الاكتفاء بارجاع قيمة 1 في حالة المساوات و 0 في العكس بل تعيد الفرق بين المذخلين و هو ما يمكن استعماله في دالة ترتيبة


{
if (*myString) return 1+stringLen(myString+1);
else return 0;
}

void stringCpy(char* dest,char* source)
{
if (*source)
{
(*dest) = (*source);
stringCpy(dest+1,source+1);
}
else (*dest) = '\0';
}

int stringCmp(char* string1,char* string2)
{
if (*string1 && *string2)
{
if (*string1 == *string2) return stringCmp(string1+1,string2+1);
else return (*string1-*string2);
}
else return stringLen(string1)-stringLen(string2);
}
int stringLen(char* myString)

أرجو لمن قام بتجربة الأكواد و عثر على خطأ ان يبلغني

#11

كل الدوال التى كتبتها ستتسبب فى stack overflow إذا كان حجم النص اكبر من عدد الإستدعاءات المحدده للدوال داخل الـ stack، بمعنى اخر قم بتجربة الكود التالى لمعرفة حجم النص:

void main()
{
	char* str = new char[5000];

	str[5000] = 0;

	int size = stringLen(str);
}

الكود السابق سيفشل و السبب stack overflow، خلاصة الأمر لا تستخدم اسلوب الإستدعاء الذاتى إلا فى اضيق اضيق الحدود و عندما لا تجد طريق اخر، ايضا لايهم حجم الداله قدر ما يهم انها تعمل جيدا و تنفذ بشكل سريع.

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

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

#12

أتفق معك تماما :)

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