#c
#c
Вопрос:
Я написал следующий код для списка ссылок, чтобы создать книгу с серийным номером и выполнить поиск по ней. Я использую в нем связанный список.
Когда я добавляю свою первую запись, она добавляется успешно, но когда я добавляю вторую запись, она показывает ошибку сегментации. Я не могу понять, почему. Пожалуйста, помогите.
Заранее спасибо.
Код:
#include<iostream>
#include<string>
#include<fstream>
#include<cstdlib>
using namespace std;
struct book
{
int accno;
string name;
book* next;
};
int main()
{
bool flag=false;
int x,m;
string s;
book* front=NULL;
book* n;
do
{
cout<<"nPlease select the following:n1.Create and appendn2.Searchn3.Exit";
cin>>m;
switch(m)
{
case 1:
n=new book();
cout<<"nEnter the book name: ";
cin>>s;
cout<<"nEnter the acc no.: ";
cin>>x;
if(front==NULL)
{
front=n;
}
else
{ n=front;
while(n->next!=NULL)
{
n=n->next;
}
n=n->next;
}
n->accno=x;
n->name=s;
break;
case 2:
cout<<"Enter the roll no.";
int y;
cin>>y;
if(front==NULL){cout<<"Doesnot existn"; break;
}
else
{
n=front;
while(n->accno!=y amp;amp; n->next!=NULL)
{
n->next=n;
}
cout<<"Book name is:"<<n->name;
cout<<"nAccno is: "<<n->accno;
}
break;
case 3: flag=true;
break;
}
}
while(flag==false);
return 0;
}
Комментарии:
1. это домашнее задание? Если это не так, используйте std::list вместо переопределения этого
2. «Я написал следующий код для списка ссылок»? Почему? Вы
using namespace std
: в нем есть множество подходящих контейнеров!
Ответ №1:
Здесь
while(n->next!=NULL)
{
n=n->next;
}
n=n->next;
вы перебираете связанный список, чтобы найти последний элемент, затем проходите мимо него. После этого n
будет null
.
Чего вам не хватает, так это создания нового элемента и добавления его в конец списка.
И вот
n->accno=x;
n->name=s;
вы также должны назначить n->next = null
, иначе ваш список не будет должным образом завершен.
Кроме того, при поиске книги здесь
while(n->accno!=y amp;amp; n->next!=NULL)
{
n->next=n;
}
cout<<"Book name is:"<<n->name;
cout<<"nAccno is: "<<n->accno;
после выхода из цикла либо вы нашли книгу, либо n
есть null
. Вы должны проверить, в чем дело, прежде чем пытаться разыменовать n, иначе вы снова получите ошибку segfault, если книги, которую вы ищете, нет в списке.
Комментарии:
1. каковы оставшиеся проблемы?
2. @Jan, Никто не сказал, что это так — проверьте мое обновление. И если вы видите еще больше проблем, не стесняйтесь указывать на них в своем собственном ответе.
3. Viraj указал на мою основную проблему. Как только я делаю n= front, я теряю указатель на новый узел, поэтому, когда front!=null, я фактически присваиваю значения null. Спасибо, ребята
4. @Разочарованный, это только часть проблемы. Даже если вы сохранили исходное значение
n
(например, используя другой указатель для обхода списка), вам все равно нужно добавить новый элемент в список, как я отметил выше.
Ответ №2:
- Научитесь писать связанные списки (так что, если это домашнее задание, нацеленное на их изучение, оно допустимо, но не помечено как таковое), но никогда не делайте этого на практике. Есть стандартная библиотека и есть boost, и у них есть все структуры данных, которые вам понадобятся, если вы не сделаете что-то действительно особенное.
- У вас C , так что не пишите код в стиле C.
book
должен быть конструктор, который должен инициализировать его элементы. Вероятно, заголовок списка также следует инкапсулировать в класс и манипулировать им с помощью его методов. - Вы никогда не устанавливаете n-> next, поэтому не удивляйтесь, что он никогда не содержит ничего значимого.
- Вы повторно используете
n
в цикле, забывая созданный вами объект (утечка памяти). - Тогда вы получите значение NULL в конце списка вместо созданного вами объекта.
Ответ №3:
в этом и заключается ваша проблема:
....
else
{
n=front;
while(n->next!=NULL) //access to next will cause seg fault!!!
{
n=n->next;
}
n=n->next; // step once more, now we have NULL on second add...
}
кроме того, где n->next
назначается? Я нигде этого не вижу?
Комментарии:
1. Помимо повторения существующего ответа, это не единственная проблема.
2. эй, после того, как я дойду до конца списка, я делаю n = n-> next, который переходит к нулевой записи. Теперь я устанавливаю его accno и имя
3. @Jan почему бы вам не дать нам ответ, вместо того, чтобы все время упоминать «другую проблему»…
4. @Разочарованный: да? зачем вам указывать регистрационный номер и имя нулевой записи? Я не слежу
5. @Tony: Я ее составлял. Просто мне потребовалось немного больше времени, чтобы упомянуть все проблемы.
Ответ №4:
Что ты здесь делаешь?
case 1:
n=new book();
cout<<"nEnter the book name: ";
cin>>s;
cout<<"nEnter the acc no.: ";
cin>>x;
if(front==NULL)
{
front=n;
}
else
{
n=front;
}
while(n->next!=NULL)
{
n=n->next;
}
n=n->next;
}
n->accno=x;
n->name=s;
break;
Вы создали новую книгу и присвоили ей n, в первом случае все в порядке, потому что вы напрямую назначаете ее front. Но в другом случае вам следует выполнить итерацию списка с использованием какой-либо другой переменной (temp), когда ваша запись n = front, вы уже потеряли указатель на объект new book. Надеюсь, вы получили свой ответ.
Комментарии:
1. значит, я должен использовать temp для итерации до конца связанного списка, а затем выполнить temp = n?
Ответ №5:
Это ошибочный код:
-
Вам нужно обнулить поле «next» при добавлении нового узла:
случай 1: новая книга(); n-> next = NULL; …
-
У вас утечка памяти