Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.06.2011, 20:41   #1
yakuleb
 
Регистрация: 31.05.2011
Сообщений: 7
По умолчанию Динамический массив структур в Си

Не могу решить следующую задачу:
Есть структура student (фамилии, оценки, курс...) . Есть массив этих структур.Создаю функцию записи в массив.

Код:
int scan_all(student *p,int n)//Ф-ция запрашивает указатель *p
							//на массив дляной "n" типа student,увеличивает 
							//его размер на 1 эл-т и   //заполняет
{
	int j;//ДЛЯ СЧЕТЧИКА
	student *p2=NULL;//промежуточный указатель для динамического расширения массива
	p2=realloc(p,(n+1)*sizeof(*p));
	if (p2!=NULL)//если нет ошибки при расширении массива на 1 эл-т
	{
		p=p2;
		n++;
		printf("Введите фамилию студента:\n");
		scanf("%s",(p+n)->name);
		printf("Введите курс студента:\n");
		scanf("%d",(p+n)->year);
	for (j=0;j<MAXGRADES;++j)//ввод оценок
	{printf("Введите %d -ю оценку:\n",j);
		scanf("%d",(p+n)->grade);
	}
	}
	else 
	{
		printf("Запись данных невозможна! Переполнение памяти!\n");		
	}
Перед тем как вводить данные функция должна увеличить массив на 1 элемент. Всё компилируется, но при отладке выдает следующее:

ОС Windows инициировала точку останова в FINAL.exe.
Это может быть вызвано повреждением кучи и указывает на ошибку в FINAL.exe или в одной из загруженных им DLL.
Возможной причиной так же может быть нажатие пользователем клавиши F12, когда фокус принадлежит FINAL.exe


отладчик сообщает что переменная p2 неправильный указатель.

Последний раз редактировалось ACE Valery; 03.06.2011 в 15:37.
yakuleb вне форума Ответить с цитированием
Старый 02.06.2011, 22:09   #2
Syuf
Форумчанин
 
Аватар для Syuf
 
Регистрация: 02.02.2010
Сообщений: 599
По умолчанию

Код:
int scan_all(student *p,int n)//Ф-ция запрашивает указатель *p
//на массив дляной "n" типа student,увеличивает 
//его размер на 1 эл-т и //заполняет
{
int j;//ДЛЯ СЧЕТЧИКА
student *p2=NULL;//промежуточный указатель для динамического расширения массива
p2=realloc(p,(n+1)*sizeof(*p));
if (p2!=NULL)//если нет ошибки при расширении массива на 1 эл-т
{
p=p2;
//n++;
printf("Введите фамилию студента:\n");
scanf("%s",(p+n)->name);
printf("Введите курс студента:\n");
scanf("%d",(p+n)->year);
for (j=0;j<MAXGRADES;++j)//ввод оценок
{printf("Введите %d -ю оценку:\n",j);
scanf("%d",(p+n++)->grade);
}
}
else 
{
printf("Запись данных невозможна! Переполнение памяти!\n"); 
}
Вы выходите за предел массива.
"Лишь то читается легко, что написано с трудом; что в час написано, то в час и позабыто."
Syuf вне форума Ответить с цитированием
Старый 03.06.2011, 19:37   #3
yakuleb
 
Регистрация: 31.05.2011
Сообщений: 7
По умолчанию

Не совсем так. Отладчик останавливается на строчке
p2=realloc(p,(n+1)*sizeof(*p));
указывая, что p2 - неправильный указатель.
По идее указателю p2 присваивается значение увеличенного массива, а потом проверка идти должна... Но на этой строе стопор.
yakuleb вне форума Ответить с цитированием
Старый 03.06.2011, 19:48   #4
Syuf
Форумчанин
 
Аватар для Syuf
 
Регистрация: 02.02.2010
Сообщений: 599
По умолчанию

Покажите код, где вызывается эта функция.
"Лишь то читается легко, что написано с трудом; что в час написано, то в час и позабыто."
Syuf вне форума Ответить с цитированием
Старый 03.06.2011, 21:29   #5
yakuleb
 
Регистрация: 31.05.2011
Сообщений: 7
По умолчанию

Здесь идет описание массива ссылок на функции функции
//main.c

Код:
#include<locale.h>
#include"interface.h"
#include "util.h"
#include "file.h"
int main()
{
	
	menu_item list[] = {
		{"Ввод с клавиатуры",scan_all},
		{"Вывод на экран",print_all},
		{"Сортировка по имени",sort_by_name},
		{"Запись в файл",save_stud},
		{"Чтение из файла",load_stud}
	};
	setlocale(LC_CTYPE,"rus");
	menu(list,sizeof (list) / sizeof (*list));	
}

далее сам вызов:
interface.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include"interface.h"


void menu(const menu_item *list,int num)//ф-я меню
{
	int i;
	void getstud(student **, int *);
	student *p;int n;
	getstud(&p,&n);

	while (1)
	{
		system("cls");//Очистка экрана
		for(i=0;i<num;++i)
			printf("%d. %s\n",i+1,list[i].prompt);//печать меню
			printf("%d. %s\n",0,"Выход");
			do
			{
				printf("\nВаш выбор (0 - %d): ",num);
				fflush(stdin);//очистка буфера ввода
			} while (scanf("%d",&i)!=1 || i<0 || i>num);
			if (--i<0) break;
			n=list[i].comand(p,n);
			system("pause");
	}
}
static void print_stud(const student *p)//печать данных 1-го эл-та типа student 
{
	int j;
	printf("%-*s %d ",MAXLEN,p->name,p->year);//печать name,year 
	for (j=0;j<MAXGRADES;++j)//печать оценок
		printf("%2d",p->grade[j]);
	printf ("\n");
	
}

int print_all(student *p,int n)//печать массива типа student
{
	int i;
	for (i=0;i<n;++i)
		print_stud(p+i);
	return n;
}
int scan_all(student *p,int n)//Ф-ция запрашивает указатель *p
							//на массив дляной "n" типа student,увеличивает 
							//его размер на 1 эл-т и заполняет
{
	int j;//ДЛЯ СЧЕТЧИКА
	student *p2=NULL;//промежуточный указатель для динамического расширения массива
	p2=realloc(p,(n+1)*sizeof(*p));
	if (p2!=NULL)//если нет ошибки при расширении массива на 1 эл-т
	{
		p=p2;
		//n++;
		printf("Введите фамилию студента:\n");
		scanf("%s",(p+n)->name);
		printf("Введите курс студента:\n");
		scanf("%d",(p+n)->year);
	for (j=0;j<MAXGRADES;++j)//ввод оценок
	{printf("Введите %d -ю оценку:\n",j);
		scanf("%d",(p+n)->grade[j]);
	}
	}
	else 
	{
		printf("Запись данных невозможна! Переполнение памяти!\n");		
	}
	
	//printf("scan_all\n"); //для отладки.
	return n;
}

описание типа student:
student.h

#ifndef STUDENT_H
#define STUDENT_H

#define MAXLEN    30
#define MAXGRADES  3
typedef struct
{
	char name[MAXLEN];
	short year;
	char grade[MAXGRADES];
} student;
#endif

Последний раз редактировалось ACE Valery; 04.06.2011 в 14:56.
yakuleb вне форума Ответить с цитированием
Старый 03.06.2011, 21:37   #6
yakuleb
 
Регистрация: 31.05.2011
Сообщений: 7
По умолчанию

Ну и собственно student.c

#include"student.h"



Код:
//Для отладки
#define NSTUD 10

 student a[] =//описание типа
{
	{"Яшин",1,{3,5,5}},
	{"Кашин",2,{3,4,5}},
	{"Пашин",4,{3,2,5}},
	{"Иванов",1,{1,3,5}},
	{"Сергеев",3,{2,5,2}},
	{"Лунков",5,{3,2,3}},
};
void getstud(student **p, int *n)//ф-ция возвращает указатель на внутрений массив
								 //типа student и колличество записей n
{
	*p=a;
	*n=sizeof(a)/sizeof(student);
}
yakuleb вне форума Ответить с цитированием
Старый 03.06.2011, 21:42   #7
Syuf
Форумчанин
 
Аватар для Syuf
 
Регистрация: 02.02.2010
Сообщений: 599
По умолчанию

Пробежал взглядом, единственное, что бросилось в глаза - это неинициализированный указатель strudent *p, который вы передаете этой функции. Это так? Ведь она с ним уже дальше страшные вещи делает, разыменует, например.
"Лишь то читается легко, что написано с трудом; что в час написано, то в час и позабыто."
Syuf вне форума Ответить с цитированием
Старый 03.06.2011, 22:42   #8
yakuleb
 
Регистрация: 31.05.2011
Сообщений: 7
По умолчанию

Другие функции тоже используют этот указатель... Тем не менее распечатать удается... Программу клинит при попытке увеличить длину массива realloc почему то не работает...
yakuleb вне форума Ответить с цитированием
Старый 03.06.2011, 22:50   #9
Syuf
Форумчанин
 
Аватар для Syuf
 
Регистрация: 02.02.2010
Сообщений: 599
По умолчанию

Так вы же realloc'чите статический массив.
"Лишь то читается легко, что написано с трудом; что в час написано, то в час и позабыто."
Syuf вне форума Ответить с цитированием
Старый 04.06.2011, 23:45   #10
yakuleb
 
Регистрация: 31.05.2011
Сообщений: 7
По умолчанию Спасибо..

Спасибо.. Дошло... Не буду задавать глупых вопросов типа :"а как написать?" Попробую сам.. Главное понял ошибку.Учусь я ..
yakuleb вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ввод структур в динамический список Mahin Общие вопросы C/C++ 4 20.04.2011 10:30
Как ввести данные в динамический массив структур? sunplant Общие вопросы C/C++ 6 28.01.2011 17:10
Динамический массив структур RaZveDchiK Помощь студентам 1 31.08.2008 21:44
Динамический массив структур Kostyakovich Помощь студентам 4 20.04.2008 21:59