Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Программирование на C / C++


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Асмик Гаряка
Статус: Академик
Рейтинг: 10414
∙ повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Советник
Рейтинг: 4010
∙ повысить рейтинг »
CradleA
Статус: Бакалавр
Рейтинг: 2474
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / C/C++

Номер выпуска:1742
Дата выхода:10.05.2012, 16:00
Администратор рассылки:Киселёва Алёна aka Verena (Академик)
Подписчиков / экспертов:141 / 93
Вопросов / ответов:1 / 1

Консультация # 185946: Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Задание:

© Цитата:
Написать программу для работы с упорядоченной таблицей по запросам оператора. Упорядоченная таблица организована вектором; каждый элемент таблицы имеет следющую стр
...

Консультация # 185946:

Уважаемые эксперты! Пожалуйста, ответьте на вопрос:

Задание:

© Цитата:
Написать программу для работы с упорядоченной таблицей по запросам оператора. Упорядоченная таблица организована вектором; каждый элемент таблицы имеет следющую структуру:
struct Item{
int key; /* ключ элемента */
char *info /*указатель на информацию */
};
Максимальный размер талицы ограничен (для задания максимального размера таблицы использовать константу - например, const int SIZE = ...;).
Предусмотреть следующие операции:
- включение нового элемента в таблицу при условии, что в таблице не может быть двух элементов с одинаковыми ключами; если при включении нового элемента возникает такая ситуация, на экран должно быть выведено сообщение об ошибке;
- удаление элемента из таблицы по заданному ключу;
- вывод содержимого таблицы на экран.
Разработать дв а варианта программы:
а)и сама таблица, и информация, относящаяся к элементы таблицы, хранятся в основной памяти;
б)и сама таблица, и информация, относящаяся к элементу таблицы, хранятся во внешней памяти (используется двоичный файл произвольного доступа). Все операции выполняются с таблицей, размещённой в основной памяти. Таблица считывается из файла (или создаётся в первый раз) в начале сеанса работы и записывается в файл сразу же при выполнении операции включения в таблицу. Имя файлы вводится по запросу из программы.

Примечания:
1. Программа должна содержать несколько функций; функция main должна выполнять: вывод меню, ввод и анализ ответа, вызов на исполнение требуемой функции;
2. В программе нужно предусмотреть проверку правильности ввода данных;
3. Для варианта б) следует модифицировать структуру, определяющую элемент таблицы, включив в неё длину информации и её смещение в файле;
4. В варианте б) для работы с файлом использовать функции пакета stdio.h; чтение и запись выполнять с помощью fread() и fwrite(), в которых должна быть указана реальная длина информации.


Чистый C++
Желательно использовать:
Агоритм двоичного поиска

Желательно, чтобы программа была с комментариями.

Дата отправки: 02.05.2012, 15:24
Вопрос задал: Безымянный (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, Безымянный!
Вариант а)

Код :
#include <locale>
#include <iostream>
#include <string.h>

using namespace std;

bool Find(int, int*);
void AddElement(void);
void DelElement(void);
void OutTable(void);
void Exit(void);
int GetNum(void);

const int	SIZE = 10;	//максимальный размер таблицы

typedef struct Item
{
	int		key;		//ключ элемента
	char	*info;		//указатель на информацию
}ITEM;

const char *mesMain[] =		//сообщения меню
{
	"Добавить новый элемент",
	"Удалить элемент",
	"Вывести таблицу",
	"Выход"
};
//количество пунктов меню
int MesMainCount = sizeof( mesMain ) / sizeof( mesMain[0] );
//функции отработки пунктов меню
void ( *funcMain[] )() ={AddElement, DelElement, OutTable, Exit};

int		count = 0;		//количество задействованных элементов таблицы
ITEM	table[SIZE];	//таблица

//поиск по таблице в памяти элемента с заданным ключем
//использован агоритм двоичного поиска
//возвращает true, если найдено, и индекс найденного элемента
//false, если не найдено, и индекс, куда надо вставить новый элемент!
//элементы в таблице сортируются по возрастанию ключей
bool Find(int key, int *idx)
{
	int first = 0;		/* Первый элемент в массиве */
    int last = count;	/* Элемент в массиве, СЛЕДУЮЩИЙ ЗА последним */
						/* Если просматриваемый участок непустой, first<last */
    int	mid; 
 
	if ((count == 0) || (table[0].key > key))
	{
		/* массив пуст или меньше всех, надо вставить его в позицию 0    */
		*idx = 0;
		return false;
	} 
	else if (table[count-1].key < key)
    {
		/* больше всех, надо вставить его в позицию count    */
		*idx = count;
		return false;
	}
 
	//где-то в середине...
	while (first < last)
	{
		/* ВНИМАНИЕ! В отличие от более простого (first+last)/2, этот код стоек к переполнениям.
		   Если first и last знаковые, возможен код (unsigned)(first+last) >> 1.    */
		mid = first + (last - first) / 2;
 
		if (key <= table[mid].key)
			last = mid;
		else
			first = mid + 1;
    }
 
    if (table[last].key == key)
    {
		/* Искомый элемент найден. last - искомый индекс */
		*idx = last;
		return true;
    } 
	else
	{
		/* Искомый элемент не найден. Его место - last.  */
		*idx = last;
		return false;
	}
}

//добавление элемента в таблицу
void AddElement()
{
	int		i, idx, num;
	char	str[80];

	if (count < SIZE)				//есть ли место в таблице?
	{
		cout << "Введите ключ элемента: ";
		num = GetNum();				//вводим ключ нового элемента
		if (Find(num, &idx))		//есть ли такой в таблице и получаем индекс, куда вставлять
		{
			cout << "Элемент с таким ключем уже есть" << endl;
			return;
		}
		if (count)					//если что-то есть
			for (i=count-1; i>=idx; i--)	//то смещаем на одну позицию к концу
				table[i+1] = table[i];		//тем самым, освобождаем место для нового
		table[idx].key = num;		//запоминаем ключ
		cout << "Введите строку: ";
		cin.ignore();				//сбросим все лишнее на входе
		cin.getline(str, 80);		//вводим строку
									//запишем данные в элемент таблицы 
		table[idx].info = new char[strlen(str)+1];
		strcpy(table[idx].info, str);
		count++;
	}
	else
		cout << "Таблица полностью заполнена" << endl;
}

//удаление элемента таблицы по ключу
void DelElement()
{
	int		idx, num;

	cout << "Введите ключ элемента: ";
	num = GetNum();					//вводим ключ	
	if (!Find(num, &idx))			//есть такой? Заодно узнаем индекс элемента
	{
		cout << "Элемент с таким ключем отсутствует" << endl;
		return;
	}
	delete [] table[idx].info;		//освободим память строки удаляемого элемента
	for (; idx<count-1; idx++)		//смещаем на одну позицию к началу
		table[idx] = table[idx+1];	//тем самым, удаляем элемент
	count--;						//уменьшаем счетчик элементов
	cout << "Элемент удален" << endl;
}

//вывод всей таблицы на экран
void OutTable()
{
	if (count)						//что-то есть?
	{
		for(int i=0; i<count; i++)	//по всем элементам
			cout << i << ": key = " << table[i].key << "\tinfo = " << table[i].info << endl;
	}
	else
		cout << "Таблица пуста" << endl;
}

//конец работы
void Exit()
{	//освободим память под строки
	for (int i=0; i<count; i++)
		delete [] table[i].info;
}

//ввод целого числа с консоли
int GetNum()
{
	int		a;
	cin >> a;
	while ( !( cin.good() || cin.eof() ) || ( a < 0 ) )
	{
		cout << "Введите число! " << endl;
		cin.ignore();
		cin >> a;
	}
	return a;
}

//вывод меню и ввод пункта меню
int ViewMenu(const char* mes[], int max)
{
	int ret;
	do
	{
		for ( int i = 0; i < max; i++ )
			cout << i+1 << ". " << mes[i] << endl;
		cout << "Ваш выбор: ";
		ret = GetNum();
	}
	while ( ret < 1 || ret > max );	//проверяем на допустимость
	return ret;						//возвращаем номер пункта
}

int main()
{
	int ret;
	setlocale(LC_ALL,"Russian");			//чтобы писалось по-русски
	do
	{
		ret = ViewMenu(mesMain, MesMainCount);	//рисуем меню и вводим пункт меню
		funcMain[ret-1]();						//отрабатываем пункт меню
		cout << "--------------------------------" << endl;
		if (ret == MesMainCount)	//Exit, как последний пункт меню?
			break;					//уходим!
	} while (ret);
	return 0;
}

Вариант б)
Код :
#include <locale>
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

void ReadTableFromFile(void);
void WriteTableToFile(void);
bool Find(int, int*);
void AddElement(void);
void DelElement(void);
void OutTable(void);
void Exit(void);
int GetNum(void);

const int	SIZE = 10;	//максимальный размер таблицы

typedef struct Item
{
	int		key;		//ключ элемента
	int		seek;		//смещение в файле поля info
	int		len;		//длина info
}ITEM;

const char *mesMain[] =		//сообщения меню
{
	"Добавить новый элемент",
	"Удалить элемент",
	"Вывести таблицу",
	"Выход"
};
//количество пунктов меню
int MesMainCount = sizeof( mesMain ) / sizeof( mesMain[0] );
//функции отработки пунктов меню
void ( *funcMain[] )() ={AddElement, DelElement, OutTable, Exit};

int		count = 0;		//количество задействованных элементов таблицы
ITEM	table[SIZE];	//таблица
FILE	*file = NULL;	//указатель на открытый файл
char	fName[256];		//имя файла

//чтение таблицы из файла
//формат файла:
//int   count			- количество задействованных элементов таблицы
//ITEM	table[SIZE]		- таблица (вся)
//...					- строки info
void ReadTableFromFile()
{
	cout << "Введите имя файла: ";
	cin.getline(fName, 256);	//вводим имя файла
	file = fopen(fName, "r+b");	//открываем на чтение/запись, тип двоичный
	if (NULL == file)			//если нет такого
	{
		file = fopen(fName, "w+b");	//то создаем новый файл
		if (file)					//создался?
		{							//запишем файл с пустой таблицей
			count = 0;				//обнулим количество (на всякий случай)
			fwrite(&count, sizeof(int), 1, file);	//количество
			fwrite(table, sizeof(ITEM), SIZE, file);//таблица
		}
		else
			cout << "Ошибка создания файла" << endl;
	}
	else
	{								//файл есть
		fread(&count, sizeof(int), 1, file);		//читаем количество
		fread(table, sizeof(ITEM), SIZE, file);		//и таблицу
	}
	fclose(file);					//файл закрываем
}

//запись таблицы в файл (в конце работы)
void WriteTableToFile()
{
	if (fName[0])					//проверим на наличие имени файла
	{
		file = fopen(fName, "r+b");	//открываем на чтение/запись
		if (file)					//открылся?
		{
			fwrite(&count, sizeof(int), 1, file);	//пишем количество
			fwrite(table, sizeof(ITEM), SIZE, file);//и таблицу
			fclose(file);			//файл закрываем
		}
		else
			cout << "Ошибка открытия" << endl;
	}
	else
		cout << "Имя файла не задано" << endl;
}

//поиск по таблице в памяти элемента с заданным ключем
//использован агоритм двоичного поиска
//возвращает true, если найдено, и индекс найденного элемента
//false, если не найдено, и индекс, куда надо вставить новый элемент!
//элементы в таблице сортируются по возрастанию ключей
bool Find(int key, int *idx)
{
	int first = 0;		/* Первый элемент в массиве */
    int last = count;	/* Элемент в массиве, СЛЕДУЮЩИЙ ЗА последним */
						/* Если просматриваемый участок непустой, first<last */
    int	mid; 
 
	if ((count == 0) || (table[0].key > key))
	{
		/* массив пуст или меньше всех, надо вставить его в позицию 0    */
		*idx = 0;
		return false;
	} 
	else if (table[count-1].key < key)
    {
		/* больше всех, надо вставить его в позицию count    */
		*idx = count;
		return false;
	}
 
	//где-то в середине...
	while (first < last)
	{
		/* ВНИМАНИЕ! В отличие от более простого (first+last)/2, этот код стоек к переполнениям.
		   Если first и last знаковые, возможен код (unsigned)(first+last) >> 1.    */
		mid = first + (last - first) / 2;
 
		if (key <= table[mid].key)
			last = mid;
		else
			first = mid + 1;
    }
 
    if (table[last].key == key)
    {
		/* Искомый элемент найден. last - искомый индекс */
		*idx = last;
		return true;
    } 
	else
	{
		/* Искомый элемент не найден. Его место - last.  */
		*idx = last;
		return false;
	}
}

//добавление элемента в таблицу
void AddElement()
{
	int		i, idx, num;
	char	str[80];

	if (count < SIZE)				//есть ли место в таблице?
	{
		cout << "Введите ключ элемента: ";
		num = GetNum();				//вводим ключ нового элемента
		if (Find(num, &idx))		//есть ли такой в таблице и получаем индекс, куда вставлять
		{
			cout << "Элемент с таким ключем уже есть" << endl;
			return;
		}
		if (count)					//если что-то есть
			for (i=count-1; i>=idx; i--)	//то смещаем на одну позицию к концу
				table[i+1] = table[i];		//тем самым, освобождаем место для нового
		table[idx].key = num;		//запоминаем ключ
		cout << "Введите строку: ";
		cin.ignore();				//сбросим все лишнее на входе
		cin.getline(str, 80);		//вводим строку
									//запишем данные в элемент таблицы и в файл
		if (fName[0])				//проверим на наличие имени файла
		{
			file = fopen(fName, "r+b");	//открываем
			if (file)					//открылся?
			{
				fseek(file, 0, SEEK_END);				//становимся в конец файла
				table[idx].seek = ftell(file);			//запоминаем позицию конца файла, как
														// смещение в файле поля info
				table[idx].len = strlen(str)+1;			//запоминаем длину строки
				fwrite(str, table[idx].len, 1, file);	//и пишем строку в конец файла
				fclose(file);							//закрываем файл
				count++;								//считаем элементы таблицы
			}
			else
				cout << "Ошибка открытия" << endl;
		}
		else
			cout << "Имя файла не задано" << endl;
	}
	else
		cout << "Таблица полностью заполнена" << endl;
}

//удаление элемента таблицы по ключу
void DelElement()
{
	int		idx, num;

	cout << "Введите ключ элемента: ";
	num = GetNum();					//вводим ключ	
	if (!Find(num, &idx))			//есть такой? Заодно узнаем индекс элемента
	{
		cout << "Элемент с таким ключем отсутствует" << endl;
		return;
	}
	for (; idx<count-1; idx++)		//смещаем на одну позицию к началу
		table[idx] = table[idx+1];	//тем самым, удаляем элемент
	count--;						//уменьшаем счетчик элементов
	cout << "Элемент удален" << endl;
}

//вывод всей таблицы на экран
void OutTable()
{
	char	str[80];
	if (count)					//что-то есть?
	{
		if (fName[0])			//имя файла задано?
		{
			file = fopen(fName, "r+b");	//открываем файл
			if (file)					//открылся?
			{
				for(int i=0; i<count; i++)	//по всем элементам
				{
											//читаем строку из файла
					fseek(file, table[i].seek, SEEK_SET);	//в начало строки
					fread(str, table[i].len, 1, file);		//читаем строку
															//выводим элемент
					cout << i << ": key = " << table[i].key << "\tinfo = " << str << endl;
				}
			}
			else
				cout << "Ошибка открытия" << endl;
		}
		else
			cout << "Не задано имя файла" << endl;
	}
	else
		cout << "Таблица пуста" << endl;
}

//конец работы
void Exit()
{
	WriteTableToFile();		//сохраним таблицу в файле
}

//ввод целого числа с консоли
int GetNum()
{
	int		a;
	cin >> a;
	while ( !( cin.good() || cin.eof() ) || ( a < 0 ) )
	{
		cout << "Введите число! " << endl;
		cin.ignore();
		cin >> a;
	}
	return a;
}

//вывод меню и ввод пункта меню
int ViewMenu(const char* mes[], int max)
{
	int ret;
	do
	{
		for ( int i = 0; i < max; i++ )
			cout << i+1 << ". " << mes[i] << endl;
		cout << "Ваш выбор: ";
		ret = GetNum();
	}
	while ( ret < 1 || ret > max );	//проверяем на допустимость
	return ret;						//возвращаем номер пункта
}

int main()
{
	int ret;
	setlocale(LC_ALL,"Russian");			//чтобы писалось по-русски
	ReadTableFromFile();				//читаем таблицу из файла (или создаем новый)
	do
	{
		ret = ViewMenu(mesMain, MesMainCount);	//рисуем меню и вводим пункт меню
		funcMain[ret-1]();						//отрабатываем пункт меню
		cout << "--------------------------------" << endl;
		if (ret == MesMainCount)	//Exit, как последний пункт меню?
			break;					//уходим!
	} while (ret);
	return 0;
}

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 06.05.2012, 03:51
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!



В избранное