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

حزورة لتنشيط الدماغ..

رائج
بدأه مصطفى 36a2 في 1 يوليو 2012 · 81 رد · 4,562 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#26

وهل هذا يعني أننا استطعنا معرفة العنوان الذي يؤشر عليه المؤشر؟؟لا ...

لا أظن أن هذا يحقق المطلوب ...

لنفترض أننا نريد المؤشر أن يؤشر على الحجرة رقم 1000 ..(طبعا سيكون أي تعامل مع الحجرة Access voilation لكن مجرد فكرة)

هذا هو المطلوب

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 2 يوليو 2012 في 22:50

#27
اقتباس
لنفترض أننا نريد المؤشر أن يؤشر على الحجرة رقم 1000 ويعرض محتواها .. هذا هو المطلوب

من أين لك بهذا الترقيم ؟

و كيف ستعرف عدد حجرات الذاكرة ؟؟

#28

ما رأيك بهذا الكود:

#include<iostream>
using namespace std;
int main()
{
    	unsigned int a=1000;
    	unsigned int*p=(unsigned int*)a;
    	cout<<p<<endl;
    	return 0;
}

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 2 يوليو 2012 في 23:09

#29

جيد, و لكن ماذا لو كان العنوان الذي حجزتَه مشغولا من طرف برنامج آخر ؟؟

#30

طبعا أخبرتك أن الدخول أصلا سيكون Access violation

ولكن مجرد فكرة ... طبعا لو كتبنا مثلاً ...

cout<<*p<<endl;

قسيتوقف البرنامج عن العمل ...

#31

شكرا لكم على هذا الموضوع المفيد ...

لكن لدي بعض الاستفسارات حول ما كتبتموه ...( كوني تعلمت الـ C++ حديثا ) ..

هل هناك أحد لديه بعض الوقت ليساعدني في إزالة الغموض عنها ... ( لا أريد أن أتثاقل على أحد :blush:

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

وشكرا لكل من يساعدني ..

وجزاكم الله خيرا :)

حسبنا الله ونعم الوكيل

#32

مرحبا بك أخي الكريم :)

ضع أسئلتك و ستجد الإجابة إن شاء الله.

بالتوفيق.

#33

للفائدة, الأسباب الرئيسية لــ Access violation هي :

  • استخدام مؤشر غير مهيئ أو مهيئ بشكل خاطئ.
  • تحرير المؤشر قبل الإنتهاء من استخدامه.
  • إذا تعدى المؤشر المساحة المخصصة له عند عملية الحجز. (الـــ Buffer Overflow هو نوع خاص من انواع الــ Access violation).

مثال بسيط :

لنفترض أننا نريد كتابة دالة تقول بتهئية المؤشر الذي تستقبله كوسيط, الكود سيكون هكذا :

#include<iostream>
using namespace std;
void initialization(int* p, int x) {
    *p = x;
    return;
}
int main() {
    int n = 8,*ptr = &n;
    cout<<ptr<<"\t"<<*ptr<<endl;
    initialization(ptr,1);
    cout<<ptr<<"\t"<<*ptr<<endl;
    return 0;
}

و المُخرجات في هذه الحالة ستكون هكذا :

0x22ff18        8

0x22ff18 1

Process returned 0 (0x0) execution time : 1.860 s

Press any key to continue.

.. لكن ماذا لو أرسلنا للدالة المؤشر NULL ؟

initialization(NULL,1);

هنا سنحصل على Access violation و سيتوقف البرنامج عن العمل ! :)

لأن المؤشر NULL يملك العنوان 0x00000000 وفي العادة هذا العنوان يكون Invalid Memory Address في أغلب نظم التشغيل, (لكن ليس دائما وليس في كل الحالات).

بالتوفيق.

2
#34

حتى يُشارك معنا الجميع, سأضع لكم سؤالا بسيطا .. و لكنه يشرح مفهوم مهم جدا في السي++ :)

عند تنفيذ الكود الآتي سيظهر لنا العدد 55 و السبب يعود إلى أن المترجم اعتبر أن الــ endl متغير صحيح قيمته 5 و بالتالي أظهره مرتين :

#include<iostream>
using namespace std;
int main() {
    short endl = 5;
    cout<<endl<<endl;
	return 0;
}

  • لماذا يتعامل المترجم مع الكلمة endl على أنها متغير !؟ لماذا لا يعتبرها end line ؟
  • كيف نُجبر المترجم على أن يتعامل مع المتغير endl الثاني باعتباره end line ؟

بالتوفيق.

2
#35

حسب فهمي لمفهوم مساحات الأسماء ومفهوم محددات الوصول ...

فالمترجم عنده أولوية في فهم المتغيرات ..وفي حالتنا فإن المتغير endl له قيمتان إحداهما تابعة لمساحة الأسماء std والأخرى تابعة للمتحول المحلي endl

وعلى هذا الأساس فإن سلم أولويات المترجم يبدأ من المتحولات المحلية ..ثم المتحولات العامة ...

وإن أردنا أن يأخذ endl كسطر جديد .. فعلينا كتابة محدد الوصول إلى std قبل endl كما يلي :

#include<iostream>
using namespace std;
int main() {
	short endl = 5;
	cout<<std::endl<<std::endl;
    	return 0;
}

سؤال جميل .. شكرا لك أخي أحمد ... والسلام عليكم

1
#36

أحسنت أخي مصطفى.

اقتباس
لماذا يتعامل المترجم مع الكلمة endl على أنها متغير !؟ لماذا لا يعتبرها end line ؟

لأن الأولوية تكون للمدى الحالى يليه ما يحتويه ثم ما يحتويه.

سأوضح أكثر :

الكود يحتوي على معرفين بنفس الإسم, أحدهما المتغير endl الموجود ف لبلوك التابع للدالة الرئيسية main و الثاني هو الدالة end line الموجودة في مساحة الأسماء std.

الأولوبة ستكون للمعرف الذي تم تعريفه في المدى الأقرب للمكان الذي تم استخدامه فيه, عندما يجد المترجم الكلمة endl, سيبحث عن أقرب تعريف موجود داخل أقرب مدى و نظرا لأننا قمنا بتعريف متغير باسم endl و استخدمنا هذه الكلمة داخل نفس مجال التعريف فسيقع اختيار المترجم على المتغير endl (تم تعريف المتغير endl في مدى أقرب من مدى الدالة end line الموجودة في مساحة الاسماء std) فسيتم استخدام المتغير بدلا من الدالة.

اقتباس
كيف نُجبر المترجم على أن يتعامل مع المتغير endl الثاني باعتباره end line ؟

في هذه الحالة يجب أن نستخدم معامل تحديد المدى (Scope Resolution Operator) للخروج من مدى الدالة الرئيسية وصولا إلى المدى التابع لمساحة الأسماء std, عندها سيتعامل الترجم مع الكلمة endl على أنها الدالة التي تنقل مؤشر الكتابة إلى سطر جديد.

شكل الكود الجديد سيكون هكذا (نكتب اسم مساحة الأسماء std ثم معامل تحديد المدى ثم العضو الذي نريد الوصول إليه) :

#include<iostream>
using namespace std;
int main() {
    short endl = 5;
    cout<<endl<<std::endl;
    return 0;
}

بالتوفيق.

#37
اقتباس
أحسنت أخي مصطفى.
blush.gif

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

ما رأيك لو نجمع هذه المواضيع كلها معاً (نضع روابطها معاً ) في موضوع جديد .. يعيد لموضوعك القديم حياته .. فهو رائع بالفعل ..

هل تقوم بهذه الخطوة أنت أم أقوم بها أنا ... طبعاً بعد رأيك عن الفكرة ..

#38

هل تريد فتح موضوع جديد يحتوي على روابط مواضيع أخرى ؟

أم جمع الأفكار المتناثرة في موضوع واحد ؟

#39

كلا الأمرين معاً ..

فتح موضوع جديد فيه الفوائد المتناثرة .. وفي مقدمته نضع روابط المواضيع القديمة المتميزة .. وفي الردود نضيف الفوائد الجميلة... والخبرات الجديدة

ما رأيك؟

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 3 يوليو 2012 في 14:03

#40

هذا ما يقوم به مشرفوا القسم حاليا :)

يمكنك إضافة ما تشاء من الأفكار الجديدة, أما تنظيم و ترتيب المواضيع القديمة فهذا عمل المشرفين.

تم تعديل هذه المشاركة بواسطة أحمد الشنقيطي في 3 يوليو 2012 في 14:35

#41

سؤال آخر بسيط أيضا :

اكتب برنامج يطلب من المستخدم إدخال عددين a و b, ثم يحسب نتيجة باقي القسمة (a%b) بأكثر من طريقة. (خمسة طرق على الأقل :))

#42

حسناً ... إذا سأضع هنا ما أريد .. وعلى الله الاتكال ..

وعليكم الفهرسة يا شجعان laugh.gif

هذه الفائدة (والله أعلم ) ستثير إعجابكم كثيراً ... فهي مفيدة جداً وعملها قد نحتاجه في الكثير من البرامج ...

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

#include<iostream>
using namespace std;
int main()
{
    	cout<<__TIME__<<endl
            	<<__DATE__<<endl
            	<<__LINE__<<endl
            	<<__FILE__<<endl;
    	return 0;
}

ننتظر إغناء الموضوع ... والله ولي التوفيق

1
#43

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

كيف ننفذ هذا الكود (كود باسكال) من خلال لغة السي ؟ :blush:

 var 
a : real
begin
writeln('Iam Hamza');
end.

تم تعديل هذه المشاركة بواسطة Hamza+C+ASM في 3 يوليو 2012 في 15:07

rS3eY.png
#44

ليس لدي أي معرفة مسبقة بالباسكال .. ولكن هل السؤال سهل لدرجة أن يكون هذا هو الجواب ؟

#include<iostream>
using namespace std;
int main()
{
	cout<<"'I'm Hamza'";
	return 0;
}

بالنسبة لباقي القسمة .. وصلت أخي أحمد .. دقائق فقط

#45

لا أخي مصطفى ليس هذا هو الجواب ، سؤالي هو كيف نكتب كود الباسكال في ملف مثلا test.cpp و يشتغل ...

هكذا :

#include<iostream>
var 
a : real
begin
writeln('Iam Hamza');
end.

تم تعديل هذه المشاركة بواسطة Hamza+C+ASM في 3 يوليو 2012 في 15:15

rS3eY.png
#46

جميل جدا :)

على ذكر قضية "الملفات", يمكننا برمجة فيروس (لطيف جدا :D) يقوم بحذف ملفات ذات خصائص معينة (نحن من نحدد هذه الخصائص).

المثال التالي يعرض لك المسار الذي يتواجد فيه البرنامج بالإضافة إلى أسماء و أحجام جميع الملفات التي يبدأ اسمها بالحرف C :

#include <dir.h>
#include <stdio.h>
#include <string.h>
char *current_directory(char *path)
{
         strcpy (path, "X:\\");
         path[0] = 'A' + getdisk();
         getcurdir (0, path+3);
         return (path);
}
int main()
{
         struct ffblk ffblk;
         char curdir[MAXPATH];
         int done;
         current_directory(curdir);
         printf("Repertoire : [ %s ]\n", curdir);
         printf("Affichage des fichiers : \n");
         done = findfirst("c*.*",&ffblk,0);
         while(done != -1)
         {
                        printf("\t%s\t%u (octets)\n", ffblk.ff_name,ffblk.ff_fsize);
                        done = findnext(&ffblk);
         }
         return 0;
}

مُخرجات الكود :

post-219439-075840500%201341076959.png

سبق و أن شرحتُ المثال في هذه المشاركة.

بالنسبة للحذف, فيمكننا إدراج أوامر MS-DOS في الدالة system مثلا :

  • الأمر del لحذف ملف معين.
  • الأمر :
    RD (remove directory)//rd nomrepertoire /S /Q

    لحذف مجلد معين مهما كانت محتوياته.

2
#47

أخي أحمد إليك محاولتي في باقي القسمة :

#include<iostream>
using namespace std;
int main()
{
	int a,b;
	cout<<"Enter a,b\n";
	cin>>a>>b;
	if(b==0)main();
	int c=a%b;//1
	cout<<c<<endl;
	int d=(double(a)/double(b)-a/b)*b;//2
	cout<<d<<endl;
	int e=a-(a/b)*b;//3
	cout<<e<<endl;
	for(int i=(a>b?a:b);i>=(a>b?b:a);i-=(a>b?b:a));//4
	cout<<i<<endl;
	for(int j=(a>b?b:a);j<=(a>b?a:b);j+=(a>b?b:a));
	int f=b-j+a;//5
	cout<<f<<endl;
	return 0;
}

أستاذ حسام فهمت عليك .. سأفكر في الحل ..شكرا

1
#48

@أخي حسام ..حاولت الحل باستخدام الماكرو ولكن يبدو أنها لم تعمل حاولت إضافة الأسطر التالية بعد include

#define var using namespace std;
#define begin int main(){
#define end return 0;}
#define a using std:
#define real cout;
#define writeln(X) cout<<X

ولكن يبدو ان التعامل مع علامات الترقيم أصعب مما توقعت ... سأنتظر معرفة الإجابة بفارغ الصبر ..

يمكنني مثلا أن أقوم بكتابة برنامج صغير لترجمته .. واستدعاء البرنامج عن طريق الماكرو .. ولكن يبدو أنني سأبتعد كثيرا عن الهدف الرئيسي ...

سأذهب الآن .. وأعود مساء إن شاء الله ... شكرا لكم .. والسلام عليكم

#49

@مصطفى, مازال هناك المزيد من الطرق :) :

#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;

int main() {
    int a, b;
    cout << "a = ";
    cin >> a;
    cout << "b = ";
    cin >> b;

    /********* Debut *******/

    /******** Methode 1 : *********/
    cout << a << " % " << b << " = " << a % b << endl;

    /******** Methode 2 : *********/
    int c;
    c = a / b;
    c *= b;
    cout << a << " % " << b << " = " << a - c << endl;

    /******** Methode 3 : *********/
    c = 0;
    while (c + b < a)
        c += b;
    cout << a << " % " << b << " = " << a - c << endl;

    /******** Methode 4 : *********/
    c = a;
    for (; c > b;)
        c -= b;
    cout << a << " % " << b << " = " << c << endl;

    /******** Methode 5 : *********/
    div_t divresult;
    divresult = div(a, b);
    cout << a << " % " << b << " = " << divresult.rem << endl;

    /********* Fin *******/
    return 0;
}
2
#50

ثق تماما بأنها نفس الطرق التي استعملتها ولكن مكتوبة بشكل مختلف ...

ما عدا آخر طريقة .. ما هذا النوع الجديد ؟؟

هناك طريقة متميزة بالأسمبلي ..حيث نأخذ الباقي من مسجل خاص يحتفظ بباقي القسمة ...

أراك في المساء والسلام عليكم

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