#include<iostream>
#include<string>
using namespace std;
struct node{
int data;
node *next;
};
void CreatList (node *p)
{
int n;
for(;;)
{
cout<<"Enter the value\n";
cin>>n;
if(n==0)
{
p=NULL;
break;
}
else
{
p->data=n;
p->next=new node;
p=p->next;
}
}
}
void PrintList(node *q)
{
while(q!=NULL)
{
cout<<q->data<<endl;
q=q->next;
}
}
int CountList(node *c){
int count=0;
while (c!=NULL)
{
count++;
c=c->next;
}
return count;
}
void main (){
node *head=new node;
CreatList(head);
PrintList(head);
int n=CountList(head);
cout<<"number of node "<<n<<endl;
}خطا في بناء اللينكد لست لم اتمكن من اكتشافه
لماذا
p->next!=NULL
وليس
p!=NULL
هل هناك فرق ؟؟
لاني لما جربت الاولى نجح البرنامج بالرغم اني غير مقتنعة فيها
تم تعديل هذه المشاركة بواسطة المـــــاسة في 6 مارس 2012 في 01:08
السلام عليكم
العبارة الأولى تعنى المؤشر الذى تشير له النود ليس هو القيمة الفارغة NULL ( أى النود لا تشير إلى NULL ) .
بينما العبارة الثانية تعنى أن عنوان النود نفسها ليس فارغ أى لا يساوى NULL ( بمعنى p هى عبارة عن مؤشر من نوع node وبالتالى عندما تكون قيمتة هى NULL أى لا يحتوى على عنوان أى نود ).
لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق
لا إله إلا أنت سبحانك إني كنت من الظالمين
شكرا اخي الفاضل
اذن ماهو الاصح استخدامه عند اختبار هل وصلنا لنهاية القائمة
المـــــاسة كتب:#include<iostream> #include<string> using namespace std; struct node{ int data; node *next; }; void CreatList (node *p) { int n; for(;;) { cout<<"Enter the value\n"; cin>>n; if(n==0) { p=NULL; الخطأ في هذه الخطوة break; } else { p->data=n; p->next=new node; p=p->next; } } } void PrintList(node *q) { while(q!=NULL) { cout<<q->data<<endl; q=q->next; } } int CountList(node *c){ int count=0; while (c!=NULL) { count++; c=c->next; } return count; } void main (){ node *head=new node; CreatList(head); PrintList(head); int n=CountList(head); cout<<"number of node "<<n<<endl; }
إليك التصحيح :
void CreatList (node *p)
{
int n;
node *tmp;
for(;;)
{
cout<<"Enter the value\n";
cin>>n;
if(n==0)
{
tmp->next = NULL;
break;
}
else
{
p->data=n;
tmp = p;
p->next=new node;
p=p->next;
}
}
}الخطأ عندما كتبتي
p = null
فأنت عملياً لم تعدلي أي شيء في الـlist التي تبنينها و لم تقفليها (بقي المؤشر على العنصر الأخير و الذي هو tmp->next كما هو و لم يصبح null)
أرجو أن يكون ما كتبته واضحاً
السلام عليكم
اقتباسvoid CreatList (node *p) { int n; for(;;) { cout<<"Enter the value\n"; cin>>n; if(n==0) { p=NULL; الخطأ في هذه الخطوة break; } else { p->data=n; p->next=new node; p=p->next; } } }إليك التصحيح :
void CreatList (node *p)
{ int n; node *tmp; for(;;) { cout<<"Enter the value\n"; cin>>n; if(n==0) { tmp->next = NULL; break; } else { p->data=n; tmp = p; p->next=new node; p=p->next; } } }
أخ محمد لا فرق بين الكودين السابقين فكلاهما ينهى القائمة ويجعل أخر نود تشير إلى NULL
ولكن كلاكما لم تحررا الذاكرة المحجوزة لأخر نود أى توجد نود محجوزة غير مستخدمة.
على سبيل المثال :
- أدخل المستخدم القيمة 5 ثم القيمة 0
- سوف يتم حفظ القيمة 5 فى head ويجعل head تشير إلى NULL
- ألا تلاحظوا أن هناك نود تم حجز مساحة لها ولكن لن يتم إستخدامها .
- ويمكن إستخدام p->next=NULL فى الكود الأول ولكن هذا يعنى إضافة النود لل list ولكن هذة النود لن تحتوى على بيانات .
وبالنسبة للفرق بين إستخدام p->next!=NULL و p!=NULL فى دالة الطباعة كشرط لحلقة while:
فالأولى لن تعرض جميع القيم داخل list ولكن تعرض أقل من عدد عناصر ال list بمقدار 1 أى لن تعرض قيمة أخر node .
ولكن إستخدام الثانية سوف يعرض جميع بيانات ال nodes الموجودة داخل ال list
لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق
لا إله إلا أنت سبحانك إني كنت من الظالمين
ahmedsaoud31 كتب:السلام عليكم
أخ محمد لا فرق بين الكودين السابقين فكلاهما ينهى القائمة ويجعل أخر نود تشير إلى NULL
عزيزي ahmedsaoud31 ليتك تمهلت قليلاً قبل أن تحكم على الكودين بأنهما متشابهان دون أن تعمل لهما debug حتى !!!! و هل لاحظت أن الكود الثاني لا يسبب runtime error ؟؟؟ لا أعتقد !!
ahmedsaoud31 كتب:ولكن كلاكما لم تحررا الذاكرة المحجوزة لأخر نود أى توجد نود محجوزة غير مستخدمة.
المشكلة ليست بسبب عدم تحرير المساحة المحجوزة و لكن التحرير هو الأصح :
if(n==0)
{
delete tmp->next;
tmp->next = NULL;
break;
}طيب ممكن سؤال ,
الكود مكتوب باستخدام ADT او بدونه ..؟
السلام عليكم
اقتباسعزيزي ahmedsaoud31 ليتك تمهلت قليلاً قبل أن تحكم على الكودين بأنهما متشابهان دون أن تعمل لهما debug حتى !!!! و هل لاحظت أن الكود الثاني لا يسبب runtime error ؟؟؟ لا أعتقد !!
فعلاً أنا لم أجرب الكود وببساطة لأنى لم أتعامل مع لغة ++c ولكن تتبعت مسار الكودين ولم ألاحظ إلا عدم تحرير الذاكرة فقط بينما عاودت تتبعهما الآن وإتضح لى لماذا إستخدمت أنت المتغير tmp لحفظ القيمة السابقة للنود ونسيت أنا المتغير p فى الكود الأول هو متغير محلى ينتهى بإنتهاء الدالة .
وبالتالى أخر نود فى الكود الأول أصبحت تشير لمؤشر به قيمة NULL لم يعد موجود بالذاكرة ؟ وهذا تفسيرى لما حدث من runtime error ؟ وعلى هذا أيضاً ستشير أخر نود لمؤشر به قيمة NULL وليس لل NULL مباشراً .
عذراً على التسرع فى الرد دون تدقيق أكثر ... الخطأ عندى أنا ... وشاكراً لك ردك الجميل أخى الكريم
لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق
لا إله إلا أنت سبحانك إني كنت من الظالمين
ahmedsaoud31 كتب:عذراً على التسرع فى الرد دون تدقيق أكثر ... الخطأ عندى أنا ... وشاكراً لك ردك الجميل أخى الكريم
لا عليك أخي العزيز
hayatech كتب:طيب ممكن سؤال ,
الكود مكتوب باستخدام ADT او بدونه ..؟
هذا الكود بدون ADT
عليك بهذا الـــرابــط للمزيد حول الـ abstract data type
طيب هل يمكنكم اعادة صياغة الكود باستخدام ADT >>?
شكرا لكم جزاكم الله كل خير
شكرا اخي الفاضل محمد وليد
تعني انك استخدمت tmp للنود السابقة للـp بحيث تنهي القائمة وذلك لتعذر الـp عن انهاء القائمة لانها ستخرج عن اخر نود ؟؟
هذا التعديل مع اضافة بعض العمليات ولاحظ انني استخدمت فيها الشرط ولم يسبب مشاكل كما حصل في دالة CreatList
ارجو ان تتطلع عليه وتعطيني رايك
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
};
void CreatList (node *p)
{
int n;
node *tmp=NULL;
for(;;)
{
cout<<"Enter the value\n";
cin>>n;
if(n==0)
{ tmp->next = NULL;
break;
}
else
{
p->data=n;
p->next=new node;
tmp = p;
p=p->next;
}
}
}
void PrintList(node *p)
{
while(p!=NULL)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int CountList(node *p){
int count=0;
while (p!=NULL)
{
count++;
p=p->next;
}
return count;
}
node *isertatbeganing(node *p){
int num;
cout<<"Enter the value you want to insert at beganing:\n";
cin>>num;
node *newnode=new node;
newnode->data=num;
newnode->next=p;
return newnode;
}
void inseratloc(node *p,int loc){
int num;
node *locadd,*temp;
locadd=NULL;
while(p!=NULL)
{
if(p->data==loc)
{
locadd=p;
break;
}
else
p=p->next;
}
if(locadd==NULL)
cout<<"not found\n";
else
{
cout<<"Enter value to isert it:\n";
cin>>num;
node *newnode=new node;
newnode->data=num;
temp=p->next;
p->next=newnode;
newnode->next=temp;
}
}
node *deletenode(node *p,int key){
node *start,*temp;
start=p;
while(p!=NULL)
{
if(p->data==key)
if(start==p)
return start->next;
else
{
temp->next=p->next;
delete p;
return start;
}
else
{
temp=p;
p=p->next;
}
}
cout<<"not found "<<key<<endl;
return start;
}
void main (){
int loc,key,choice,n;
char answer;
node *head=new node;
cout<<"1. to creat list\n"
<<"2. to print list\n"
<<"3. to counting list\n"
<<"4. to add at beganing\n"
<<"5. to add at any location\n"
<<"6. to delet any node\n";
cout<<"want to try (y/n)\n";
cin>>answer;
while(answer=='Y'||answer=='y')
{
cout<<"Enter your choise:\n";
cin>>choice;
switch(choice)
{
case 1:CreatList(head);
break;
case 2:cout<<"linked lists nodes are:\n";
PrintList(head);
break;
case 3:n=CountList(head);
cout<<"number of node "<<n<<endl;
break;
case 4:head=isertatbeganing(head);
break;
case 5:cout<<"Enter value you want to inser after it:\n";
cin>>loc;
inseratloc(head,loc);
break;
case 6:cout<<"Enter node value to delete it:\n";
cin>>key;
head=deletenode(head,key);
break;
default:cout<<"invalide choise\n";
}
cout<<"more ?(y/n)\n";
cin>>answer;
}
}اريد ان اضيف عليه بعد التعديلات ولكن بعد ان اتاكد من صحته
تم تعديل هذه المشاركة بواسطة المـــــاسة في 9 مارس 2012 في 22:32
أولاً :
تابع الإدخال في أي موضع لا يعمل بشكل صحيح :
لو أني أدخلت التالي :
43 44 45 46 47
و طلبت من البرنامج أن يضيف بعد الموضع الثالث فسيفشل لأن الكود غير صحيح فهو يختبر الـ data في النود و ليس الـ index
ثانياً نسيتي أن تراعي النقطة التي ذكرها أخي ahmedsaoud31 :
if(n==0)
{
delete tmp->next;
tmp->next = NULL;
break;
}ثالثاً عملية الاختيار من القائمة مملة جداً فيمكن لك أن تقللي من الأسئلة بعد كل اختيار و إليك تعديل مقترح :
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
};
void CreatList (node *p)
{
int n;
node *tmp=NULL;
for(;;)
{
cout<<"Enter the value. \n";
cin>>n;
if(n==0)
{
delete tmp->next;
tmp->next = NULL;
break;
}
else
{
p->data = n;
p->next = new node;
tmp = p;
p = p->next;
}
}
}
void PrintList(node *p)
{
while(p!=NULL)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
system("pause >nul");
}
int CountList(node *p){
int count=0;
while (p!=NULL)
{
count++;
p=p->next;
}
return count;
}
node *isertatbeganing(node *p){
int num;
cout<<"Enter the value you want to insert at beganing:\n";
cin>>num;
node *newnode=new node;
newnode->data=num;
newnode->next=p;
return newnode;
}
void inseratloc(node *p,int loc)
{
int num;
node *locadd,*temp;
locadd=NULL;
while(p!=NULL)
{
if(p->data==loc)
{
locadd=p;
break;
}
else
p=p->next;
}
if(locadd==NULL)
cout<<"not found\n";
else
{
cout<<"Enter value to insert it:\n";
cin>>num;
node *newnode=new node;
newnode->data=num;
temp=p->next;
p->next=newnode;
newnode->next=temp;
}
}
node *deletenode(node *p,int key)
{
node *start,*temp;
start = p;
while(p!=NULL)
{
if(p->data==key)
if(start==p)
return start->next;
else
{
temp->next = p->next;
delete p;
return start;
}
else
{
temp=p;
p=p->next;
}
}
cout << "not found " << key << endl;
return start;
}
void main (){
int loc,key,choice,n;
node *head=new node;
while(true)
{
system("cls");
cout<<"1. to creat list\n"
<<"2. to print list\n"
<<"3. to counting list\n"
<<"4. to add at beganing\n"
<<"5. to add at any location\n"
<<"6. to delet any node\n"
<<"7. to Exit\n";
cout<<"Enter your choise:\n";
cin>>choice;
switch(choice)
{
case 1:
system("cls");
CreatList(head);
break;
case 2:
system("cls");
cout<<"linked lists nodes are:\n";
PrintList(head);
break;
case 3:
system("cls");
n = CountList(head);
cout<<"number of node "<<n<<endl;
system("pause >nul");
break;
case 4:
system("cls");
head = isertatbeganing(head);
break;
case 5:
system("cls");
cout<<"Enter value you want to insert after it:\n";
cin>>loc;
inseratloc(head,loc);
break;
case 6:
system("cls");
cout<<"Enter node value to delete it:\n";
cin>>key;
head=deletenode(head,key);
break;
case 7:goto end;
break;
default:cout<<"invalide choise\n";
}
}
end:;
}ملاحظة : يمكن أن يتم طباعة الليست بعد كل تعديل بدلاً من أن يكون خيار الطباعة منفصلاً .
كل الشكر لك اخي الفاضل على ملاحظاتك
ساقوم بالتعديل
اريد التعديل على دالة الانشاء بحيث اذا تم ادخال الصفر باول القائمة تصبح فارغة حاولت ذلك ولكن يعطيني خطا بالتنفيذ
السلام عليكم
من الأفضل فصل دالة إدخال البيانات من المستخدم عن دالة إدراج النود داخل ال list لتلاشى هذا الخطأ بسهولة .
لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق
لا إله إلا أنت سبحانك إني كنت من الظالمين
كل الشكر لك
ساحاول فيه وارد لكم بالتعديل
ارجو ان تعذروني اليومين القادمين
السلام عليكم
أنا قمت بتهيئة مترجم لغة سي++ لأرى الخطأ الذى أشار إليه الأخ محمد فى المشاركة وفعلاً كان خطأ بسبب والوصول لعناوين ليست من حق البرنامج أثناء التشغيل , كما تحدثت عنه فى المشاركات السابقة .
وأيضاً سبب المشكلة الحالية عند إدخال قيمة صفر كأول قيمة يتم التوجه مباشراً إلى كود تحرير الذاكرة للمؤشر الذى يشير إليه المتغير tmp الذى لم يتم حجز مساحة له بعد ليقوم بحزفها . وهذه تعتبر عملية وصول لمتغير لم يتم تهيئته بعد فتصبح عملية غير مشروعة ينتج عنها ما يعرف بخطأ أثناء التشغيل .
فالحل الأفضل فصل دالة الإدخال عن دالة ربط النود بالقائمة list .
وإن أردت التعديل على نفس الدالة لتلاشى الخطأ فيكون عن طريق قرأه القيمة الأولى المدخلة من المستخدم خارج الدوران الخاص بحلقة for فإن كانت القيمة غير مساوية للصفر يقوم بالدخول للحلقة وإن كانت تساوى صفر لا يتم الدخول للحلقة من البداية , مع ملاحظة تحويل كود القرأه cin من بداية الحلقة لنهايتة لتفادى قرأه قيمتين متتاليتين .
عمداً قصدت عدم كتابة الكود ... وإكتفيت بالشرح النظرى لخلق مجال من التفكير فربما تكون لديك أفكار أفضل للتغلب على المشكلة .
لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق
لا إله إلا أنت سبحانك إني كنت من الظالمين
قبل أن أناقش الحلول هذا أحد التحسينات على بنية المعطيات ( تزويد الباني ( constructor ) بقيم إفتراضية ):
struct node{
int data;
node *next;
node():next(NULL),data(0){}
};إليك أحد الحلول الممكنة و التي أشار إليها أخي أحمد :
void CreatList (node *p)
{
bool first = true;
int n;
node *tmp=NULL;
for(;;)
{
cout<<"Enter the value\n";
cin>>n;
if(n==0)
{
if ( !first )
tmp->next = NULL;
break;
}
else
{
p->data=n;
p->next=new node ;
tmp = p;
p=p->next;
first = false ;
}
}
}اقتباسفالحل الأفضل فصل دالة الإدخال عن دالة ربط النود بالقائمة list .
هل هذا ما قصدته أخي :
node* getNode()
{
node* tmp;
int n;
cout << "Enter the value. \n";
cin >> n;
if ( n != 0 )
{
tmp = new node;
tmp->data = n;
}
else
tmp = NULL;
return tmp;
}
void CreatList (node* p)
{
cout << "Enter the value. \n";
cin >> p->data;
if ( p->data != 0 )
do
{
p->next = getNode();
p = p->next;
} while ( p != NULL );
}