Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Работа с файлами

Автор: npl 9.12.2007 16:47

Даны названия N различных обществ (N заданное число), фигуристы которых участовали в соревновании. О каждом фигуристе известно: фамилия, название общества и 10 оценок за его выступление. Требуется для каждого спортивного общества определить фигуриста, показавшего наивысший результат, считая его единственным. Баллы, полученные фигуристом, подсчитываются следующим образом: максимальная и минимальная оценки отбрасываются, а из остальных формируется средняя. При вводе данных обеспечить уникальность наименований обществ и обязательную принадлежность фигуриста к одному из них.

Автор: volvo 9.12.2007 17:41

... и что? Хорошее задание, только зачем ты привел его? Чтоб тебе все сделали и выложили "на тарелочке"? Иди в Поиск, там есть задачи про хоккейные и футбольные команды, группы студентов с оценками на экзамене, разбирайся, как они сделаны, начинай делать свое задание, что будет непонятно - приходи, спрашивай...

А так просто вываливать задание безо всяких попыток решить (и показать остальным, что ты пытался, но у тебя не получилось) - это по меньшей мере обрекать тему на забвение...

Автор: npl 9.12.2007 17:48

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

Автор: andriano 9.12.2007 18:28

Цитата(npl @ 9.12.2007 13:48) *

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

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

Автор: npl 9.12.2007 18:38

Вот код


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 9.12.2007 21:20

Народ, откликнитесь.

Автор: andriano 9.12.2007 23:00

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

Автор: npl 9.12.2007 23:05

Цитата(andriano @ 9.12.2007 19:00) *

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

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

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

Автор: andriano 9.12.2007 23:20

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

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

Автор: npl 9.12.2007 23:22

Если ФИО меньше 10, то там оставшееся место заполнено пробелом.

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

Добавлено через 1 мин.

Цитата(andriano @ 9.12.2007 19:20) *

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

И как это сделать?

Автор: andriano 9.12.2007 23:29

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

Автор: npl 9.12.2007 23:32

Я сам составлял файл. Задачу надо решать для конкретного своего файла.

Добавлено через 13 мин.
andriano, может уже предложите конкретные решения, а не пустые слова?

Автор: andriano 10.12.2007 0:09

Цитата(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 10.12.2007 0:12

Да забудьте про преобразование. Оставлю так, как есть. Как найти фигуриста с максимальным результатом для каждого общества?

Автор: andriano 10.12.2007 0:15

Самый простой способ - перебором.

PS. А алгоритм разбора строки я бы порекомендовал подправить.

Автор: npl 10.12.2007 1:36

Не получается найти максимальный элемент. Когда находится максимальный среди 10 оценок, там всё просто. А как сделать среди средних? Дайте конкретный пример.

Автор: andriano 10.12.2007 2:38

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

Автор: npl 10.12.2007 2:49

Цитата(andriano @ 9.12.2007 22:38) *

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

И как их перебирать. У меня не работает. Приведите свой код.

Автор: andriano 11.12.2007 0:57

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

Автор: npl 11.12.2007 1:09

Цитата(andriano @ 10.12.2007 20:57) *

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

Есть у меня тип данных для общества.

Автор: andriano 11.12.2007 1:32

Пальчиком ткни.

Автор: npl 11.12.2007 2:25

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

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


Автор: andriano 13.12.2007 0:46

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

Вот это называется типом данных:

type
figurist=record
fio:string[10];
obsh:string[10];
ocenka:array[1..10] of integer;
end;

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

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

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

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

Автор: npl 13.12.2007 3:33

"Спасибо", что не помогли, andriano. Но к счастью в этом мире есть добрые люди.

Автор: Michael_Rybak 13.12.2007 3:51

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

Автор: npl 13.12.2007 3:55

Цитата(Michael_Rybak @ 12.12.2007 23:51) *

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

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

Добавлено через 15 мин.
Огромное спасибо volvo!!!

Автор: Michael_Rybak 13.12.2007 4:20

Цитата
Никто не заставлял его тратить на меня время.

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

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

Сочувствую (без сарказма). И тем не менее.

Автор: npl 13.12.2007 17:11

Цитата(Michael_Rybak @ 13.12.2007 0:20) *

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

Отвечать или нет - это личное дело каждого. А если уж решил ответить, то отвечать надо по существу, а не уходить от вопроса.

Автор: Lapp 13.12.2007 18:24

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

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

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

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

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


Автор: andriano 14.12.2007 13:40

"Пришел барин и всех рассудил." :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 14.12.2007 15:27

Начнем тогда уж.. Внесу свою лепту для начала 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 14.12.2007 22:17

Цитата(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');

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