Помощь - Поиск - Пользователи - Календарь
Полная версия: Поиск однофамильцев в типизированном файле
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
alex9910
Нужно вывести из типизированного ф-ла однофамильцев. Типизированный файл состоит из типа запись.

Например: при запросе фамилии Петрова выводились все стоки с фамилиями Петрова и Петров.
или при запросе : Петров выводились и Петров и Петрова.
Как можно сделать проверку на подстановку или отброс окончаний?

Всем заранее спасибо!

procedure print_usl;
begin
reset(F);
if (filesize(F) <> 0) then
begin
repeat
clrscr;
Writeln('Введите ФИО студента ');
readln(Str_v);
{cp:=copy()}
Chek_DL_SL(Str_v, 15);
Chek_FIO(Str_v);
if f1 = false then
write(' ');
until (f1 = true) and (f2=true);
str_v:=str_v;

K:=0;
While not EoF (F) do begin
read(F,S);

IF str_v[length(str_v)]= 'а' then
begin
s.fio_stud:=copy(str_v, 1, length(str_v)-1);
end else
begin
s.fio_stud:=str_v;

print_shapka;
k:=1;

writeln;
Write( #179);
Write( S.FIO_Stud:16);
Write( #179);
Write( S.Stip:9);
Write( #179);
Write( S.FIO_mum:14);
Write( #179);
Write( S.zp_mum:8);
Write( #179);
Write( S.FIO_ot:14);
Write( #179);
Write( S.zp_ot:8);
Write( #179);
writeln;

end;
end;
if k=0 then writeln('Студентов с фамилией ',str_v, ' не найдено' );
readkey;
clrscr;
close(F);
Osh;

end
else
begin
clrscr;
Writeln('Файл пуст. Записи не найдены');
close(F);
osh;
readkey;
clrscr;
end;
end;
IUnknown
Ну вот и сделай так:

IF str_v[length(str_v)]= 'а' then
test_fio:=copy(str_v, 1, length(str_v)-1);
else
test_fio:=str_v;


, а потом в цикле сравнивай test_fio с текущей фамилией:

if (F.FIO_Stud = test_fio) or (F.FIO_Stud = test_fio + 'a') then
begin
Inc(k);
end;
(Можно было бы искать через if pos(F.FIO_Stud, test_fio) > 0 then, но будут ложные срабатывания: "Петров" и "Петровский" будут считаться похожими, а это не так).

Но это не самая хорошая идея, сравнивать напрямую. Очень много несоответствий начнется. Скажем, фамилия "Ланская" - как сравнить ее с "Ланской"? smile.gif Проверять на 'ая'? Найдется несколько других примеров, с которыми ни проверка на "а", ни проверка на "ая" не сработают. Т.е., тебе придется делать много проверок. У меня есть более интересная идея. Есть такое понятие, как "расстояние Левенштейна" - т.е., мера похожести двух строк. (Это не важно сейчас, но высчитывается эта мера как количество шагов, которые нужно проделать для преобразования одной строки в другую. Чем меньше это количество - тем строки ближе. Будет логично предположить, что для мужских/женских фамилий дистанция Левенштейна не будет больше 2, т.е., максимум за 2 шага из одной фамилии можно получить другую). Я бы все-таки подумал в эту сторону. Чем добавлять десятки проверок, и не факт, что будут учтены все сочетания, проще сделать подсчет этой дистанции, и проверять ее. Подумай над этим. Это из области Fuzzy Search, т.е., Нечеткого Поиска, а у тебя как раз поиск нечеткий, у тебя не жестко заданная строка, которую надо найти, а нужно "найти что-то, очень похожее вот на это".
alex9910
Не получилось. Или я не понял куда подставить этоsad.gif

Вот весь проект.. Конечно сложно там во всем наверное будет быстро разобраться.. Но может получится.

Эта процедура в модуле под названием PECHAT а запуск происходит через MENU
IUnknown
Я имел в виду что-то типа:
{Процедура печати по условию}
procedure print_usl;
var test_fio : string;
begin
reset(F);
if (filesize(F) <> 0) then
begin
repeat
// Мне все равно ,что у тебя происходит в Chek_DL_SL и Chek_FIO, я исхожу из предположения
// что после ввода и проверок в str_v находится фамилия студента, которого надо найти в базе
clrscr;
Writeln('Введите ФИО студента ');
readln(Str_v);
Chek_DL_SL(Str_v, 15);
Chek_FIO(Str_v);
if f1 = false then
write(' ');
until (f1 = true) and (f2=true);

// Вот от этой фамилии отсекаешь 'a', если она там есть
if str_v[length(str_v)]= 'а' then
test_fio:=copy(str_v, 1, length(str_v)-1)
else
test_fio:=str_v;

K:=0;
reset(F);
print_shapka; // Выводишь ДО ЦИКЛА шапку
while not EoF (F) do
begin
read(F,S); // а потом в цикле сравниваешь текущую фамилию с test_fio и test_fio + 'a'
if (S.FIO_Stud = test_fio) or (S.FIO_Stud = test_fio + 'а') then
begin
k:=1;
writeln;
Write( #179);
Write( S.FIO_Stud:16);
Write( #179);
Write( S.Stip:9);
Write( #179);
Write( S.FIO_mum:14);
Write( #179);
Write( S.zp_mum:8);
Write( #179);
Write( S.FIO_ot:14);
Write( #179);
Write( S.zp_ot:8);
Write( #179);
writeln;
end;
end;
close(F);
Osh;
if k=0 then
writeln('Студентов с фамилией ',str_v, ' не найдено' );
readkey;
clrscr;
end
else
begin
clrscr;
Writeln('Файл пуст. Записи не найдены');
close(F);
osh;
readkey;
clrscr;
end;
end;
Извини, но разбираться, где ты там описываешь все переменные (и почему переменные не описываются как можно ближе к месту использования - это первое условие для написания менее глючной программы, а ты все норовишь затолкать их в другой модуль, ибо в этом же я подобных переменных не обнаружил) мне лень, да и не хочется. Неинтересно это, я тебе указывал уже на ошибки, ты В ТОЧНОСТИ их повторяешь. Как об стену горох. На фиг мне, спрашивается, опять тут расписывать на десяток страниц, КАК НАДО, если ты делаешь КАК ПОПАЛО???
alex9910
Увы делалось как было написано в задании....

Все в программе хорошо, но проверяет то только на фамилию
Если в файле фамилии без инициалов то все прекрасно! А вот с инициалами ничего не находит....
IUnknown
Цитата
Увы делалось как было написано в задании....
Задание не определяет (по крайней мере - не должно определять) способ решения. И не определяет, где описывать переменные, и переменные какого типа. И где ставить комментарии тоже не определяет задание. Задание ставит задачу, которую необходимо решить. А уж как ее программист будет решать - это не его (задания) дело. Твою программу можно влет сократить в 5 раз. В пять!!! Это что, задание так требует, чтобы в файле Redakt.pas было больше 600 строк? Да там и 150 по хорошему - перебор. Так что не надо валить на задание. Все зависит от того, кто это задание выполняет.

Цитата
Если в файле фамилии без инициалов то все прекрасно! А вот с инициалами ничего не находит....
А надо было сразу думать, а не пихать фамилию вместе с инициалами в одно поле. Ты что думаешь, это оттого, что программисту нечего было делать в любой нормальной базе фамилия хранится отдельно, имя - отдельно, а отчество - отдельно? Или ты думал, что все программисты недоумки, а ты вот один такой мудрый, догадался все запихать в одно поле, чтоб особо не заморачиваться? Ну, догадался запихать - догадывайся и переделывать теперь smile.gif
Гость
Цитата(IUnknown @ 3.06.2012 14:33) *

Задание не определяет (по крайней мере - не должно определять) способ решения. И не определяет, где описывать переменные, и переменные какого типа. И где ставить комментарии тоже не определяет задание. Задание ставит задачу, которую необходимо решить. А уж как ее программист будет решать - это не его (задания) дело. Твою программу можно влет сократить в 5 раз. В пять!!! Это что, задание так требует, чтобы в файле Redakt.pas было больше 600 строк? Да там и 150 по хорошему - перебор. Так что не надо валить на задание. Все зависит от того, кто это задание выполняет.

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



Печать по условию задал препод однофамильцев найти....
А что редакт на 600 строк. Я даже не знаю как по другому сократить до 150 wacko.gif
alex9910
"Это что, задание так требует, чтобы в файле Redakt.pas было больше 600 строк? "

Нет задание требует редактирование в виде меню а как по другому его организовывать не знаю.. Да и уже некогда, еще диаграмму нужно делать... ypriamii.gif
Как-то реально вывести гистограмму (столбиковую диаграмму) допустим сколько студентов получают стипендию до 980 ру. и сколько больше 1000 например?
Jakeline
And I thuohgt I was the sensible one. Thanks for setting me straight.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.