Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с файлами
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
npl
Даны названия N различных обществ (N заданное число), фигуристы которых участовали в соревновании. О каждом фигуристе известно: фамилия, название общества и 10 оценок за его выступление. Требуется для каждого спортивного общества определить фигуриста, показавшего наивысший результат, считая его единственным. Баллы, полученные фигуристом, подсчитываются следующим образом: максимальная и минимальная оценки отбрасываются, а из остальных формируется средняя. При вводе данных обеспечить уникальность наименований обществ и обязательную принадлежность фигуриста к одному из них.
volvo
... и что? Хорошее задание, только зачем ты привел его? Чтоб тебе все сделали и выложили "на тарелочке"? Иди в Поиск, там есть задачи про хоккейные и футбольные команды, группы студентов с оценками на экзамене, разбирайся, как они сделаны, начинай делать свое задание, что будет непонятно - приходи, спрашивай...

А так просто вываливать задание безо всяких попыток решить (и показать остальным, что ты пытался, но у тебя не получилось) - это по меньшей мере обрекать тему на забвение...
npl
Частично задача решена. А именно, я создаю типизированный файл, куда помещаю фамилии, названия обществ и оценки.
andriano
Цитата(npl @ 9.12.2007 13:48) *

Частично задача решена. А именно, я создаю типизированный файл, куда помещаю фамилии, названия обществ и оценки.

Интересно также узнать, ЗАЧЕМ ты это делаешь. По условию, вроде, этого не требуется.
npl
Вот код

program obchestva_and_figuristyi;
uses crt;
type
figurist=record
fio:string[10];
obsh:string[10];
ocenka:array[1..10] of integer;
end;
var
f:file of figurist;
ftxt:text;
i,cod:integer;
z:figurist;
st:string;
max,min:integer;
s,sr:real;
begin
clrscr;
assign(ftxt,'figur1.txt');
reset(ftxt);
assign(f,'figur.dat');
rewrite(f);
while not eof(ftxt) do
begin
readln(ftxt,st);
z.fio:=copy(st,1,pos(' ',st));
z.obsh:=copy(st,12,pos(' ',st));
delete(st,1,22);
for i:=1 to 10 do
begin
val(st[1],z.ocenka[i],cod);
delete(st,1,2);
end;
write(f,z);
end;
close(ftxt);
close(f);
reset(f);
while not eof(f) do
begin
read(f,z);
write(z.fio,' ',z.obsh,' ');
for i:=1 to 10 do
write(z.ocenka[i]);
writeln;
max:=z.ocenka[1];
for i:=2 to 10 do
begin
if z.ocenka[i]>max then
max:=z.ocenka[i];
end;
write(max,' ');
min:=z.ocenka[1];
for i:=2 to 10 do
begin
if z.ocenka[i]<min then
min:=z.ocenka[i];
end;
write(min,' ');
s:=0;
for i:=1 to 10 do
s:=s+z.ocenka[i];
write(s:2:1,' ');
sr:=(s-max-min)/8;
writeln(sr:2:2);
end;
close(f);
end.


Пока я определил максимальную, минимальную оценку, отбросил их и нашёл среднюю.

Добавлено через 5 мин.
Думаю, что делать дальше. Создать ещё один типизированный файл, туда поместить фамилии фигуристов, названия обществ и их средние оценки. И дальше работать с этим файлом, чтобы для каждого общества найти фигуриста с максимальным результатом.
npl
Народ, откликнитесь.
andriano
То, что ты сделал, возможно, подходит под определение "бессмысленная работа с типизированным файлом", но никак не "работа с текстовым файлом".
Бессмысленная потому, что все эти манипуляции не нужны. Все операции целесообразно делать непосредственно в оперативной памяти, введя массив типа figurist и целую переменную, индицирующую длину заполненной части этого массива.
Что же касается темы, то вероятнее всего, имеется в виду чтение и разбор входного текстового файла с фигурисами, а также вывод результата работы в текстовый же файл.
Пока что на том этапе, что ты опубликовал, у тебя содержится несколько непоняток и минимум одна ошибка.
Непонятки заключены в том, почему ты считаешь, что Ф.И.О. способны всегда поместиться в 10 символов, а также длниа названия спортивного общества не может превышать этой величины?
Ошибка - в том, что ты перед чтением оценки зачем-то удаляешь из строки 22 симвлоа. Почему именно 22? Это такая мировая константа?
npl
Цитата(andriano @ 9.12.2007 19:00) *

То, что ты сделал, возможно, подходит под определение "бессмысленная работа с типизированным файлом", но никак не "работа с текстовым файлом".
Бессмысленная потому, что все эти манипуляции не нужны. Все операции целесообразно делать непосредственно в оперативной памяти, введя массив типа figurist и целую переменную, индицирующую длину заполненной части этого массива.
Что же касается темы, то вероятнее всего, имеется в виду чтение и разбор входного текстового файла с фигурисами, а также вывод результата работы в текстовый же файл.
Пока что на том этапе, что ты опубликовал, у тебя содержится несколько непоняток и минимум одна ошибка.
Непонятки заключены в том, почему ты считаешь, что Ф.И.О. способны всегда поместиться в 10 символов, а также длниа названия спортивного общества не может превышать этой величины?
Ошибка - в том, что ты перед чтением оценки зачем-то удаляешь из строки 22 симвлоа. Почему именно 22? Это такая мировая константа?

Результат не нужно выводить в текстовый файл. Ф.И.О. в 10 символов, потому что в текстовом файле, который есть Ф.И.О. не превышает 10 символов. А дальше идёт название общества. Она тоже не больше 10. 10+пробел+10+пробел=22. Минимальные, максимальные он находит правильно. Среднее тоже.

Добавлено через 4 мин.
Лучше подскажите, как из средних для каждого общества найти фигуриста с максиальным результатом.
andriano
Если проверка задания будет выполнена по уму, то файл с фигуристами тебе будет предложен другой. Есть ли уверенность, что твоя программа с ним справится?
"Не больше" и "равно" - далеко не одно и то же. Если, скажем, фамилия - Иванов, а название общества - Динамо, то есть ли уверенность, что удалять все равно надо 22 символа? Тот факт, что при существующем файле максимальное и минимальное находит правильно, еще не говорит о том, что так будет всегда.

Ты считал средние не для каждого общества, а для каждого фигуриста. Теперь надо соотнести фигуристов с конкретными обществами и для каждого общества найти максимальное среди средних для входящих в него фигуристов.
npl
Если ФИО меньше 10, то там оставшееся место заполнено пробелом.

Добавлено через 5 мин.
Вот содержание исходного текстового файла
http://npfiles.ru/files/figur1.txt

Добавлено через 1 мин.
Цитата(andriano @ 9.12.2007 19:20) *

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

И как это сделать?
andriano
А есть ли описание формата файла?
Не может оказаться, что в другом файле будет заполняться пробелами до 12-го символа, а в третьем - все разной длины и с единственным пробелом-разделителем?
Для того, чтобы решать задачу, надо точно знать условие.
В текстовых файлах нет определенной структуры, поэтому обычно нет никакого выравнивания проблами по длине, а при необходимости используются разделители: пробел, символ табуляции, запятая, конец строки...
Ты сам составлял файл или его тебе дал преподаватель?
npl
Я сам составлял файл. Задачу надо решать для конкретного своего файла.

Добавлено через 13 мин.
andriano, может уже предложите конкретные решения, а не пустые слова?
andriano
Цитата(npl @ 9.12.2007 19:32) *

Я сам составлял файл. Задачу надо решать для конкретного своего файла.
Я бы на месте преподавателя захотел посмотреть, как программа будет работать на других файлах.
(наверное, из меня вышел бы очень вредный преп. sad.gif
Цитата

Добавлено через 13 мин.
andriano, может уже предложите конкретные решения, а не пустые слова?
Вообще-то я даю именно КОНКРЕТНЫЕ советы по решению.
Если подробнее, то я могу порекомендовать следующий алгоритм разбора строки:
1. Удаляем пробелы в начале.
2. Находим позицию разделителя L.
3. Если L = 0, выводим сообщение об ошибке, иначе продолжаем работу.
4. Копируем в поле имени L-1 символов.
5. Удаляем L символов в начале строки.
6. Удаляем пробелы в начале.
7. Находим позицию разделителя L.
8. Если L = 0, выводим сообщение об ошибке, иначе продолжаем работу.
9. Копируем в поле названия команды L-1 символов.
10. Удаляем L символов в начале строки.
11. Цикл длиной 9.
12. Удаляем пробелы в начале.
13. Находим позицию разделителя L.
14. Если L = 0, выводим сообщение об ошибке, иначе продолжаем работу.
15. Копируем во временную строку L-1 символов.
16. Пытаемся преобразовать эту строку в число.
17. Если преобразование не удалось - выводим сообщение об ошибке, иначе - продолжаем работу.
18. Удаляем L символов в начале строки.
19. Конец цикла.
20. Удаляем пробелы в начале.
21. Пытаемся преобразовать оставшуюся часть строки в число.
22. Если преобразование не удалось - выводим сообщение об ошибке, иначе - продолжаем работу.

В качестве ваианта:
11. Дописываем разделитель в конец строки.
11а. Цикл длиной 10.
строки 20-22 - не нужны.
npl
Да забудьте про преобразование. Оставлю так, как есть. Как найти фигуриста с максимальным результатом для каждого общества?
andriano
Самый простой способ - перебором.

PS. А алгоритм разбора строки я бы порекомендовал подправить.
npl
Не получается найти максимальный элемент. Когда находится максимальный среди 10 оценок, там всё просто. А как сделать среди средних? Дайте конкретный пример.
andriano
Коль скоро для каждого фигуриста все равно вычисляется средняя оценка, то имеет смысл предусмотреть в структуре поле для ее хранения.
Ну и потом, естественно, перебирать эти поля в поисках максимума.
npl
Цитата(andriano @ 9.12.2007 22:38) *

Коль скоро для каждого фигуриста все равно вычисляется средняя оценка, то имеет смысл предусмотреть в структуре поле для ее хранения.
Ну и потом, естественно, перебирать эти поля в поисках максимума.

И как их перебирать. У меня не работает. Приведите свой код.
andriano
А ты не заметил, что твоя программа не совсем соответствует условию задачи?
В условии требуется анализировать общества (и именно их количество указано), а у тебя предусмотрен тип данных для описания фигуриста и нет типа данных для общества.
npl
Цитата(andriano @ 10.12.2007 20:57) *

А ты не заметил, что твоя программа не совсем соответствует условию задачи?
В условии требуется анализировать общества (и именно их количество указано), а у тебя предусмотрен тип данных для описания фигуриста и нет типа данных для общества.

Есть у меня тип данных для общества.
andriano
Пальчиком ткни.
npl
obsh:string[10];
вот тут, может хватить мудить, если б вы andriano знали, давно бы уже написали нужный мне код norespect.gif

 ! 
За речью следи.

andriano
Грубить не надо.
Помочь - могу, а писать код за тебя - не буду.

Вот это называется типом данных:
type
figurist=record
fio:string[10];
obsh:string[10];
ocenka:array[1..10] of integer;
end;

А вот это - полем в типе "figurist", имеющим тип "string[10]":
obsh:string[10];

Не следует поутать одно с другим.

Вообще-то алгоритм написания программы на каком либо языке программирования примерно такой:
- решить задачу ручками, отмечая про себя, какие действия при этом происходят,
- записать алгоритм действий по-русски,
- переписать на нужном языке программирования.

При обработке текстовых файлов, как правило, удобно оказывается действовать в следующем порядке:
- завести тип данных, хорошо описывающий входные данные,
- завести тип данных, хорошо описывающий выходные данные,
- считать входные данные в память,
- в памяти обработать входняе данные с целью заполнить поля выходного типа.
npl
"Спасибо", что не помогли, andriano. Но к счастью в этом мире есть добрые люди.
Michael_Rybak
"Спасибо" andriano от тебя заслуживает как минимум за потраченное на тебя время. Смени тон.
npl
Цитата(Michael_Rybak @ 12.12.2007 23:51) *

"Спасибо" andriano от тебя заслуживает как минимум за потраченное на тебя время. Смени тон.

Никто не заставлял его тратить на меня время. И вовсе я не грублю. Извините, если, что-то не так сказал, но нервы перед сессией накалены до предела.

Добавлено через 15 мин.
Огромное спасибо volvo!!!
Michael_Rybak
Цитата
Никто не заставлял его тратить на меня время.

Аааа, т.е. когда ты задаешь вопрос, я должен не отвечать, а сначала спросить тебя, заставляешь ты меня или нет? Т.к. если я отвечу не то, что ты бы ожидал услышать, то я в ответ получу "пустые разговоры" и "мудить". Какая прелесть.

Цитата
но нервы перед сессией накалены до предела.

Сочувствую (без сарказма). И тем не менее.
npl
Цитата(Michael_Rybak @ 13.12.2007 0:20) *

Аааа, т.е. когда ты задаешь вопрос, я должен не отвечать, а сначала спросить тебя, заставляешь ты меня или нет? Т.к. если я отвечу не то, что ты бы ожидал услышать, то я в ответ получу "пустые разговоры" и "мудить". Какая прелесть.

Отвечать или нет - это личное дело каждого. А если уж решил ответить, то отвечать надо по существу, а не уходить от вопроса.
Lapp
М
Господа, прошу прекратить перебранку. Тему закрывать не хочу, потому что она, по-видимому, еще нужна автору (если нет - скажи).

npl, прошу тебя понять, что замечания отвечавших тебе направлены на улучшение твоей программы, хотя ты этого можешь не понимать в настоящий момент.

andriano, прошу тебя быть более конкретным в ответах. Постарайся отвечать не только правильно, но и так, чтоб тебя поняли - чтобы поняли, что ты говоришь по существу.

К всем: побольше дружелюбия. А грубость прошу исключить совсем.

В дальнейшем прошу говорить только по теме
Спасибо.

andriano
"Пришел барин и всех рассудил." :D

[ ]

Мне кажется, вряд ли здесь кто-то не понимает по-русски. Скорее дело в другом: нужен текст на Паскале, а самому переводить с русского на Паскаль не хочтся, - пусть лучше это сделает кто-то другой!

Тем более, что исправлять явно указанный недостаток автор этой темы не захотел, решив, очевидно, что и так сойдет.
Между тем программа, работающая с текстовыми файлами, должна быть нечувствительна к количеству пробелов, разделяющих слова, т.е. совершенно одинаково обрабатывать "Иванов Динамо" и " Иванов Динамо ". Приведеная же программа, очевидно, с текстовыми файлами работать не умеет, а умеет только с файлами опредедленной структуры.

Теперь по поводу задачи в целом (заодно уважаемый volvo сможет сравнить со своим вариантом).

- Предусмотреть типы данных для фигуриста (в исходном коде уже есть) и для спортивного общества (название, Ф.И.О. ОДНОГО спортсмена, его средний результат).
- Описать переменную для спортсмена (уже есть), массив длины N для обществ (благо, в условии она задана. Можно потребовать, чтобы первой строкой в файле указывалось количество обществ: для учебных/олимпиадных задач - обычное дело. А можно и не требовать: вместо массива организовать список, выделяя память для каждого очередного элемента по мере их поступления) и целую переменную для длины заполненной части массива.
- написать функции (декомпозиция - великая вещь!) для:
а) разбора строки с заполнением полей "фигуриста": на входе - строка из файла, возвращает - подсчитанное среднее.
Функция должна уметь разбирать файлы вроде:

Иванов и.И. "Спартак" 1 2 3 4 5 6 7 8 9 10
Сидоров Иван Петрович "Крылья Советов" 3, 4, 5, 5, 7, 8, 9, 10, 11, 12
Мохаммед Ибн Али ПЕру де Оннорре "ООО Челси им. Абрамовича" 2;3;4;5;6;7;8;9;10;1
Смит Джон "Определитель Матрицы" 8.0,7.0, 9, 3., 4, 1.0, 7, 5,9,2
Петров-Водкин Кузьма С. "Спартак" 3,2 1,3,2 1,3 2,1 1,1

б) поиска и добавления обществ: на входе - строка-имя общества, на выходе - номер найденного общества в массиве.
Должна просматривать уже сформированную часть массива обществ, если не нашла - завести новое, обнулив все поля.

Порядок действия программы:
1. Открыть файл.
1а. При необходимости считать строку с количеством обществ и выделить память для массива.
2. Цикл до окончания файла:
- читаем строку
- разбираем ее
- находим номер общества
- если средний балл спортсмена найденного общества ниже, чем вновь считанного, заменяем все данные общества новым спортсменом
3. Закрыть файл.
4. Вывести в цикле на печать заполненный массив обществ.

Кстати, размещать в общедоступном месте (например, на форуме) програму без комментаиев - mauvais ton.
Должна быть минимум одна строка коментария на 5-7 строк кода.
Должны быть откомментированы все процедуры и функции: назначение и список параметров.
Должны быть откомментированы все новые типы и их поля, а также глобальные переменные.
Естественно, не должно быть коментариев типа:
r := sqrt(x*x + y*y); {присваиваем переменной r значение sqrt(x*x + y*y)}
Malice
Начнем тогда уж.. Внесу свою лепту для начала smile.gif

type
fig=record
fio:string;
obsh:string;
ocenka: array[1..10] of integer;
end;
...
procedure parse (s:string;var f:fig);
var i,n:integer;
begin
f.fio:=copy(s,1,pos ('"',s)-1);
delete(s,1,length(f.fio)+1);
f.obsh:='"'+copy(s,1,pos ('"',s)-1)+'"';
delete(s,1,length(f.obsh)-1);
for i:=1 to 10 do begin
while (not(s[1] in ['0'..'9'])) and (s>'') do delete (s,1,1);
n:=0;
while (s[1] in ['0'..'9']) and (s>'') do begin
n:=n*10+ord (s[1])-$30;
delete (s,1,1);
end;
f.ocenka[i]:=n;
end;
end;

andriano
Цитата(Malice @ 14.12.2007 11:27) *

Начнем тогда уж.. Внесу свою лепту для начала smile.gif

OK.
Несколько рекомендаций:
   ocenka: array[1..10] of integer;

Насколько я помню, в фигурном катании оценки являются числом в общем случае нецелым. Рекомендую:
   ocenka: array[1..10] of single;

procedure parse (s:string;var f:fig);

Вообще-то переменная f одна на всю программу, при этом временная и глобальная. Поэтому вряд ли имеет смысл передавать ее в качестве формального параметра. Впрочем, это дело вкуса.
А еще я рекомендовал сразу подсчитать средний балл и возвращать его как значение функции.
function parse (s:string): single;

Следующую строку:
f.obsh:='"'+copy(s,1,pos ('"',s)-1)+'"';

можно немного упростить.
f.obsh:='"'+copy(s,1,pos ('"',s));

Следующий код ориентирован на целые числа, кроме того, вместо:
    n:=n*10+ord (s[1])-$30;

правильнее было бы написать:
    n:=n*10+ord (s[1])-ord('0');

В любом случае, рекомендую в этом месте скопировать во временную строку все символы до разделителя или конца строки, а потом преобразовать строку в число.
Перед этим лучше всего сначала заменить все разделители на пробелы, а затем удалить все двойные пробелы.
Ну и под конец, естественно, подсчитать средний балл.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.