Консультация № 170048
01.07.2009, 02:26
0.00 руб.
01.07.2009, 05:47
0 7 2
Здравствуйте, уважаемые эксперты. Помоги пожалуйста решить такую задачу: даны два файла. связать содержимое обоих файлов и записать все это в отдельный файл. Например:
Код:

Файл 1 Файл 2 Конечный файл
1 2 1
3 4 2
5 6 3
4
5
6

Обсуждение

Неизвестный
01.07.2009, 02:30
общий
Немного исказился пример
Код:

Файл 1 Файл 2 Конечный файл
1 2 1
3 4 2
5 6 3
4
5
6

Вот как должно быть на самом деле
давно
Мастер-Эксперт
425
4118
01.07.2009, 05:48
общий
Андрей fult:
Т.е. даны два файла с целыми числами. В третьем файле нужно получить их объединение с сортировкой, правильно?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
01.07.2009, 15:46
общий
А содержимое исходных файлов предполагать упорядоченным?
Неизвестный
01.07.2009, 15:52
общий
Если полагать, то сделал - сейчас напишу упорядочение текстовых исходных. То есть, я полагаю файлы текстовыми. Если б были типизированными, то проблем было бы намного меньше
Неизвестный
01.07.2009, 23:58
общий
это ответ
Здравствуйте, Андрей fult.
Здравствуйте, Андрей fult.
Код в приложении. Есть комментарии - не поймете что - пишите тут. Поясню
Исходные файлы перед объединением сортируются по возрастанию
Если все нормально, программа ничего на экран не выводит - если нужно, легко исправить. (Справитесь?)
Содержимое in1.txt
Код:
5
3
1

Содержимое in2.txt
Код:
2
4
6
7
8
-2
9

Содержимое выходного файла out.txt
Код:
-2
1
2
3
4
5
6
7
8
9

Обратите внимание, что исходные файлы изменяются - становятся отсортированными
С недопустимыми числами не экспериментировал. Могут быть сбои, хотя поначалу и это предусматривал

Приложение:
{Вариант, в котором нет ограничений на размер файлов.
ВРАНЬЁ, конечно. Строки пересчитываются и используется тип Integer, так что,
сейчас в файле исходном каждом может быть не более 32565 чисел
Но, ессно, заменив типы переменных можно существенно увеличить, а можно и не считать числа
- просто длиннее станет код}

CONST
FileName1: String = 'in1.txt';
FileName2: String = 'in2.txt';
FileOut : String = 'out.txt';

procedure SortTextFile(aFileName: String);
{Файлы должны быть закрыты}
CONST
TempFileName = 'temp.txt';
BackFileName = 'back.txt';
var
f_src, f_back, f_temp: Text;
i, i_min, number_no, number_no_min, number_count: Integer;
{используется для упорядочения текстовых файлов}

begin
{Алгоритм такой: прочитываем файл - запоминаем значение наименьшего,
записываем во временный файл
опять читаем сначала исходный и записываем в резервный,
если в первый раз встречаем значение, равного наименьшему, то
в резервный не записываем
Затем переименовываем резервный в исходный и опять, пока}
assign(f_src, aFileName);
{$I-} Reset(f_src); {$I+}
if IOResult <> 0 then Exit;

Assign(f_temp, TempFileName);
Rewrite(f_temp); {отсортированный файл}

{Подсчитаем число чисел в файле}
number_count:=0;
while NOT SeekEOF(f_src) do
begin
Read(f_src, i);
inc(number_count);
end;
while number_count > 0 do begin
Reset(f_src);
{Ищем номер минимального числа}
Read(f_src, i_min);
number_no := 1;
number_no_min := 1;

While NOT SeekEOF(f_src) do begin
Read(f_src, i);
inc(number_no);
if i < i_min then begin
number_no_min := number_no;
i_min := i
end
end;
WriteLn(f_temp, i_min);

{Теперь нужно исключить это число из исходного
Переписываем в резервный, а затем переименовываем в исходный}
Assign(f_back, BackFileName);
Rewrite(f_back); number_no := 0;
Reset(f_src);
While NOT SeekEOF(f_src) do begin
Read(f_src, i); inc(number_no);
if number_no <> number_no_min then
WriteLn(f_back, i)
end;
dec(number_count);
Flush(f_back);
Close(f_back);
Close(f_src);
Erase(f_src);
Rename(f_back, aFileName);
end;
Flush(f_temp);
Close(f_temp);

{Теперь удалить старый и переименовать временный в исходный}
Erase(f_src);
Rename(f_temp, aFileName);
end;

TYPE
TtoRead = (file1, file2);

VAR
f1, f2, fout: Text;
i1, i2: Integer;
isf1, isF2: Boolean; {Флаги, что имеются считанные данные}
toRead: TtoRead; {Что считывать: файл1 или файл2}
BEGIN
Assign(f1, FileName1);
{$I-} Reset(f1);{$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть файл ', FileName1);
WriteLn('Работа программы завершена. Нажмите любую клавишу');
ReadKey; Halt(1)
end;
Assign(f2, FileName2);
{$I-} Reset(f2);{$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть файл ', FileName2);
WriteLn('Работа программы завершена. Нажмите любую клавишу');
ReadKey; Halt(1)
end;
Assign(fout, FileOut);
{$I-} Rewrite(fout);{$I+}
if IOResult <> 0 then begin
WriteLn('Не могу создать файл ', FileOut);
WriteLn('Работа программы завершена. Нажмите любую клавишу');
ReadKey; Halt(1)
end;
{завершается цикл как только закончатся ОБА файла
Если встретится ошибка чтения, то просто ЭТОТ файл перестает
считываться
Начальное считывание}
{$R+}
{включаем проверку на принадлежность диапазону. По умолчанию выключена}

{Упорядочение исходных файлов}
Close(f1); Close(f2);

SortTextFile(FileName1);
SortTextFile(FileName2);

Reset(f1); Reset(f2);
{Объединение упорядоченных}
isF1 := NOT SeekEOF(F1);
isF2 := NOT SeekEOF(F2);
if NOT(isF1) and NOT(isF2) then
begin {ни один не считан. Допустим в обоих ошибки чтения}
WriteLn('Не удается считывать информацию ни из одного файла');
WriteLn('Работа программы завершается. Нажмите любую клавишу');
ReadKey;
Close(f1); Close(f2); Close(fout);
Halt(2)
end;
if isF1 then begin
{$I-} Read(f1, i1); {$I+}
isF1 := IOResult = 0;
end;
if isF2 then begin
{$I-} Read(f2, i2); {$I+}
isF2 := IOResult = 0;
end;

repeat
while isF1 do begin
if NOT isF2 then
WriteLn(fout, i1)
else
begin
if (i1 <= i2) then
WriteLn(fout, i1)
else
Break;
end;
if SeekEOF(F1) then
isF1 :=FALSE
else begin
{$I-} Read(f1, i1); {$I+}
isF1 := IOResult = 0;
end
end;
while isF2 do begin
if NOT isF1 then
WriteLn(fout, i2)
else
begin
if (i2 <= i1) then
WriteLn(fout, i2)
else Break;
end;
if SeekEOF(F2) then
isF2 := False
else
begin
{$I-} Read(f2, i2); {$I+}
isF2 := IOResult = 0;
end
end;
until (NOT isF1) and (NOT isF2); {условия выхода}

Close(f1);
Close(f2);
Flush(fout); {Вывод в текстовый файл медленный - нужно дождаться}
Close(fout);
END.
Неизвестный
01.07.2009, 23:58
общий
это ответ
Здравствуйте, Андрей fult.
Здравствуйте, Андрей fult.
Код в приложении. Есть комментарии - не поймете что - пишите тут. Поясню
Исходные файлы перед объединением сортируются по возрастанию
Если все нормально, программа ничего на экран не выводит - если нужно, легко исправить. (Справитесь?)
Содержимое in1.txt
Код:
5
3
1

Содержимое in2.txt
Код:
2
4
6
7
8
-2
9

Содержимое выходного файла out.txt
Код:
-2
1
2
3
4
5
6
7
8
9

Обратите внимание, что исходные файлы изменяются - становятся отсортированными
С недопустимыми числами не экспериментировал. Могут быть сбои, хотя поначалу и это предусматривал

Приложение:
{Вариант, в котором нет ограничений на размер файлов.
ВРАНЬЁ, конечно. Строки пересчитываются и используется тип Integer, так что,
сейчас в файле исходном каждом может быть не более 32565 чисел
Но, ессно, заменив типы переменных можно существенно увеличить, а можно и не считать числа
- просто длиннее станет код}

CONST
FileName1: String = 'in1.txt';
FileName2: String = 'in2.txt';
FileOut : String = 'out.txt';

procedure SortTextFile(aFileName: String);
{Файлы должны быть закрыты}
CONST
TempFileName = 'temp.txt';
BackFileName = 'back.txt';
var
f_src, f_back, f_temp: Text;
i, i_min, number_no, number_no_min, number_count: Integer;
{используется для упорядочения текстовых файлов}

begin
{Алгоритм такой: прочитываем файл - запоминаем значение наименьшего,
записываем во временный файл
опять читаем сначала исходный и записываем в резервный,
если в первый раз встречаем значение, равного наименьшему, то
в резервный не записываем
Затем переименовываем резервный в исходный и опять, пока}
assign(f_src, aFileName);
{$I-} Reset(f_src); {$I+}
if IOResult <> 0 then Exit;

Assign(f_temp, TempFileName);
Rewrite(f_temp); {отсортированный файл}

{Подсчитаем число чисел в файле}
number_count:=0;
while NOT SeekEOF(f_src) do
begin
Read(f_src, i);
inc(number_count);
end;
while number_count > 0 do begin
Reset(f_src);
{Ищем номер минимального числа}
Read(f_src, i_min);
number_no := 1;
number_no_min := 1;

While NOT SeekEOF(f_src) do begin
Read(f_src, i);
inc(number_no);
if i < i_min then begin
number_no_min := number_no;
i_min := i
end
end;
WriteLn(f_temp, i_min);

{Теперь нужно исключить это число из исходного
Переписываем в резервный, а затем переименовываем в исходный}
Assign(f_back, BackFileName);
Rewrite(f_back); number_no := 0;
Reset(f_src);
While NOT SeekEOF(f_src) do begin
Read(f_src, i); inc(number_no);
if number_no <> number_no_min then
WriteLn(f_back, i)
end;
dec(number_count);
Flush(f_back);
Close(f_back);
Close(f_src);
Erase(f_src);
Rename(f_back, aFileName);
end;
Flush(f_temp);
Close(f_temp);

{Теперь удалить старый и переименовать временный в исходный}
Erase(f_src);
Rename(f_temp, aFileName);
end;

TYPE
TtoRead = (file1, file2);

VAR
f1, f2, fout: Text;
i1, i2: Integer;
isf1, isF2: Boolean; {Флаги, что имеются считанные данные}
toRead: TtoRead; {Что считывать: файл1 или файл2}
BEGIN
Assign(f1, FileName1);
{$I-} Reset(f1);{$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть файл ', FileName1);
WriteLn('Работа программы завершена. Нажмите любую клавишу');
ReadKey; Halt(1)
end;
Assign(f2, FileName2);
{$I-} Reset(f2);{$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть файл ', FileName2);
WriteLn('Работа программы завершена. Нажмите любую клавишу');
ReadKey; Halt(1)
end;
Assign(fout, FileOut);
{$I-} Rewrite(fout);{$I+}
if IOResult <> 0 then begin
WriteLn('Не могу создать файл ', FileOut);
WriteLn('Работа программы завершена. Нажмите любую клавишу');
ReadKey; Halt(1)
end;
{завершается цикл как только закончатся ОБА файла
Если встретится ошибка чтения, то просто ЭТОТ файл перестает
считываться
Начальное считывание}
{$R+}
{включаем проверку на принадлежность диапазону. По умолчанию выключена}

{Упорядочение исходных файлов}
Close(f1); Close(f2);

SortTextFile(FileName1);
SortTextFile(FileName2);

Reset(f1); Reset(f2);
{Объединение упорядоченных}
isF1 := NOT SeekEOF(F1);
isF2 := NOT SeekEOF(F2);
if NOT(isF1) and NOT(isF2) then
begin {ни один не считан. Допустим в обоих ошибки чтения}
WriteLn('Не удается считывать информацию ни из одного файла');
WriteLn('Работа программы завершается. Нажмите любую клавишу');
ReadKey;
Close(f1); Close(f2); Close(fout);
Halt(2)
end;
if isF1 then begin
{$I-} Read(f1, i1); {$I+}
isF1 := IOResult = 0;
end;
if isF2 then begin
{$I-} Read(f2, i2); {$I+}
isF2 := IOResult = 0;
end;

repeat
while isF1 do begin
if NOT isF2 then
WriteLn(fout, i1)
else
begin
if (i1 <= i2) then
WriteLn(fout, i1)
else
Break;
end;
if SeekEOF(F1) then
isF1 :=FALSE
else begin
{$I-} Read(f1, i1); {$I+}
isF1 := IOResult = 0;
end
end;
while isF2 do begin
if NOT isF1 then
WriteLn(fout, i2)
else
begin
if (i2 <= i1) then
WriteLn(fout, i2)
else Break;
end;
if SeekEOF(F2) then
isF2 := False
else
begin
{$I-} Read(f2, i2); {$I+}
isF2 := IOResult = 0;
end
end;
until (NOT isF1) and (NOT isF2); {условия выхода}

Close(f1);
Close(f2);
Flush(fout); {Вывод в текстовый файл медленный - нужно дождаться}
Close(fout);
END.
Прикрепленные файлы:
Неизвестный
02.07.2009, 18:59
общий
Спасибо большое
Форма ответа