Вывести на экран элементы, для которых сумма двух предыдущих элементов меньше двух следующих
Есть задания: а) Вывести на экран элементы, для которых сумма двух предыдущих элементов меньше двух следующих. А также вывести на экран эти суммы (код ниже, не выполняется) б) Вывести на экран элементы, для которых в списке предыдущих элементов количество парных равно количеству парных в списке следующих элементов.(хотелось бы посмотреть на алгоритм выполнения)
Касательно вопроса а), код:
void sumaparnyh(Tnum*& Start) {
Tnum* wp, * pp, * xt;//xt=next-cлед.
int right, left, right1, left1;//числовые значения левого и правого соседа тек. элем.
wp = Start;
pp = NULL;
xt = NULL;
while (wp != NULL) {
pp = wp->prev;
xt = wp->next;
if ((wp->next == wp->prev) && (wp->next == NULL)) {
cout << "Only one element in list" << endl;
break;
}
if (xt->next == NULL)
right1 = 0;
else right1 = xt->next->num;
if (wp->next == NULL)
right = 0;
else right = wp->next->num;
if (pp->prev == NULL)
left1 = 0;
else left1 = pp->prev->num;//если поставить точки остановы, то тут появляется картинка 1
if (wp->prev == NULL)
left = 0;
else left = wp->prev->num;
if (left + left1 < right + right1) {
cout << "For " << wp->num << ": " << " summ of neighbor left " << left + left1 << " less than neigbor right" << right + right1 << endl;
}
pp = wp;
wp = wp->next;
xt = xt->next;
}
}
Работаю с двусвязным списком рандомных чисел.
Крашится до выполнения. Ошибок код не выдает. В чем проблема?
На выходе должны получится числа: элементы, у которых сумма предыдущих меньше, чем сумма следующих; эти же суммы.
Заранее спасибо за помощь!
Код всей программы:
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
typedef
struct Num {
int num;
Num* prev;
Num* next;
}Tnum;
void createRandList(Tnum*& Start, int cnt);
void addToEnd(Tnum*& Start, Tnum* PNew);
void addToSort(Tnum*& Start, Tnum* PNew);
void showList(Tnum*& Start);
void showControlOutputDbList(Tnum*& Start);
void delEl(Tnum*& Start);
void delList(Tnum*& Start);
int findPos(Tnum*& Start);
void dillnapyat(Tnum*& Start);
void dillnatri(Tnum*& Start);
void sumaparnyh(Tnum*& Start);
Tnum* Start;
void add(Tnum*& Start);
void createRandList(Tnum*& Start, int cnt)
{
Tnum* PNew;
srand(time(NULL));
for (int i = 1; i <= cnt; i++)
{
PNew = new Tnum;
PNew->num = rand() % 100;
addToSort(Start, PNew);
}
}
void addToEnd(Tnum*& Start, Tnum* PNew)
{
Tnum* wp;
PNew->next = NULL;
PNew->prev = NULL;
if (Start == NULL)
{
Start = PNew;
return;
}
wp = Start;
while (wp->next != NULL)
{
wp = wp->next;
}
wp->next = PNew;
PNew->prev = wp;
}
void addToSort(Tnum*& Start, Tnum* PNew)
{
Tnum* wp, * pp;
PNew->next = NULL;
PNew->prev = NULL;
pp = NULL;
wp = Start;
while ((wp != NULL) && (PNew->num > wp->num))
{
pp = wp;
wp = wp->next;
}
if (pp == NULL)
{
PNew->next = Start;
if (Start != NULL)
{
Start->prev = PNew;
}
Start = PNew;
}
else
{
pp->next = PNew;
PNew->prev = pp;
if (wp != NULL)
{
wp->prev = PNew;
PNew->next = wp;
}
}
}
void showList(Tnum*& Start)
{
Tnum* wp = Start;
while (wp != NULL)
{
cout << wp->num << " ";
wp = wp->next;
}
}
void showControlOutputDbList(Tnum*& Start)
{
Tnum* wp, * pp;
wp = Start;
pp = NULL;
while (wp != NULL)
{
cout << wp->num << " ";
pp = wp;
wp = wp->next;
}
cout << endl;
wp = Start;
while (pp != NULL)
{
cout << pp->num << " ";
pp = pp->prev;
}
cout << endl;
}
void delEl(Tnum*& Start)
{
int result = findPos(Start);
Tnum* POld, * Prev, * Next;
POld = Start;
if (result > -1) {
while (POld->num != result)
{
POld = POld->next;
}
Prev = POld->prev;
Next = POld->next;
if (Start == POld)
{
Start = Next;
Start->prev = NULL;
}
else if (POld->next == NULL) {
Prev->next = NULL;
}
else
{
Prev->next = Next;
Next->prev = Prev;
}
delete POld;
}
else {
cout << "Number wasn`t finded. You entered wrong number" << endl;
}
}
void delList(Tnum*& Start)
{
Tnum* POld;
while (Start != NULL)
{
POld = Start;
Start = Start->next;
delete POld;
}
}
int findPos(Tnum*& Start) {
int num;
cin >> num;
Tnum* wp = Start;
int pos = -1;
while (wp != NULL) {
if (wp->num == num) {
pos = num;
return pos;
}
wp = wp->next;
}
}
void dillnapyat(Tnum*& Start) {
if (Start == NULL) {
return;
}
Tnum* wp;
wp = Start;
while (wp != NULL)
{
if (wp->num % 5 == 0)
{
if (wp->next == NULL)
{
wp->prev->next = NULL;
}
if (wp->next != NULL)
{
wp->prev->next = wp->next;
wp->next->prev = wp->prev;
}
}
wp = wp->next;
}
delete wp;
}
void dillnatri(Tnum*& Start) {
Tnum* wp = Start;
while (wp != NULL) {
if (wp->num % 3 == 0 && wp->num >= 3) {
if (wp->next == NULL) {
Tnum* New = new Tnum;
New->num = 10;
New->next = NULL;
New->prev = wp;
wp->next = New;
}
else {
Tnum* New = new Tnum;
New->num = 10;
New->next = wp->next;
New->prev = wp;
wp->next = New;
}
}
wp = wp->next;
}
}
/*void parnielementy(Tnum*&Start); это пункт б в моем вопросе, не готовый */
void sumaparnyh(Tnum*& Start) {
Tnum* Left1, * Left, * Current, * Right, * Right1;
int LeftSumm, RightSumm;
Current = Start;
if (Current->next == NULL)
{
cout << "Only one element in list" << endl;
return;
}
else
while (!Current) // то же самое, что (Current!=NULL)
{
Left = Current->prev;
if (Left != NULL)
{
Left1 = Left->prev;
}
Right = Current->next;
if (Right != NULL)
{
Right1 = Right->next;
}
// теперь здесь у вас указатели на 5 элементов списка
// Если указатель == NULL, значит узла не существует
// Дальше работаете со значениями узлов с предварительной проверкой указателей на NULL
LeftSumm = 0;
RightSumm = 0;
if (!Left) // (Left != NULL)
{
LeftSumm += Left->num;
if (!Left1)//Ошибка C4703 используется потенциально неинициализированная локальная переменная-указатель "Left1"
{
LeftSumm += Left1->num;
}
}
if (!Right)
{
RightSumm += Right->num;
if (!Right1)//Ошибка C4703 используется потенциально неинициализированная локальная переменная-указатель "Right1"
{
RightSumm += Right1->num;
}
}
Current = Current->next;
if (LeftSumm < RightSumm) {
cout << "For " << Current->num << ": " << " summ of neighbor left " << LeftSumm << " less than neigbor right" << RightSumm << endl;
}
else cout << "Not found." << endl;
}
}
void intList(Tnum*& Start) {
Start = NULL;
}
int main()
{
char ch;
cout << "Choose operation with the list: \n";
cout << "0. Fill the list with the random numbers\n";
cout << "1. Show the list\n";
cout << "2. Show the list in the forward and reverse order\n";
cout << "3. Add element to the end of the list\n";
cout << "4. Display elements, for which amount of previous paired elements equal amount of other paired elements\n";
cout << "5. After all elements, which /3 paste 10\n";
cout << "6. Delete list\n";
cout << "7. Delete element\n";
cout << "Protecting lab3: \n";
cout << "8. Delete all elemets /5 \n";
cout << "9. Display element, summ of neighbors of wich less summ next two. Show summ of this elements too\n";
cout << "=============================================================================" << endl;
do {
cout << "\nEnter the number [0-9]: ";
cin >> ch;
switch (ch) {
case '0': {int cnt;
cout << "Enter the amount of elemetns: ";
cin >> cnt;
cout << endl;
createRandList(Start, cnt);
showList(Start); } break;
case '1': showList(Start); break;
case '2': showControlOutputDbList(Start); break;
case '3': add(Start); break;
/*case '4': parnielementy(Start);break; пункт б*/
case '5': dillnatri(Start); break;
case '6': {delList(Start); break;
cout << "List deleted." << endl; }break;
case '7': delEl(Start); break;
case '8': dillnapyat(Start); break;
case '9': sumaparnyh(Start); break;
}
} while (true);
return 1;
}
void add(Tnum*& Start) {
Tnum* PNew = new Tnum;
cout << "You're going to add new number to the list. Number: "<<endl;
cin >> PNew->num;
addToEnd(Start, PNew);
showList(Start);
}
Ответы (3 шт):
Вообще лучше привести весь текст программы. Т.к. ошибки могут быть и при заполнении списка. Но если сделать анализ по-быстрому, допустив что первоначальное формирование списка без ошибок, косячков много конечно.
- Зачем передавать в функцию указатель на ссылку (Tnum*& Start)? Я думаю, вы сами не понимаете смысл этой записи. Достаточно указателя.
- Проверку на 1 элемент в списке можно сделать один раз перед циклом, в самом начале.
- Проверка на 1 элемент в списке достаточно проверить на ноль указатель на следующий элемент и всё. В функцию передается указатель на начало списка, так? Если следующего элемента нет, значит список из 1 элемента:
wp = Start;
if (wp->next == NULL)
{
cout << "Only one element in list" << endl;
return;
}
- Крах программы из-за того, что вы обращаетесь по нулевому указателю. Нигде не проверяется указатели wp->prev и wp->next на NULL при переприсваивании. Если из цикла убрать ифы с подсчетом сумм значений, оставить только арифметику указателей, то получится:
while (wp != NULL)
{
pp = wp->prev;
xt = wp->next;
... // здесь идет обращение по указателям
pp = wp; // строчка бессмысленна, т.к. в начале цикла идет переопределение
wp = wp->next;
xt = xt->next; // строчка бессмысленна, т.к. в начале цикла идет переопределение
}
Т.е. если текущий элемент wp первый в списке, то pp становится равен NULL если текущий элемент wp последний в списке, xt становится равен NULL и дальше идет обращение pp->prev или xt->next, т.е. неизвестно куда.
while (wp != NULL)
{
pp = wp->prev; // если wp первый элемент, то pp == NULL
xt = wp->next; // если wp последний элемент, то xt == NULL
if ( pp->prev == NULL ) // вот здесь идет обращение в никуда
left1 = 0;
if ( xt->next == NULL ) // вот здесь идет обращение в никуда
right1 = 0;
Хотя бы визуально отделите арифметику указателей от вычисления сумм. А ещё проще на каждом шаге цикла не проходить опять по указателям, а хранить в переменных (или массиве) значения 5 узлов списка и сдвигать их. Тогда на каждом шаге цикла нужно будет получить только 1 значение узла списка - самого правого (текущий+2).
У вас 2 указателя на предыдущие и 2 на последующие узлы списка. Их все нужно проверять на NULL. Для предыдующих:
if ( pp == NULL )
if ( pp->prev == NULL )
А для понимания механики процесса попробуйте сначала хранить указатели в отдельных переменных. И назовите их осмысленно. Также в самом начале помогает рисовать на бумаге, если не получается держать в голове. :) Например:
Tnum *Left1, *Left, *Current, *Next, *Next1; // указатели на 2 предыдущих, текущий и 2 следующих узла
int LeftSumm, RightSumm;
while(!Current) // то же самое, что (Current!=NULL)
{
Left = Current->prev;
if(Left != NULL)
{
Left1 = Left->prev;
}
Right = Current->next;
if( Right != NULL )
{
Right1 = Right->next;
}
// теперь здесь у вас указатели на 5 элементов списка
// Если указатель == NULL, значит узла не существует
// Дальше работаете со значениями узлов с предварительной проверкой указателей на NULL
LeftSumm = 0;
RightSumm = 0;
if(!Left) // (Left != NULL)
{
LeftSum += Left->num;
if(!Left1)
{
LeftSum += Left1->num;
}
}
...
Current = Current->next;
}
Вот так проверил - работает.
Поскольку Start - глобальная переменная, нет необходимости передавать её в параметрах функций.
Чтобы избавиться от закомментированных ошибок при инициализации указателей обнулите их.
И строка Current = Current->next; должна быть последней в теле цикла. Потому что это переход на следующий элемент списка.
Tnum* Start = NULL;
void createRandList(int cnt)
{
Tnum* PNew;
srand(time(NULL));
for (int i = 1; i <= cnt; i++)
{
PNew = new Tnum;
PNew->num = rand() % 100;
addToSort(PNew);
}
}
void showList(Tnum* Start)
{
Tnum* wp = Start;
while (wp != NULL)
{
cout << wp->num << " ";
wp = wp->next;
}
cout << endl;
}
void delList(Tnum*& Start)
{
Tnum* POld, *wp;
wp = Start;
while (wp != NULL)
{
POld = wp;
wp = wp->next;
delete POld;
}
Start = NULL;
}
void sumaparnyh(Tnum* Start)
{
Tnum *Left1=NULL, *Left, *Current, *Right, *Right1=NULL;
int LeftSumm, RightSumm;
Current = Start;
if (Current->next == NULL)
{
cout << "Only one element in list" << endl;
return;
}
while (Current!=NULL)
{
Left = Current->prev;
if (Left != NULL)
{
Left1 = Left->prev;
}
Right = Current->next;
if (Right != NULL)
{
Right1 = Right->next;
}
LeftSumm = 0;
RightSumm = 0;
if (Left != NULL)
{
LeftSumm += Left->num;
if (Left1 != NULL)
{
LeftSumm += Left1->num;
}
}
if (Right != NULL)
{
RightSumm += Right->num;
if (Right1 != NULL)
{
RightSumm += Right1->num;
}
}
if (LeftSumm < RightSumm) {
cout << "For " << Current->num << ": " << " summ of neighbor left " << LeftSumm << " less than neigbor right " << RightSumm << endl;
}
else cout << "Not found." << endl;
Current = Current->next;
}
}
int main()
{
createRandList(10);
showList( Start );
sumaparnyh( Start );
delList( Start );
return 0;
}
