Консультация № 172922
05.10.2009, 12:59
0.00 руб.
0 15 2
Здравствуйте уважаемые эксперты

Файл f содержит записи следующей структуры:
- имя студента;
- пол;
- рост;
- оценки по трем экзаменам.
Написать процедуру TASK_3_5 (f), выводящую имена девушек одного роста.

натолкните пожалуйста на алгоритм прохода файла за как можно меньшее количество раз для определения девушек одного роста, код можно не писать. Большое спасибо.

Обсуждение

Неизвестный
05.10.2009, 13:38
общий
это ответ
Здравствуйте, Евгений Викторович.

Первое, что приходит в голову, - создать массив записей (Stud) размерностью от 1 до N (кол-во записей в файле) с полями Len: byte (рост), Sex: boolean (пол - если девушка = true), Eq: boolean (есть ли такого роста - если есть = true).
При первом чтении из файла занести Len, Sex из файла, Eq инициализировать false.
После, пробежаться по этому массиву (см. фрагмент кода ниже) и записать в Eq true для соответствующих персон.
При втором чтении файла вывести на печать тех, для кого поле Eq=true.
Недостаток метода: Если есть несколько девушек с ростом, например, 160 см. и несколько с ростом 170 см, выводиться имена будут "вразнобой" (несортировано по росту)

Приложение:
{pupil - имя записи в файле f}
...
for i:=1 to n do begin
read(f,pupil);
stud[i].sex:=pupil.sex;
stud[i].len:=pupil.len;
stud[i].eq:=false;
end;

for i:=1 to n-1 do
for j:=i+1 to n do
if stud[i].len=stud[j].len then begin
stud[i].eq:=true;
stud[j].eq:=true;
end;

...
for i:=1 to n do begin
read(f,pupil);
if stud[i].sex and stud[i].eq then
writeln(pupil.name,' ',pupil.len)
end;
давно
Профессионал
304622
583
05.10.2009, 13:40
общий
1) Не совсем понятна задача. Нужны имена девушек, чей рост равен заданной величине? Или надо вывести имена всех девушек, сгруппировав их по одинаковому росту (т.е. по сути отсортировав их список)? Или надо выбрать те значения роста, которые повторяются у двух и более девушек, и вывести имена для каждого значения?

2) Насколько я понял, просто считать весь файл в память и там сортировать в своё удовольствие, -- не годится?

3) Если это нельзя, то допустимо ли считывать лишь значения роста в массив или динамический список?
давно
Мастер-Эксперт
425
4118
05.10.2009, 13:41
общий
Евгений Викторович:
А Вы с понятием "динамический список" знакомы? Т.е. список каких-то данных с нефиксированным размером и расширяемым по мере необходимости.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Профессионал
304622
583
05.10.2009, 13:51
общий
Максим Юрьевич:
Этот вариант хоть и выведет имена девушек с дублирующимися значениями роста, но в разнобой. Например:

Лена 160
Галя 155
Люда 165
Валя 155
Зина 160
Оля 165
Неизвестный
05.10.2009, 14:06
общий
Цитата: Сергей Бендер
Этот вариант хоть и выведет имена девушек с дублирующимися значениями роста, но в разнобой

Да, Сергей. Я указал на этот недостаток в ответе.
давно
Академик
320937
2216
05.10.2009, 14:58
общий
05.10.2009, 15:11
это ответ
Здравствуйте, Евгений Викторович.
Примем допущения.
1. Рост измеряется целым числом сантиметров.
2. Максимальный рост 250 см.
3.Список имен девушек одного роста не длинней 255 символов.

Дальше создаем arr[1..250] of string[255]; Читаем файл последовательно. Если у какой-то девушки рост, допустим, 153 см, ее имя (с запятой впереди) надо добавить к элементу массива с номером 153. Дальше просто распечатываем непустые элементы массива с их индексами.
{ Кстати, в ЕГЭ (часть C) именно такие задачки. }
5
Неизвестный
05.10.2009, 15:08
общий
Модераторы:
Добрый день, господа! Прошу внести изменения в ответ:
".........
3.Список имен девушек одного роста не длинней 255 символов
........"
давно
Мастер-Эксперт
425
4118
05.10.2009, 15:09
общий
Даже в TurboPascal (хотя его использование сейчас равноценно приезду в Грецию и общению там на древнегреческом ) есть средства позволяющие создать структурированный и отсортированный список девушек с проходом файла за один раз.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
05.10.2009, 15:17
общий
Я привел ЕГЭшное решение (о чем и написал в ответе).
давно
Мастер-Эксперт
425
4118
05.10.2009, 15:41
общий
leonid59:
Ваше решение, хоть и нерационально по использованию памяти, тем не менее позволяет структурировать выходные данные хотя бы по росту. У предыдущего автора выход вообще, кто в лес, кто по дрова.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
05.10.2009, 18:21
общий
sir Henry:
Наверно, тогда есть смысл давать на такие вопросы два ответа: один - "как правильно", а второй - "как преподы спрашивают" ;)
давно
Старший Модератор
31795
6196
05.10.2009, 23:17
общий
leonid59:
Цитата: 300647
Наверно, тогда есть смысл давать на такие вопросы два ответа: один - "как правильно", а второй - "как преподы спрашивают" ;)

И это говорит преподаватель
Цитата: 300647
Организация: Ковровский транспортный колледж
Адрес: Ковров
О себе:
преподаватель математики и информатики

Есть только одно решение - правильное, а если преподаватели спрашивают не правильное решение, то цена им пол-копейки.
leonid59:
Единственно правильное решение:
Цитата: из вопроса
натолкните пожалуйста на алгоритм прохода файла за как можно меньшее количество раз для определения девушек одного роста

Идея создания массива по росту правильная, но есть и отдельные моменты.
Когда я учился в военном училище, в наш взвод набрали 30-ть человек почти одного роста и одинаковой комплекции. На первом курсе мы были похожи на близницов, все лысые, одного роста и одинаково неуклюжи. В первое время мы гордились своей похожестью. Только потом мы узнали, зачем так сделали - "взвод почетного караула". Такие взводы были на каждом курсе. Снимали с любого занятия (было и с караула дергали):форма одежды, оружие, боеприпасы и построение на плацу через 20-ть минут.
Но это я отвелекся: строка 255 символов очень маленькая для хранения информации о студентах одной группы(тем более, что некоторые ТР не воспринимают определение string[255], вернее воспринимают, но обрабатыают как строку 127 символов), а если говорить об одном курсе. У меня полное имя состоит из 10-ти символов, а Вы представьте сколько там(во взводе) было Валентинов, Валериев и Александров. Женские имена имеют среднюю длину отличную от имен мужчин, меньшую, но тем не мение, где гарантия, что не поменяются сами условия задачи. При одних она работает, при других нет. А ещё и один дополнительный разделительный символ ",", на каждое имя.

И так повторюсь, сама идея правильная, но нужно создавать статический массив указателей на динамический список данных об каждом студенте. После этого решается вопрос поставленный в посте:
Цитата: Вадим Исаев ака sir Henry
Ваше решение, хоть и нерационально по использованию памяти, тем не менее позволяет структурировать выходные данные хотя бы по росту.

Статическая память используется минимально, но наргужается динамическая.
И как вариант снижения используемой памяти: возможен ещё и подсчет разных: Шур - 5, Маш - 3, Марин-2 и т.д.

Если честно, то есть методы внешней сортировки, которые больше нагружают работу с файлами, но позволяют сортировать большие объемы данных(но они противоречат условию задачи, снизить именно работу с файлом).
Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
06.10.2009, 08:37
общий
Задача должна была быть решена без использования динамической памяти, т.к. динамическая память - тема следующей контрольной работы . Большое спасибо всем за помощь.
только кое-что изменил
Дальше просто распечатываем непустые элементы массива с их индексами.

распечатываем непустые элементы, содержащие больше одного имени девушки(перед выводом строки прошел по ней циклом, посчитал запятые, если >1 то выводим элемент)
приложил итоговый код решения задачи, правда пришлось ещё больше урезать размер массива и размер строки с именами девушек, при большем размера вылетала ошибка runtime 202(переполнение стека). Среда программирования BP 7.0 for Windows(давно бы уже перешел на что-нибудь другое, но требования преподавателя - работать только в ней, почему - хз )
Код:

program kr1z2;
uses
WinCrt;
const
name = 'z2.dat';
n1 = 140;{примем рост девушек от n1 до n2 см}
n2 = 240;
type
list = record
name : string;
sex : boolean; {TRUE - девушка, FALSE - парень}
height : integer;
val : array[1..3] of 2..5
end;
listfile = file of list;
myarr = array[n1..n2] of string[60];

procedure TASK_3_5(var f : listfile);
var
lf : list;
arr : myarr;
i,j : integer;
kol_name : byte;
begin
{$I-}
Reset(f);
{$I+}
if IOResult = 0 then
begin
for i:=n1 to n2 do arr[i]:='';
while not EOF(f) do
begin
read(f,lf);
if lf.sex then arr[lf.height]:=arr[lf.height]+lf.name+',';
end;
for i:=n1 to n2 do
begin
if arr[i]<>'' then
begin
kol_name:=0;
for j:=1 to Length(arr[i]) do if arr[i,j]=',' then Inc(kol_name);
if kol_name>1 then Writeln(i,': ',arr[i]);
end;
end;
Close(f);
end else Writeln('Файл не существует');
end;

var
f : listfile;
begin
Assign(f,name);
TASK_3_5(f);
end.
давно
Старший Модератор
31795
6196
06.10.2009, 11:35
общий
Евгений Викторович:
Смотрим, что у Вас находится в Опции(Options) | Размеры памяти(Memory Sizes) | Размер стека(Stack size). У меня там стоит 16'384 байта. Все переменные определенные в процедуре TASK_3_5 размещаются в стеке, т.е. у Вас получается, что в стеке используется:
lf : list;256+1+2+3=261 байт
arr : myarr;(240-140+1)*(60+1)=6'161 байт
i,j : integer;2х2=4
kol_name : byte;=1
261+6161+4+1=6427 байт, это только под переменные(вернее там будет 6430 байт, т.к. компилятор сам выравнивает каждую переменную на четное число байт). Добавим вызов процедуры 4 байта, передаваемый параметр 4 байта и организация стекового кадра 2-а байта, как минимум ещё нужно приблизительно 256 байт для нормальной работы программы. Это прибизительный расчет по программе приведенной выше(добавлено:на практике размер стекового кадра под переменные, компилятор сформировал в размере 6'686 байт). При других входных параметрах будут другие значения, т.е. если тип массива определить как myarr = array[ n1..n2 ] of string;, то только под один массив нужно будет 25'856 байт.

Выход из этой ситуации простой, дайте компилятору новое значение размера стека, к примеру 60'000 байт(максимальное:65'536) и Вы забудете об ошибке runtime 202, а ещё проверите знания преподавателем среды ТР7.0 (найдет ли он причину этой ошибки).

Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
06.10.2009, 14:43
общий
Евгений Викторович:
Здравствуйте, Евгений Викторович! Спасибо за корректировку ответа (и за оценку:).
Что касается размера строки (конечно, при невозможности динамически создавать объекты) - есть еще одна идея, правда, довольно вычурная. Женских имен в организации (в учебном заведении, ...) в общем-то количество ограниченное, ну, допустим, меньше 1000.
Потребуется дополнительный файл имен.
Из этого файла имен до чтения файла сведений создаем дополнительный массив строк Names, содержащий женские имена, сортирнем его по алфавиту.
Теперь при прочтении строчки из файла сведений сначала поищем имя в массиве Names, а затем запишем в уже существующий массив индекс имени (естественно, приведенный к строковому виду). Это даст возможность даже в Вашем раскладе string[60] хранить уже не менее 15 индексов имен.
Возможная проблема: в массиве Names указаны не все имена, допустим, группа международная и имени какого-либо студента в общедоступном словаре нет.
Форма ответа