Я использую функцию для создания динамического массива с помощью MALLOC.
получение пользовательского ввода с использованием SCANF. по какой-то причине я получаю это заявление об ошибке:
** Необработанное исключение по адресу 0x00007FFEE518D646 (ucrtbased.dll) в Project4STRUCTS.exe: 0xC0000005: место записи нарушения прав доступа 0xFFFFFFFFCD7AE350.**
ПРОБЛЕМА В ФУНКЦИИ INPUT_DATA
#define _CRT_SECURE_NO_WARNINGS
#define SIZE 3
#include<stdio.h>
typedef struct student_init_data {
int ID;
int* StudentGradeArray;
int NumOfExams;
}Student_init_data;
typedef struct student_processed_data {
int ID;
int StudentAvg;
}Student_processed_data;
typedef struct statistics {
Student_processed_data* HIGH;
Student_processed_data* LOW;
int SizeofHIGH;
int SizeofLOW;
int Tavg;
}Statistics;
int* Input_Data(int Exams) {
int i;
int* arr = (int*)malloc(Exams * sizeof(int));
for (i = 0;i < Exams;i++)
{
printf("enter Grade: ");
scanf("%d", &arr[i]);
}
return arr;
}
int Student_Average(int* GradeArray,int NumofExams) {
int i;
int avg=0;
for (i = 0;i < NumofExams;i++)
avg = avg + GradeArray[i];
avg = avg / NumofExams;
return avg;
}
int Total_Average(Student_processed_data StudentAVG[SIZE], int NumofStudents) {
int i;
int avg = 0;
for (i = 0;i < NumofStudents;i++)
avg = avg + StudentAVG[i].StudentAvg;
avg = avg / NumofStudents;
return avg;
}
void Classification(Student_init_data InitStudentData[SIZE],Statistics *pStats) {
int i;
Student_processed_data StudentAVG[SIZE];
pStats->SizeofHIGH = 0;
pStats->SizeofLOW = 0;
for (i = 0;i < SIZE;i++)
StudentAVG[i].ID = InitStudentData[i].ID;
for (i = 0;i < SIZE;i++)
{
StudentAVG[i].StudentAvg = Student_Average(InitStudentData[i].StudentGradeArray, InitStudentData[i].NumOfExams);
}
pStats->Tavg = Total_Average(StudentAVG, SIZE);
for (i = 0;i < SIZE;i++)
{
if (StudentAVG[i].StudentAvg >= pStats->Tavg)
(pStats->SizeofHIGH)++;
else
(pStats->SizeofLOW)++;
}
pStats->HIGH = (Student_processed_data*)malloc((pStats->SizeofHIGH) * sizeof(Student_processed_data));
pStats->LOW = (Student_processed_data*)malloc((pStats->SizeofLOW) * sizeof(Student_processed_data));
for (i = 0;i < SIZE;i++)
{
if (StudentAVG[i].StudentAvg >= pStats->Tavg)
(pStats->HIGH)[i] = StudentAVG[i];// High=pointer||same as High[i]
else
(pStats->LOW)[i] = StudentAVG[i];// HIGH = {ID,AVG}, StudentAVG = {ID,AVG}
}
}
void Print_Tab(Statistics Stats) {
int i;
printf("Total Average is:%d ", Stats.Tavg);
printf("\n %d number of students had AVG higher than TAVG:\n", Stats.SizeofHIGH);
for (i = 0;i < Stats.SizeofHIGH;i++)
{
printf("ID:%d , AVG:%d | ", (Stats.HIGH)[i].ID, (Stats.HIGH)[i].StudentAvg);
}
printf("\n %d number of students had AVG lower than TAVG:\n", Stats.SizeofLOW);
for (i = 0;i < Stats.SizeofLOW;i++)
{
printf("ID:%d , AVG:%d | ", (Stats.LOW)[i].ID, (Stats.LOW)[i].StudentAvg);
}
}
void Free_Mem(Statistics* Pfreestat, Student_init_data* PfreeStudentData) {
free(Pfreestat->LOW);
free(PfreeStudentData->StudentGradeArray);
free(Pfreestat->HIGH);
}
void main() {
int i;
Student_init_data StudentData[SIZE];
Statistics Stats;
for (i = 0;i < SIZE;i++)
{
printf("\nEnter Stundent Num %d ID and Number of Exams:\n", i + 1);
scanf("%d", &StudentData[i].ID);
scanf("%d", &StudentData[i].NumOfExams);
StudentData[i].StudentGradeArray = Input_Data(StudentData[i].NumOfExams);
}
Classification(StudentData ,&Stats);
Print_Tab(Stats);
Free_Mem(&Stats,&StudentData);
}
Спасибо вам всем, Эяль
Я попытался отладить, чтобы увидеть проблему, и не смог получить больше, чем понимание того, что проблема возникает из-за SCANF.
Я попытался изучить это определенное исключение в Интернете, но не смог найти что-то с той же проблемой.
int* Input_Data(int Exams) { int i; int* arr = (int*)malloc(экзамены * sizeof(int)); for (i = 0;i < Экзамены;i++) { printf("введите оценку: "); scanf("%d", &arr[i]); } вернуть обр;
Хорошее общее правило: не используйте scanf. Также читайте sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
Пожалуйста, добавляйте недостающую информацию в вопрос, а не в комментарии. Вы можете использовать кнопку edit
под вопросом
Вы не проверяете, получили ли вы действительный адрес памяти от malloc
. В противном случае код выглядит нормально.
спасибо за ответ, как мне проверить и как я могу это решить? @Герхард
Как вы проверяете, имеет ли переменная определенное значение? С ==
: if (arr == NULL) { /*error handling*/ } else { /*use arr*/ }
Некоторые проблемы:
#include <stdlib.h>
для функций управления памятью.Free_Mem(&Stats,&StudentData);
на Free_Mem(&Stats,StudentData);
, потому что StudentData — это массив структур.free(PfreeStudentData->StudentGradeArray);
на for (int i = 0; i < SIZE; i++) free(PfreeStudentData[i].StudentGradeArray);
void main()
не соответствует стандарту C. Лучше использовать int main()
и возвращать 0 по завершению.Попробуйте с этими изменениями.
Спасибо за ответ. это не решило проблему с моей стороны. при достижении scanf он все еще показывает мне это исключение, и я не совсем понял, почему это не &Studentdata, если это структура, а не указатель
Это потому, что это массив структур. Также Free_Mem должен перебирать массив и освобождать StudentGradeArray
в каждом элементе.
Вы получаете ошибку при первом сканировании или после ввода некоторых данных?
Спасибо за помощь! Это РАБОТАЛО!! Я хочу понять, зачем мне нужно было добавить еще одну библиотеку? а также когда есть массив структур, вы 1. всегда используете . (вместо ->) после индексации? 2. когда вы отправляете массив структур в функцию - она отправляет первый адрес, первую структуру в массиве? @Муравей
@eyalgvili вы не добавили еще одну библиотеку. Вы только добавили недостающий заголовок. Вы должны получить предупреждения об использовании функции, которая не была объявлена ранее. Функция malloc
возвращает указатель, но если вы не предоставляете прототип, предполагается, что возвращается int
. Еще один шанс получить очень полезное предупреждение от вашего компилятора, но вы заглушаете его, добавляя бесполезное и на самом деле вредное приведение arr = (int*)malloc...
Вы не должны приводить возвращаемое значение malloc
в C
На ваш вопрос об использовании . вместо -> это потому, что вы уже откладываете указатель, используя синтаксис массива [].
@Gerhardh, спасибо за добавление вашего комментария. Почему вредно и бесполезно разыгрывать MALLOC? что мне делать по другому в следующий раз?
@eyalgvili См. Могу ли я использовать результат malloc?. arr = (int*)malloc(Exams * sizeof(int));
--> arr = malloc(sizeof arr[0] * Exams);
.
@eyalgvili Вы просто не должны возвращать значение malloc
. Вот и все. Если вы этого не сделаете, компилятор предупредит вас о "создании указателя из целого числа". Это должно заставить вас присмотреться, пока вы не исправите это предупреждение. Ваш актерский состав предотвратил это предупреждение. Вы не смотрели внимательнее, вы не избегали того, чтобы компилятор делал какие-то преобразования, которые он не должен делать. И в результате вы получили какой-то сбой.
Добро пожаловать в СО. Предоставьте код и сообщения об ошибках в виде текста, а не изображений. Мы не можем скопировать ваш скриншот в редактор или компилятор.