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

تعلم ال Structure

بدأه Ali Al-Zyoud في 27 أكتوبر 2009 · 11 رد · 3,553 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

طبعاً البرمجه الشيئيه أو البرمجه الموجها للكائنات هي ان تجعل برنامجع مجموعه من ال objects او الكائنات التي تتعامل فيما بينها ولكل كائن دوره حياه و عمليه خلق او creation وعمليه موت او انهاء وجود الكائن ، طبعاً هذا الامر يسهل عليك الكثير من الجهد والعمل ويجعل برامجك اسهل من حيث الفهم وأمكانيه التطوير فأذا اردت ان تطور برنامجك فبأمكانك تطوير الكائن المعين الذي تريده دون تغيير على الكود للبرنامج .

طبعاً الموضوع يحتوي الكثير من المفاهيم الاساسيه وافضل طريقه لتعامها ه يفي ان تبداء تبرمج بنفسك كل موضوع جديد تتعلمه في هذا المجال ، المواضيع سهله وليسه صعبه ولكنها تعتمد على الابداع والتخيل نوعاً ما .

اولاً وقبل كل شيء عليك تعلم مفهوم ال structure بشكل اساسي قبل الدخول في علم ال OOP .

ال structure :

وهو عمل خليط من مجموعه من الvariables و functions او (دوال ومتغيرات) للقيام بوضيفه معينه او التعبير عن شيء معين

مثلاً لو اردنا ان نعمل structure لمربع ماهي المتغيرات للمربع ؟؟؟

انها طول الضلع لان باقي الاضلاع متساويه

ماذا يمكن ان نحصل عن معلومات قد نحتاجها من المربع مثلاً المساحه والمحيط ويمكن اشياء اخرى غير ذالك سوف نفترض اننا سوف نستفيد فقط من المساحه

اذا ال structure الذي سوف نقوم ببنائه يحتوي على متغير وهو طول الضلع وعلى function تحسب المساحه .

الان كيف علينا تحديد اسم ال structure وافضل اسم هو square اي مربع .

الان كيف سنعبر عن هذا ال structure حتي يفهمه السي ::

اولاً عليك ان تعرف ان عليك تعريف ال structure قبل داله ال main

ثانياً نستخدم الكلمه المحجوزه struct ثم يتبعها اسم ال structure الذي نريده

struct square

ثم القوسين وبداخلهما نكتب ما نريده من متغيرات و دوال

<!--c1--><div class='codetop'>كود</div><div class='codemain'><!--ec1--> struct square{<BR> int length;<BR> int Area(){return length*length;}<BR>};//مهم جداً جداً ان لاتنسى وضع الفاصله المنقوطه<!--c2--></div><!--ec2-->

لاتنسى وضع الفاصله المنقوطه .

طبعاً طول الضلع هو length وسوف تكون المساحه هي length*length اي طول الضلع تربيع

هذا هو تعريف الstructure ولان كيف نستخدمه ؟؟؟

الان داخل جمله ال main سنعرف متغير من نوع square اي من نوع الstructure الذي قمنا ببنائه .

;square S1

الان ماذا نحتاج ان ندخل للsquare من بيانات ؟؟؟ نعم انه طول الضلع lenght لكن كيف ؟؟؟

لاستخدام المتغيرات او الدوال داخل الstructure نستخدم ال النقطه بعد اسم المتغير الذي من نوع structure وهو هنا S1

;S1.length=10

الان ال structure سوف تقوم بحساب المساحه لك ، ولكن كيف نحصل على المساحه ؟؟

نستخدم نفس الطريقه بأستخدام الداله Area داخل ال structure

<!--c1--><div class='codetop'>كود</div><div class='codemain'><!--ec1--> cout<<S1.Area();<!--c2--></div><!--ec2-->

الان ماذا سيطبع البرنامج ؟؟ سيطبع 100 وهي المساحه الفعليه

والان البرنامج كاملاً :

<!--c1--><div class='codetop'>كود</div><div class='codemain'><!--ec1--><BR>#include<iostream><BR>#include<conio.h><BR>using namespace std;<BR>struct square{<BR> int length;<BR> int Area(){return length*length;}<BR>};//مهم جداً جداً ان لاتنسى وضع الفاصله المنقوطه<BR><BR>int main(){<BR>square S1;<BR>S1.length=10;<BR>cout<<S1.Area();<BR> getch();<BR>return 0;}<BR><!--c2--></div><!--ec2-->

اتمنى ان تكونوا فهمتو الفكره الاساسيه لل structure وهي بسيطه نوعاً ما ونستفيد منها كثيراً كما تلاحظ .

اي استفسارات ان ارحب بها كثيراً

ولان حاولو ان تعملو structure لل المستطيل واضف له داله للمحيط مثلاً وحاول ان تطبق ما تعلمته هنا ، وانا في الخدمه للمساعده

#2

السلام عليكــم ورحمـة الله وبركاتــه ،،درس جيد و ذكرني في مشكل إعترضني عند التعامل مع structure و لم أجد كيف أفرغ محتوياهاالمشكل يتمثل في كيفية إفراغ structure تحتوي متغيرات من نوعchar[] لإحرر لاحقا المتغير من نوعstructure من الذاكرة<!--c1--><div class='codetop'>PHP</div><div class='codemain'><!--ec1-->typedef struct FileInfo{char FullPath[50];char FileName[20];char AccessPermission[10];long long int size;};EFT_Upload =(FileInfo*)malloc(sizeof(struct FileInfo));// CONSTANTS<!--c2--></div><!--ec2--><!--c1--><div class='codetop'>PHP</div><div class='codemain'><!--ec1-->free(EFT_Upload); // Invalid structure free operation !!!<!--c2--></div><!--ec2-->

#3

بن العيد

يمكنك عرض الكود لربما هناك شى نستطيع مساعدتك فية (الجزء الخاص بملئى الchar[] )

فمن الممكن ان تكون ملئت الchar [] عن طريق مساواتة بconstant اى مثلا

ففى تلك الحالةلن تترجم اصلا لانك تحاول اسناد constant char* الى constant char* ولن يقبل الاول التغيير

والطريقة الاخرى انك قد تكون ملاتها عن طريق احد دوال الcopy

وفى تلك الحالة سيكون لديك نسختين فى الذاكرة من الstring .

الحل الذى اقترحة هو فانكشن ك() scanf فتلك الدالة ستقوم بملئى الchar[] عند طريق نقل البيانات الية فى scope اخر(لانها ستجرى ذلك فى دالة اخرى) وبالتالى ستقوم بمسح نسخة الcallee وسيعود اليك char[] مملوء ببياناتك (وايضاء فعلها بتلك الطريقة سيترك لك فرصة لاختبار الsize قبل نقلة)

وفى تلك الحالة يجب ان تحرر .

كل تلك افتراضات فقط

الكود سيوضح اكثر.

تم تعديل هذه المشاركة بواسطة apex في 29 أكتوبر 2009 في 21:56

name : mohamedyosry

#4

الكود عملته بال سي وليس السي بلس بلس ، تقريباً المبداء واحد بال سي بلس بلس اذا عملت dynamic allocation وهي استخدام الامر new ،ولكنه لن يخرج من الميمور حتى تعمل delete لل pointer .

اما بالسي فنستخدم malloc ولتفريغ نستخدم ال free

المبداء واحد في اللغتين ولكنه اسهل بالسي بلس بلس .

ولكن دائماً ومهم جداً جداً تفريغ المتغيرات التي عملتها dynamic allocation لانها لن تختفي من البرنامج الا عند انتهائه فتخيل ان هناك function تخلق كائن وتعمل له dynamic allocating في كل مرا تستدعيها بعد فتره ستجد ان برنامجك بداء يحتوي اضعاف حجمه الاصلي بذاكره .

ومن اهم الامثله على استخدام ال dynamic allocating في ال data structure K وفي ال winAPI وهي عادتاً تستخدم حسب الحاجه ويمكن استخدامها في اي برنامج

#5

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

ذكرت ما أتحدث عنه بمزيد من التفاصيل في هذا الموضوع

]الإتقان في البرمجة

#6

ما لاحظتة فى الكتاب . الكود الخاطى المشار الية

char* FileTempExtension;
// Memory allocation
FileTempExtension=(char*)malloc(sizeof(FileTempExtension))

قمت بحجز ذاكرة بحجم char* اى 4 بايت (حجم البوينتر يتوقف على الالة) لتستخدمها بعد ذلك لتخزين 6 بايت بتلك الجملة

strcpy(FileTempExtension,".temp");

اعتقد ان هناك انتهاك للذاكرة

والكود يحتوى على اخطاء اخرى

typedef struct FileInfo
 {char FullPath[50];
  char FileName[20];
  char AccessPermission[10];
  long long int size;
 };

ومن ثم

FileInfo *EFT_Upload;

ربما اختلاف مترجمات ولكنى استخدم gcc ولا تترجم الا ب

typedef struct FileInfo
 {char FullPath[50];
  char FileName[20];
  char AccessPermission[10];
  long long int size;
 }FileInfo;

ولا اعتقد ان ستركشر التى تحتوى مصفوفات لا تحرر لان هذا الكود عمل معى دون مشاكل

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
	typedef struct FileInfo
	 {char FullPath[50];
	 }FileInfo;
	FileInfo *EFT_Upload;
	EFT_Upload =(FileInfo*)malloc(sizeof(struct FileInfo));
	strcpy(EFT_Upload->FullPath,"fgdfgfg");
	free(EFT_Upload);
	return 0;
}

وهذا ايضاء

int main()
{
	typedef struct FileInfo
	 {char FullPath[50];
	 }FileInfo;
	FileInfo *EFT_Upload;
	EFT_Upload =(FileInfo*)malloc(sizeof(struct FileInfo));
	printf(EFT_Upload->FullPath,"/home/MyName/Boxes/EFT_Upload.xml");
	free(EFT_Upload);
	return 0;
}

اعتقد ان امر عدم الترجمة يخص خطاء ماء وارجح انتهاك الذاكرة

name : mohamedyosry

#7

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

لاحضت من الملف انك تستخدم c syntacs . وخصوصاً مع الدالتين المشهورتين malloc و free .

ان احد اهم الاسباب التي لاانصح البرمجين الجدد بأستخدام هذه الدوال ليس بسبب ضعفها ولكن لانهم ما سوف يواجهونه في المستقبل القريب في بيئه الدوت نت اشكال dynamic allocation مثل السي بلس بلس ولكنها بعيده نوعاً ما عن ال سي نثل gcnew ، طبعاً لمبرمجي لسي يستطيع استخدام جميع الطرق دون ان يختلط عليه الامر .

وهناك استفسار وهو :

انك تحدثت انه عند تفريغ لائحه من المؤشرات لايكون استخدام الداله delete في محلها ولكن ان الامر يمكن ان لايفهم المبتدئين هذا الشيء لانه عمل delete هو نفس عمل free في هذا المجال فيمكن استخدامها لتفريغ الائحه مؤشراً تلو الاخر بنفس الاستخدام

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// TYPES
typedef struct FileInfo
{
char * FullPath;
char * FileName;
char * AccessPermission;
long long int size;
};
// CONSTANTS
#define READ "F_CANREAD"
// METHODS
int main()
{ 
 FileInfo *EFT_Upload;
	char* FileTempExtension;
 // Memory allocation
 EFT_Upload =new FileInfo;
 EFT_Upload->FileName=new char[50];
 EFT_Upload->FullPath=new char[50];
 EFT_Upload->FullPath=new char[50];
 FileTempExtension=new char[50];
 // populate the EFT_Upload structure
 strcpy(EFT_Upload->FileName,"EFT_Upload.xml");
 strcpy(EFT_Upload->FullPath,"/home/MyName/Boxes/EFT_Upload.xml");
 strcpy(EFT_Upload->FullPath,READ);
 // Assign a value to the char* variable FileTempExtension
 strcpy(FileTempExtension,".temp");
 // Continue your work here
 delete(EFT_Upload->FileName);
 delete(EFT_Upload->FullPath);
 delete EFT_Upload;
 // Now EFT_Upload structure is free
 return 0;
}

اتمنى انك ما تزعل وتخلي دائماً روحك رياضيه بالنقاش ، واحنا بنتناقش وكل شي تمام

#8

<!--c1--><div class='codetop'>كود</div><div class='codemain'><!--ec1-->انك تحدثت انه عند تفريغ لائحه من المؤشرات لايكون استخدام الداله delete في محلها ولكن ان الامر يمكن ان لايفهم المبتدئين هذا الشيء لانه عمل delete هو نفس عمل free في هذا المجال فيمكن استخدامها لتفريغ الائحه مؤشراً تلو الاخر بنفس الاستخدام<!--c2--></div><!--ec2-->

مبرمجى سى/سى++ يحفظونها جيدا . استخدم free مع malloc و delete مع new

بالطبع new لها استخدامها فى حجز الobjects وذلك لانها تنادى الconstructor بعد حجز الذاكرة و الdelete تنادى ال destructor قبل تفريغ الذاكرة وبعض الامور التى تجعل تلك الفانكشن مناسبة لاستخدامها مع الobjects .

عموما الاختلافات تنحصر فى

<!--quoteo--><div class='quotetop'>إقتباس</div><div class='blockquote'><!--quotec-->1. Operator new constructs an object (calls constructor of object), malloc does not.

2. Operator new is an operator, malloc is a function.

3. Operator new can be overloaded, malloc cannot be overloaded.

4. Operator new throws an exception if there is not enough memory, malloc returns a NULL.

5. Operator new[] requires to specify the number of objects to allocate, malloc requires to specify the total number of bytes to allocate.

6. malloc() returns void *, which has to be explicitly cast to the desired type but new returns the proper type.

7. Operator new/new[] must be matched with operator delete/delete[] to deallocate memory, malloc() must be matched with free() to deallocate memory.

8. The new/delete couple does not have a realloc alternative that is available when malloc/free pair is used. realloc is used to resize the length of an array or a memory block dynamically.<!--QuoteEnd--></div><!--QuoteEEnd-->

لكنك فى حالات قد تحتاج لاستخدام malloc() خاصة ان اكثر دقة واكثر تحكم فى بعض الحالات. واحيانات هناك دوال حجز aligned و هناك دوال حجز فى الstack

مثل alloca() (لكنها غير محمولة على الاجهزة التى لا تحتوى على stack ) .

وفى النهاية ايضاء انت تستخدم malloc() لاسباب منها

-تريد ان يكون الكود محمول بين السى والسى++.

-انت تستخدم مكتبة من السى وتقوم بحجز مساحة لشى تابع لها فعليك ايضاء بmalloc .

فى السى (واعتقد ان معظم مبرمجى السى++ يفكرون بنفس الطريقة ) يعتبرون

<!--quoteo--><div class='quotetop'>إقتباس</div><div class='quotemain'><!--quotec-->وهو عمل خليط من مجموعه من الvariables و functions<!--QuoteEnd--></div><!--QuoteEEnd-->

يعتبرون هذا الامر زائد لان فى السى لا يمكن تضمين function فى الstructure (فى لغات كc# ذهبوا ابعد من ذلك ليضمنوا اساليب الoo من ال inheritance و encapsulation (عمل public & private & protected )

باختصار اذا اردت ذلك فلتنشى class وتدعك من الستراكشر لانها مناسبة ببساطتها لاغراض اخر (لا يمكن تضمين الا الvariables و pointer to function ) وايضاء حافظ على توافقك مع السى

تم تعديل هذه المشاركة بواسطة HGB في 26 نوفمبر 2009 في 00:20

name : mohamedyosry

#9

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

المشكلة و بكل بساطة تتمثل في كيفية إفراغ متغير من نوع مؤشر ل struct تتكون عناصره من char[]

#10

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

اقتباس
ما لاحظتة فى الكتاب . الكود الخاطى المشار الية

لم أتحدث عن كود خاطئ، إنما تحدثت عند مؤشر محجوز حتى نهاية الترجمة

اقتباس
قمت بحجز ذاكرة بحجم char* اى 4 بايت (حجم البوينتر يتوقف على الالة) لتستخدمها بعد ذلك لتخزين 6 بايت بتلك الجملة

حجزت المتغير و تركته بنوع المتغيرchar* لأن القيمة التي ستسند له لاحقا متغيرة

اقتباس
والكود يحتوى على اخطاء اخرى

:blink:

اقتباس
ولا اعتقد ان ستركشر التى تحتوى مصفوفات لا تحرر لان هذا الكود عمل معى دون مشاكل

هل تحققت من إفراغ الذاكرة؟

اقتباس
انك تحدثت انه عند تفريغ لائحه من المؤشرات لايكون استخدام الداله delete في محلها ولكن ان الامر يمكن ان لايفهم المبتدئين هذا الشيء لانه عمل delete هو نفس عمل free في هذا المجال فيمكن استخدامها لتفريغ الائحه مؤشراً تلو الاخر بنفس الاستخدام

dlete واحدة تلوى الأخرى إذا كانت العناصر المكونة للstruct مؤشرات و ليس مصفوفة حروف char[]، و هو ما أعنيه بسؤالي

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

اقتباس
اتمنى انك ما تزعل وتخلي دائماً روحك رياضيه بالنقاش ، واحنا بنتناقش وكل شي تمام

لا أرى علاقة هذه الأمنية بالموضوع !!!

#11
اقتباس
حجزت المتغير و تركته بنوع المتغيرchar* لأن القيمة التي ستسند له لاحقا متغيرة

انا استفسر عن هذا السطر

FileTempExtension=(char*)malloc(sizeof(FileTempExtension))

فلماذا حجزت لة ذاكرة بحجم char* (اى على بعض الالات 4 بايت )

ولكن حسب ردك فان فى باقى الكود يحتوى طريقة ليحجز لة على حسب المساحة المرادة .

اقتباس
والكود يحتوى على اخطاء اخرى

اقصد فقط اضافة اسم typedef بعد الستركشر اذا كنت تنوى تعريفة من اسمة

typedef struct FileInfo
{char FullPath[50];
char FileName[20];
char AccessPermission[10];
long long int size;
}FileInfo;

اذا كنت تريد تعريفة بتلك الطريقة

FileInfo *EFT_Upload;

تم تعديل هذه المشاركة بواسطة apex في 2 نوفمبر 2009 في 00:29

name : mohamedyosry

#12
بن العيد كتب:

dlete واحدة تلوى الأخرى إذا كانت العناصر المكونة للstruct مؤشرات و ليس مصفوفة حروف char[]، و هو ما أعنيه بسؤالي

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

حجزت المتغير و تركته بنوع المتغيرchar* لأن القيمة التي ستسند له لاحقا متغيرة

ماذا تقصد اذا كانت عناصر ال struct مؤشرات وليست مصفوفه حروف ؟؟؟ ان المؤشر يشير الى مصفوفه موجوده بال heap اذا حذفت المؤشر تختفي المصفوفه .

اما من حيث حجز المتغير من نوع *char انت لم تحجز متغير من هذا النوع انما عرفت مؤشر من نوع char ولم تحجز شيئاً بذاكره سوى حجم المؤشر بذاكره ال stack وهي 4 byte ولايمكن حجز قيمه له ان لم تقم بأنشائه initialization وهو ماعملته بال new اما بلكود فأنك تضع قيمه بداخله دون عمل انشاء له مما يسبب الخطاء في الكود لانك لاتعمل انشاء للمؤشرات داخل ال struct وعدم اضافه بعض المكتبات الخاصه مثل string.h.

تم تعديل هذه المشاركة بواسطة Ali Al-Zyoud في 2 نوفمبر 2009 في 09:30

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