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

سؤال متواضع؟؟!!

مغلق
بدأه الحاسوبية في 27 سبتمبر 2003 · 15 رد · 1,192 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

كيف أقوم باسترجاع أكثر من قيمة من أي اجراء (function )

نحن نعلم بأن كلمة return تستخدم للعودة بقيمة ما من الاجراءات

ولكن return تعود بقيمة واحدة فقط.. فكيف تعود بأكثر من قيمة؟؟

أتوقع المؤشرات لها دور في ذلك .. أود التوضيح لو سمحتوا

تحياااااتي

#2

في لغه السي والسي++ لا توجد طريقه لذلك, مع العلم أنه يوجد لغات تدعم هذا, لكن يوجد عده حلول:

* عدد القيم "المرَجعه" معروف ضمناً, ومن نفس النوع, الحل ارجاع هذه القيم بمصفوفه.

* استعمال struct أوبناء class خاص اذا لزم الأمر مثال:

typedef struct {

int a;

char b;

} new_type;

new_type my_function (...) {

new_type tst;

...

return tst;

}

* حلول غير محبذه GLOBAL VARS!!

#3

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

يمكن عمل ذلك عن طريق المؤشرات او ما يطلق عليه refernce parameters

مثال

void example ( int& param);

اختكم

لغة سي

c_languge

#4

السلام عليكم,

إن الطريقة التي أتى بها الأخ SirFlipFlop هي أحسن الطرق.

وأريد أن أزيد إضافة أنه حين نرجع struct هكدا من الأفضل أن لا تكون كبيرة يعني فيها أشياء كثيرة ففي هده الحالة يجب استرجاع مؤشر ل struct كما قال الأخ clang .

وإلى اللقاء.

#5

السلام عليكم

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

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

وشكرا

اللهم علمنا ما ينفعنا وأنفعنا بما علمتنا أنك أنت العليم الحكيم

سبحان الله وبحمده سبحان الله العظيم

لاحول ولاقوة الا بالله( كنز من كنوز الجنة ).

#6

السلام عليكم,

أريد أن أضيف شيئا وهو أنه حين نرجع مثلا قيمتين من دالة باستعمال المؤشر ففي الحقيقة سنقوم كأننا استعملنا struct دون أن ندري.

فكمثال نفترض أن الدالة سترجع قيمتين من DWORD وهما x و y .فإدا استعملنا struct str والدالة ترجع لنا مؤشر على الستراكت فسنقرأ القيمتين كالتالي :

str->x و str->y .

وإدا افترضنا أنالدالة ترجع مؤشر اسمه ptr من نوع DWORD مثلا فسنقرأ القيمتين كالتالي :

x=*ptr

ptr++ العلامة + على اليمين .

y=*ptr

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

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

أتمنى أن يكون في هدا إفادة في انتظار اقتراحات أخلرى من عند الإخوان.

إلى اللقاء.

#7

SR Filp Flop

Clang

Chik

السهم الناري

أشكركم جزيل الشكر على هذا التفاعل الرائع

ومزيدا من التقدم ان شالله

لم أرى ردودكم إلا الآن

أفدتوني الله يجزاكم خير

وكلامك الأخير ياأخ chik معقول

شكرا مرة أخرى

#8

نعم الأخ chik أعطى تحليل ممتاز وأنا ساوضح شيء قاله, القيم المتتابعه تلك هي عباره عن مصفوفه, والمعروف ان الشكل الذي تحجزه المصفوفه متتالي في الذاكره, تماماً كما نعرفه, (لكن أشدد هنالك حالات الوضع فيها يختلف, لا أريد الدخول في التفاصيل, لكن ماذا يحدث لمصفوفه "طويله جدا"ً؟؟) وهذا يتوافق أيضاً مع الحل الأول الذي أعطيته.

وللأيضاح الترتيب المتتالي للقيم داخل الـstruct يختلف عن الترتيب الذي حددناه نحن داخل الكود, ذلك لأن الكمبايلر ("الذكي")يجد ترتيباً معيناً لوضع القيم في الذاكره - لتوفير المكان!! أتوقف هنا لأن الكماله بعد ذلك تتعلق بتصميم الأسمبلر للمعالج...

#9

هذا مثال يقوم باستعادة ثلاث قيم من الدالة واتلبرنامج واضح مربع ومكعب رقم ( بواسطة المؤشرات )

#include <iostream.h>

//ÈÑäÇãÌ ÏÇáÉ ÊÚíÏ ãÑÈÚ æãßÚÈ ÑÞã

int  SquerAndCaub( int n, int *psquer, int *pcaub );

int main()
{
	int  squar,caub,number;
    int error;

	cout << " Enter Number 0 to 20  ";
	cin >> number;

	error = SquerAndCaub(number,&squar,&caub);

	if( !error)
	{
  cout << "\n Number = " << number;
  cout << "\n Squar  = " << squar;
  cout << "\n caub   = " << caub;
  cout << endl;
	}
	else
	{  
  cout << "\n Error Input \n ";
  
	}

	return  0;
}

int  SquerAndCaub( int n, int *psquer, int *pcaub )
{
	int value =0;

	if( n>20 )
  value = 1;
	else
	{
  *psquer = n*n;
  *pcaub   = n*n*n;
  value = 0;
	}

	return  value;
}

كما أني أريد من الاخ chik اذا تكرم أدراج مثال لكي يتضح لنا كيف نعود بمصفوفة كاملة ونطبعها باستدخاد struct والرجوع بمؤشر اليه.أو أي شخص أخر اذا اراد ذلك فالمهم تبادل الخبرات.

والى اللقاء

اللهم علمنا ما ينفعنا وأنفعنا بما علمتنا أنك أنت العليم الحكيم

سبحان الله وبحمده سبحان الله العظيم

لاحول ولاقوة الا بالله( كنز من كنوز الجنة ).

#10

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

اللهم علمنا ما ينفعنا وأنفعنا بما علمتنا أنك أنت العليم الحكيم

سبحان الله وبحمده سبحان الله العظيم

لاحول ولاقوة الا بالله( كنز من كنوز الجنة ).

#11

السلام عليكم,

نحن قد تكلمنا عن كيفية إرجاع عدة قيم بواسطة دالة وأنا قد قلت أنه يمكننا فعل دلك بإرجاع مؤشر لStruct نكون قد وضعنا فيه كل ما نريد إرجاعه وسأعطي مثالا بسيطا لهدا كما طلب بعض الإخوان.

عندنا دالة MyFunc(int x,int y) نعطيها عددين ويجب أن ترجع لنا بواسطة مؤشر عن الستراكت 3 أعداد. جمع العددين , فارقهما و نتيجة ضربهما وهنا تكون عندنا struct كالتالي

Struct TheRet

{

int Sum ; الجمع

Int Diff ; الفرق

Int Mul ; الضرب

}

وهدا هو المثال كاملا :

#include <iostream.h>

struct TheRet

{

int Sum;

int Diff;

int Mul;

};

TheRet rr;

TheRet* MyFunc(int x, int y)

{

rr.Sum=x+y;

rr.Diff=x-y;

rr.Mul=x*y;

return &rr;

}

int main(int argc, char* argv[])

{

int x,y;

cout << "Enter 2 numbers \n";

cin >> x >> y;

TheRet* a=MyFunc(x,y);

cout <<"the sum is : "<<a->Sum <<"\n";

cout <<"the diff is : "<<a->Diff << "\n";

cout << " the mul is : "<< a->Mul << "\n";

return 0;

}

هدا ونهن هنا نتكلم على Return لكن في الحقيقة وفي هده الحالات الأشياء التي نريد من الدالة استرجاعها نرسل مئشرات لها في Arguments للدالة وهده الأخيرة لا ترجع شيئا..ففي المثال السابق يمكن أن نغير الدالة على النحو التالي :

Void MyFunc(int x,int y,int* sum,int* diff,int* mul)

وفي هده الحالة يصبح المثال السابق كالتالي

#include <iostream.h>

void MyFunc(int x, int y,int* sum,int* diff,int* mul)

{

*sum=x+y;

*diff=x-y;

*mul=x*y;

}

int main(int argc, char* argv[])

{

int x,y,thesum,thediff,themul;

cout << "Enter 2 numbers \n";

cin >> x >> y;

MyFunc(x,y,&thesum,&thediff,&themul);

cout <<"the sum is : "<<thesum <<"\n";

cout <<"the diff is : "<<thediff << "\n";

cout << " the mul is : "<< themul << "\n";

return 0;

}

وهدا الأخير يستعمل كثيرا مثل ما نلاحظ في العديد من API مثل GetWindowText على سبيل المثال.

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

إلى اللقاء.

#12

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

ولكن لدي سؤل اذا تكرمت لماذا كتبنا في الدالة الاولى

return  &rr;

 لماذا كتبت ( &) مع جملة return

ملاحظة للكتابة الكود يوجد شيء اسمه CODE ضلل الكود واضغط عليه وأن شاء الله تكون الكتابه غير مقلوبة.

وشكرا الى اللقاء.

اللهم علمنا ما ينفعنا وأنفعنا بما علمتنا أنك أنت العليم الحكيم

سبحان الله وبحمده سبحان الله العظيم

لاحول ولاقوة الا بالله( كنز من كنوز الجنة ).

#13

السلام عليكم,

نعرف أن الأوبراتر & حين يكون أمام شيء ما فإنه يعطينا العنوان أو رقم الداكرة الموجود فيه دلك الشيء.

فمثلا حين أكتب :

int a=5 فهنا a عدد وقيمته 5 ولكن حين أكتب a & فهدا يعطيني العنوان الموجود فيه قيمة a أو بعبارة أخرى يعطينا المؤشر على a .

ففي المثال السابق أردنا من الدالة أن ترجع مؤشرا عن الستراكت ونحن قد قمنا ب TheRet rr وهنا rr هي ستراكت وليس مؤشر عن الستراكت وحين نملأ هده الستراكت ونريد أن نرجع مؤشر عنها سنرجع rr& وكما قلنا هدا سيعطينا المؤشر عن الستراكت rr وهدا ما كنا نريده.

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

وعكس & هو * وهنا يجب أن نفرق بين هده النجمة والنجمة التي ندلي بهل على المؤشرات فمثلا :

int a=5 هنا عندنا عدد a وقيمته 5

int* pt = &a هنا عندنا مؤشر اسمه pt وهو من نوع int وقيمة هدا المؤشر هي عنوان a

int b=*pt النجمة هنا على يسار pt تعني القيمة من نوع int الموجودة في العنوان pt وهدا يشكل عكس ما تقوم به & .وفي هده الحالة فإن قيمة b ستكون هي نفس قيمة & يعني 5 .

وحين نستعمل هده الأشياء يجب معرفة شيء آخر وهو ما يسمى ب cast . فنحن عندما نستعمل المؤشرات فإننا نستعمل الداكرة أو عناوين في الداكرة .فلنقل أننا في العنوان x فالمشكل المتبقي هو مع كم عدد من الأبيات سنتعامل ولهدا فإننا حين نأخد مؤشر من نوع int فإننا نعرف أننا سنتعامل مع 4 بايت لأن int يكتب في الداكرة على 4 بايت وإدا كان من نوع byte فإنه سيأخد بايت واحد غلى غير دلك. وهنا يمكن أن نستعمل الكاست إدا أردنا تغيير بعض الأشياء فمثلا :

int a=5 عدد من نوع int قيمته 5

int* pt=&a مؤشر على a

byte* bt=(byte* )pt هنا bt هو مؤشر على byte ولكن قيمته هي نفس قيمة pt هدا الأخير يعمل على 4 بايت بينما bt يعمل على بايت 1 فقط وهنا استعملنا cast وهو ما كتب بين القوسين (byte* )

byte b=*bt هنا لا ستكون ما موجود في الداكرة bt مع أخد بايت 1 .هنا إدا كان العدد a أصغر من 255 القيمة القصوى للبايت - وهنا نفترض أننا نتعامل مع الأعداد الموجبة فقط حتى لا نعقد الأمور أكثر - فإن a و b تكون لهما نفس القيمة وسيكون غير دلك في الحالات الأخرى.

وإلى اللقاء

#14

السلام عليكم

أخواني

أسعدني تفاعلكم مع الموضوع

والله يعطيكم العافية

بالرغم من أن البرامج التي ذكرت كانت مكتوبة بلغة ++C

ولكن لا مشكلة .. فلافارق كبير بينها وبين C

شرح الأخ chik جميل ويشكر عليه

مع أن مسألة cast لم أفهمها جيدا

فمثلا هذا المثال لم أفهم مافائدة هالعبارة (int)

double a[2],*p,*q;
p=a;
q=p+1;
printf("%d\n",(int)q-(int)p);

هذا مثال بسيط ولكن ودي أعرف فائدة int في السطر الأخير

ولكم خالص شكري

تحياتي

#15

السلام عليكم,

في مثالك عندنا a من نوع double ونعرف أن double يأخد 8 بايت للتأكد من دلك يمكن أن نزيد السطر :

int sz=sizeof(double

);

ونرى أن فعلا sz تساوي 8 .

فحين نكتب q=a فإن q سيصبح مؤشرا على a أو بالأحر على a[0] فلنفترض أن q تشير إلى الداكرة رقم 1000 مثلا فحين نكتب p=q+1 فهنا p سيشير إلى a[1] يعني ستصبح قيمة p هي 1008 وليس 1001 لأن المؤشر double يعمل على 8 بايت وفي المثال فزيادة (int) في الحالتين تجعلنا نحسب الفرق على أعداد عادية int وليس على مؤشرات وهنا ستكون النتيجة 8 وهده تكون طريقة لحسب طول شيء ما. وللتأكد أكثر يمكن أن نزيد السطر :

int i=(int)(p-q) ; ونقارنه مع int j=(int)p - (int)q

فهنا نلاحظ أن i ستكون تساوي 1 بينما j تساوي 8.

أتمنى أن يكون هدا أوضح شيء ما وأنا رهن كل اقتراح.

إلى اللقاء.

#16

أخي chik

مشكور جزيل الشكر

وماقصرت

ومزيدا من التقدم ان شالله

تحياتي

هذا الموضوع مغلق.

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