Удалить из списка все элементы, большие среднего арифметического - C (СИ)
Формулировка задачи:
Здравствуйте.
Задача такая:Написать программу по созданию, просмотру, добавлению и решению поставленной задачи для двунаправленного линейного списка. Создать список из случайных целых чисел. Удалить из списка все элементы, большие среднего арифметического.
Как работать со структурой такого типа я похоже понял, написал алгоритм, функции по созданию, удалению.
Теперь суть проблемы: при построении решения ошибок не выдает. В процессе выполнения пункта меню 4 (Удалить из списка все элементы, большие среднего арифметического.) выбрасывает и выдает ошибку: Unhandled exception at 0x01321c54 in Alexey.exe: 0xC0000005: Access violation reading location 0x00000008.
Я написал цикл вайлом (те while(t!=NULL)). Как я понимаю как только мой указатель выйдет за список, он укажет в NULL. Соответственно это будет последняя итерация и больше в вайл не войдет. При пошаговой отладке видно, что он проходит 11 раз (я сделал 11 псевдорандомных элементов). Удаляет все элементы, которые больше среднего арифметического и на 11 итерации естественно t уже смотрит в NULL (t=t->Next). Это видно и в окне переменных. Но на 12 итерацию происходит попадание в вайл, уже удалять нечего, т.к. все уже удалено, и по тексту следует t=t->Next;. Которое уже итак смотрит в никуда и тут компилятор выдает ошибку.
Надеюсь, моя проблема ясна. Прошу помощи у знающих - что я делаю не так. Так же может быть по остальному тексту что-то режет глаз, тк я новичок. MS VS2010. Код ниже. Спасибо.
//Написать программу по созданию, просмотру, добавлению и решению поставленной задачи для двунаправленного линейного списка.
//13. Создать список из случайных целых чисел. Удалить из списка все элементы, большие среднего арифметического.
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<math.h>
struct Spis
{
int info;
Spis *Prev,*Next;
};
Spis*begin,*end,*t;
int menu();
void View(Spis*begin); //просмотр списка
Spis* Create(Spis**begin,Spis**end); //создание списка
Spis* Add(Spis**begin,Spis**end); //добавление элемента
void Del(Spis**begin); //удаление списка
void DelMaxMid(Spis*begin); //Удалить из списка все элементы, большие среднего арифметического
void main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int menu1;
do
{
menu1=menu();
switch(menu1)
{
case 1: //1 - создать список из случайных целых чисел
{
begin=Create(&begin,&end);
break;
}
case 2: //2 - просмотр списка
{
View(begin);
break;
}
case 3: //3 - добавление элементов списка
{
begin=Add(&begin,&end);
break;
}
case 4: //4 -Удалить из списка все элементы, большие среднего арифметического
{
DelMaxMid(begin);
break;
}
case 5:
{
Del(&begin);
if(begin==NULL)
puts("Проверено! ");
_getch();
}
}
}while(menu1!=5);
}
int menu()// меню по созданию, просмотру, добавлению и решению поставленной задачи
{
int enter;
printf("\t\tМЕНЮ ПРОГРАММЫ\n");
printf("\t1 - создать список из случайных целых чисел в диапазоне от 1 до 10\n");
printf("\t2 - просмотр списка\n");
printf("\t3 - добавление элементов списка\n");
printf("\t4 - yдалить из списка все элементы, большие среднего арифметического\n");
printf("\t5 - выход\n");
printf("___________________________________________________________________________\n");
printf("Введите пункт меню: ");
scanf("%d",&enter);
return enter;
}
Spis* Create(Spis**begin,Spis**end)
{
*begin=NULL;
Spis*t=(Spis*)malloc(sizeof(Spis));
t->info=rand()%10;
t->Prev=NULL;
t->Next=NULL;
*begin=*end=t;
for(int i=0;i<10;i++)
{
t=(Spis*)malloc(sizeof(Spis));
t->info=rand()%10;
t->Prev=NULL;
t->Next=*begin;
(*begin)->Prev=t;
*begin=t;
}
printf("\n\tСписок создан\n\n");
return t;
}
void View(Spis*begin)
{
t=begin;
while(t!=NULL)
{
printf("%d\n",t->info);
t=t->Next;
}
}
Spis* Add(Spis**begin,Spis**end)
{
t=(Spis*)malloc(sizeof(Spis));
printf("\n\n Введите значение для добавления: ");
scanf("%d",&t->info);
t->Prev=NULL;
t->Next=*begin;
(*begin)->Prev=t;
*begin=t;
return t;
}
void Del(Spis**begin)
{
Spis*t=*begin;
while(*begin!=NULL)
{
t=*begin;
*begin=(*begin)->Next;
free(t);
}
puts("Память очищена");
}
void DelMaxMid(Spis*begin) //Удалить из списка все элементы, большие среднего арифметического
{
Spis*key=NULL;
int q_namber=0,summ=0; //количество элементов
double s_ar; //среднее арифметическое
t=begin;
while(t!=NULL)
{
q_namber++;
summ+=t->info;
t=t->Next;
}
s_ar=(double)summ/q_namber;
printf("\nСреднее арифметическое: %0.2lf\n",s_ar);
t=begin;
while(t!=NULL)
{
t=begin;
while(t!=NULL) //иду по списку, пока не найду тот эл-т, который больше s_ar; //среднее арифметическое
{
if(t->info>s_ar)
{
key=t;
break;
}
t=t->Next;
}
if(key!=NULL) //cамо удаление из списка
{
if(key==begin) //если элемент расположен в начале
{
begin=begin->Next;
begin->Prev=NULL;
}
else
{
if(key==end) //если он в конце
{
end=end->Prev;
end->Next=NULL;
}
else //или в "теле"
{
(key->Prev)->Next=key->Next;
(key->Next)->Prev=key->Prev;
}
}
free(key); //затираю память
key=NULL;
}
else
t=t->Next;
}
}Решение задачи: «Удалить из списка все элементы, большие среднего арифметического»
textual
Листинг программы
//Написать программу по созданию, просмотру, добавлению и решению поставленной задачи для двунаправленного линейного списка.
//13. Создать список из случайных целых чисел. Удалить из списка все элементы, большие среднего арифметического.
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<math.h>
struct Spis
{
int info;
Spis *Prev,*Next;
};
Spis*begin,*end,*t;
int menu();
void View(Spis*begin); //просмотр списка
Spis* Create(Spis**begin,Spis**end); //создание списка
Spis* Add(Spis**begin,Spis**end); //добавление элемента
void Del(Spis**begin); //удаление списка
void DelMaxMid(Spis*begin); //Удалить из списка все элементы, большие среднего арифметического
void main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int menu1;
do
{
menu1=menu();
switch(menu1)
{
case 1: //1 - создать список из случайных целых чисел
{
begin=Create(&begin,&end);
break;
}
case 2: //2 - просмотр списка
{
View(begin);
break;
}
case 3: //3 - добавление элементов списка
{
begin=Add(&begin,&end);
break;
}
case 4: //4 -Удалить из списка все элементы, большие среднего арифметического
{
DelMaxMid(begin);
break;
}
case 5:
{
Del(&begin);
if(begin==NULL)
puts("Проверено! ");
_getch();
}
}
}while(menu1!=5);
}
int menu()// меню по созданию, просмотру, добавлению и решению поставленной задачи
{
int enter;
printf("\t\tМЕНЮ ПРОГРАММЫ\n");
printf("\t1 - создать список из случайных целых чисел в диапазоне от 1 до 10\n");
printf("\t2 - просмотр списка\n");
printf("\t3 - добавление элементов списка\n");
printf("\t4 - yдалить из списка все элементы, большие среднего арифметического\n");
printf("\t5 - выход\n");
printf("<br>\n");
printf("Введите пункт меню: ");
scanf("%d",&enter);
return enter;
}
Spis* Create(Spis**begin,Spis**end)
{
*begin=NULL;
Spis*t=(Spis*)malloc(sizeof(Spis));
t->info=rand()%10;
t->Prev=NULL;
t->Next=NULL;
*begin=*end=t;
for(int i=0;i<10;i++)
{
t=(Spis*)malloc(sizeof(Spis));
t->info=rand()%10;
t->Prev=NULL;
t->Next=*begin;
(*begin)->Prev=t;
*begin=t;
}
printf("\n\tСписок создан\n\n");
return t;
}
void View(Spis*begin)
{
t=begin;
while(t!=NULL)
{
printf("%d\n",t->info);
t=t->Next;
}
}
Spis* Add(Spis**begin,Spis**end)
{
t=(Spis*)malloc(sizeof(Spis));
printf("\n\n Введите значение для добавления: ");
scanf("%d",&t->info);
t->Prev=NULL;
t->Next=*begin;
(*begin)->Prev=t;
*begin=t;
return t;
}
void Del(Spis**begin)
{
Spis*t=*begin;
while(*begin!=NULL)
{
t=*begin;
*begin=(*begin)->Next;
free(t);
}
puts("Память очищена");
}
void DelMaxMid(Spis*begin) //Удалить из списка все элементы, большие среднего арифметического
{
Spis*key=NULL;
int q_namber=0,summ=0; //количество элементов
double s_ar; //среднее арифметическое
t=begin;
while(t!=NULL)
{
q_namber++;
summ+=t->info;
t=t->Next;
}
s_ar=(double)summ/q_namber;
printf("\nСреднее арифметическое: %0.2lf\n",s_ar);
t=begin;
while(t!=NULL)
{
t=begin;
while(t!=NULL) //иду по списку, пока не найду тот эл-т, который больше s_ar; //среднее арифметическое
{
if(t->info>s_ar)
{
key=t;
break;
}
t=t->Next;
}
if(key!=NULL) //cамо удаление из списка
{
if(key==begin) //если элемент расположен в начале
{
begin=begin->Next;
begin->Prev=NULL;
}
else
{
if(key==end) //если он в конце
{
end=end->Prev;
end->Next=NULL;
}
else //или в "теле"
{
(key->Prev)->Next=key->Next;
(key->Next)->Prev=key->Prev;
}
}
free(key); //затираю память
key=NULL;
}
else
t=t->Next;
}
}
Объяснение кода листинга программы
- Создание списка из случайных целых чисел в диапазоне от 1 до 10 выполняется в функции
Create(Spis**begin,Spis**end). - Просмотр списка осуществляется в функции
View(Spis*begin). - Добавление элемента в список выполняется в функции
Add(Spis**begin,Spis**end). - Удаление списка выполняется в функции
Del(Spis**begin). - Удаление всех элементов списка, больших среднего арифметического, выполняется в функции
DelMaxMid(Spis*begin).