Форум программистов, компьютерный форум, киберфорум
Pascal (Паскаль)
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
Заблокирован
1

Внешняя сортировка бинарного файла (чтение после конца файла невозможно)

06.06.2014, 20:02. Показов 1615. Ответов 10
Метки нет (Все метки)

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

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{Вариант 21.
Создать бинарный файл, содержащий натуральные числа, величина которых не 
превосходит 10^9, заполнив его случайной информацией. Если в файле есть хотя бы 
одно трехзначное число, все цифры которого одинаковы, упорядочить файл по 
невозрастанию. Имя исходного файла, имя упорядоченного файла и размер исходного 
файла программа должна получать через командную строку.}
program lab14;
 
{Аргументы коммандной строки: имя исходного файла, имя выходного файла,
размер исходного файла}
 
 
{Вывод бинарного файла на экран}
procedure showBinFile(filename: string); 
var f : file of Integer;
    n: Integer;
begin
    assign(f, filename);
    reset(f);
    writeln(filename, ':');
    while not Eof(f) do begin
        read(f, n);
        write(n, ' ');
    end;
    writeln('');
    close(f);
end;
 
{Проверка, что все цифры числа равны или различны}
function EqualDigits(n: Integer): Boolean;
var one: Integer;
    two: Integer;
    three: Integer;
begin
    n := abs(n);
    one := (n mod 100) mod 10;
    two := (n mod 100 - (n mod 100) mod 10) div 10;
    three := (n - n mod 100) div 100;
    EqualDigits := (one = two) and (two = three);
end;
 
var file_in:    file of LongInt;
    file_out:   file of longint;
    check: Boolean;
    size: Integer;
    i,j: LongInt;
    x,y: LongInt;
    n: Integer;
begin
    assign(file_in, paramstr(1));   reset(file_in);
    assign(file_out, paramstr(2));  rewrite(file_out);
    size := StrToInt(paramstr(3));
    check := false;
    
    {Заполнение файла натуральными числами}
    randomize;
    while (size > 0)  do begin
        n := random(1000);
        if n > 0 then begin
            write(file_in, n);
            dec(size);
        end;
    end;
    write(file_in, 111);
    
    {Проверка условия: есть ли в файле трехзначное число,
    состоящее из одинаковых цифр}
    reset(file_in);
    repeat
        read(file_in, x);
        if ((x >= 100) and (x <= 999)) and EqualDigits(x) then 
            check := true;
        write(file_out, x);
    until eof(file_in);
    
    {Сортировка}
    reset(file_out);
    if check then begin
        for i:=0 to filesize(file_out)-1 do
            for j:=i+1 to filesize(file_out) do begin
                seek(file_out, i); read(file_out, x);
                seek(file_out, j); read(file_out, y);
                if x < y then begin
                    seek(file_out, i); write(file_out, y);
                    seek(file_out, j); write(file_out, x);
                end;
            end;
    end;
 
 
close(file_in); 
close(file_out);
 
ShowBinFile(paramstr(1));
ShowBinFile(paramstr(2));
end.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.06.2014, 20:02
Ответы с готовыми решениями:

Чтение чисел из файла. Чтение после конца потока невозможно
Товарищи, помогите. В Pascal'e я не силен, так что не бейте меня ногами, но есть задача: написать...

Ошибка при чтении файла: Чтение после конца потока невозможно
Всем добрый вечер! Пытаюсь считать данные из rtf файла и загрузить их в excel файл. Но выпадает...

Ошибка "Чтение после конца потока невозможно" при чтении из файла с помощью BinaryReader
private void ShowFromFile_Click(object sender, EventArgs e) { ...

Чтение после конца потока невозможно
Ошибку выдаёт в 33й строке :cry: using System; using System.IO; namespace...

10
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
06.06.2014, 22:46 2
Размер файла надо брать не из параметра командной строки, а определять по самому файлу:
вместо:
Pascal
52
  size := StrToInt(paramstr(3));
надо написать:
Pascal
52
  size := FileSize(file_in);
Кроме этого, в задании сказано:
Создать бинарный файл, содержащий натуральные числа, величина которых не
превосходит 10^9 ...
Это означает, что тип Integer здесь не подходит. Т. к. в Turbo/Borland Pascal его наибольшее значение:
2^15 = 32768 < 10^9.
Надо взять другой тип - тип Longint. Его наибольшее значение:
2^31 = 2147483648 > 10^9.

Добавлено через 1 минуту
И ещё, т. к., в задании говорится про бинарный файл:
Создать бинарный файл...
то, возможно, следует использовать тип File, а не File of Longint.
0
Заблокирован
07.06.2014, 14:40  [ТС] 3
Размер файла надо брать не из параметра командной строки, а определять по самому файлу:
вместо:
В задании сказано, что файл еще нужно создать, и не уточняется, что для этого нужно писать отдельную утилу. Значит, файл должна создавать моя программа при старте, и для этого размер файла надо передать через командную строку.

Это означает, что тип Integer здесь не подходит.
Просто я решил заполнять файл числами, которые не превосходят 999, иначе в последовательности почти не встретятся трехзначные числа из одинаковых цифр.

то, возможно, следует использовать тип File, а не File of Longint
А в чем тут разница?

Добавлено через 7 минут
Кстати, вчера ошибки прекратились, когда я в коде сортировки заменил
Код
for j:=i+1 to filesize(file_out) do begin
на
Код
for j:=i+1 to filesize(file_out)-1 do begin
Это корректно?. Вчера полчаса гуглил различные варианты сортировки, и код вроде моего почти не встречался. У меня индексы начинаются с 0, а там, где пишут
Код
for j:=i+1 to filesize(file_out) do begin
они начинались с 1. И сама форма записи с j:=i+1 почему-то редкая.
0
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
07.06.2014, 16:11 4
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
В задании сказано, что файл еще нужно создать, и не уточняется, что для этого нужно писать отдельную утилу. Значит, файл должна создавать моя программа при старте, и для этого размер файла надо передать через командную строку.
Тогда в коде надо заменить:
Pascal
1
reset(file_in);
на:
Pascal
1
rewrite(file_in);
Потому что при вызове reset(file_in) открывается уже существующий файл. И может оказаться, что этого файла нет. Или может случиться так, что размер уже существующего файла file_in больше значения, заданного в параметре Size. И тогда далее код будет работать с бОльшим количеством компонентов, чем указано в Size. Потому, что в коде конец данных в файле определяется не по значению Size, а по значению Eof(file_in).
Ещё при переборе элементов файла надо всё-таки цикл repeat заменить на while. Через цикл while содержимое файла будет правильно обработано, даже если файл пуст. Понятно, что в программе не предполагается создавать пустой файл, тем не менее, код должен быть надёжным.
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
Кстати, вчера ошибки прекратились, когда я в коде сортировки заменил
Pascal
1
for j:=i+1 to filesize(file_out) do begin
на
Pascal
1
for j:=i+1 to filesize(file_out)-1 do begin
Это корректно?
Да - всё правильно сделано.
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
У меня индексы начинаются с 0
Всё верно. Элементы файла нумеруются по смещению от начала файла. Смещение от начала файла - это количество элементов, которые расположены "слева" от текущего элемента. Первый элемент файла имеет смещение = 0, смещение последнего элемента файла = FileSize(F) - 1. Именно с такой индексацией работает функция Seek(), например.
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
то, возможно, следует использовать тип File, а не File of Longint
А в чем тут разница?
Разница в том, что содержимое бинарного файла не привязано к какому-либо типу данных. Такую привязку должен сделать сам программист. Кроме этого, содержимое бинарного файла можно читать/записывать блоками, состоящими из множества записей. Это очень ускоряет работу, если размер файла большой.
Ну в общем, этот момент, наверное, лучше у преподавателя уточнить. В задании сформулировано так:
Создать бинарный файл, содержащий натуральные числа, величина которых не
превосходит 10^9 ...
Я лично посчитал бы, что здесь имеется в виду именно тип File.
Вот если бы формулировка была такая:
Создать файл, элементами которого являются натуральные числа, величина которых не
превосходит 10^9 ...
то, здесь уже имеется в виду тип файла: File of Longint.
Но лучше всё-таки уточнить у преподавателя - как следует это понимать.
0
Заблокирован
07.06.2014, 16:48  [ТС] 5
Разница в том, что содержимое бинарного файла не привязано к какому-либо типу данных. Такую привязку должен сделать сам программист. Кроме этого, содержимое бинарного файла можно читать/записывать блоками, состоящими из множества записей. Это очень ускоряет работу, если размер файла большой.
Бинарный и типизированный файл это разные вещи, что ли? А если открыть их в текстовом редакторе, в них все равно будет один и тот же двоичный код.
Тогда как изменить логику программы, если объявить файлы как File? Размер элементов тогда ведь неизвестен, надо задать его каким-то образом.
0
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
07.06.2014, 17:17 6
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
Бинарный и типизированный файл это разные вещи, что ли?
Типы таких файлов - разные. А содержимое может быть одинаковым. Типы определяют лишь способ обработки.
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
А если открыть их в текстовом редакторе, в них все равно будет один и тот же двоичный код.
Да, верно - содержимое одинаковым будет.
Цитата Сообщение от Eru Iluvatar Посмотреть сообщение
Тогда как изменить логику программы, если объявить файлы как File? Размер элементов тогда ведь неизвестен, надо задать его каким-то образом.
Да, размер будем задавать при открытии/создании файла:
Pascal
1
2
3
4
5
6
7
8
var
  file_in, file_out : File;
...
begin
...
  {Создаём файл, открываем его и задаём наименьший блок чтения/записи равным
  размеру переменной типа Longint.}
  Rewrite(file_in, SizeOf(Longint));
Далее надо заменить:
Pascal
1
write(file_in, n);
на:
Pascal
1
BlockWrite(file_in, n, 1);
Заменить:
Pascal
1
read(file_in, x);
на:
Pascal
1
BlockRead(file_in, x, 1);
И т. д. Остальной код, где используется Seek(), FileSize(), Eof() - останется без изменений.
1
Заблокирован
08.06.2014, 14:46  [ТС] 7
Rewrite(file_in, SizeOf(Longint));
Только сегодня обнаружил, что функции с такими параметрами нет ни в ПаскальАБЦ, ни в FPC.
0
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
08.06.2014, 15:40 8
Во Free Pascal - есть. Вот в Pascal ABC нет таких функций.
0
Заблокирован
08.06.2014, 16:29  [ТС] 9
Теперь программа скомпилировалась, но при запуске из консоли возникает runtime error по какому-то адресу.


Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
{Вариант 21.
Создать бинарный файл, содержащий натуральные числа, величина которых не 
превосходит 10^9, заполнив его случайной информацией. Если в файле есть хотя бы 
одно трехзначное число, все цифры которого одинаковы, упорядочить файл по 
невозрастанию. Имя исходного файла, имя упорядоченного файла и размер исходного 
файла программа должна получать через командную строку.}
program lab14;
 
{Аргументы коммандной строки: имя исходного файла, имя выходного файла,
размер исходного файла}
 
 
{Вывод бинарного файла на экран}
procedure showBinFile(filename: string); 
var f : file;
    n: LongInt;
begin
    assign(f, filename);
    reset(f);
    writeln(filename, ':');
    while not Eof(f) do begin
        BlockRead(f, n, 1);
        write(n, ' ');
    end;
    writeln('');
    close(f);
end;
 
{Проверка того, что все цифры трехзначного числа равны или различны}
function EqualDigits(n: Integer): Boolean;
var one: Integer;
    two: Integer;
    three: Integer;
begin
    n := abs(n);
    one := (n mod 100) mod 10;
    two := (n mod 100 - (n mod 100) mod 10) div 10;
    three := (n - n mod 100) div 100;
    EqualDigits := (one = two) and (two = three);
end;
 
var file_in:    file;
    file_out:   file;
    check: Boolean;
    size, err: Integer;
    i,j: LongInt;
    x,y: LongInt;
    n: LongInt;
begin
    assign(file_in, paramstr(1));   rewrite(file_in, SizeOf(Longint));
    assign(file_out, paramstr(2));  rewrite(file_out, SizeOf(Longint));
    val(paramstr(3), size, err);
    check := false;
    
    {Заполнение файла натуральными числами}
    randomize;
    while (size > 0)  do begin
        n := random(1000);
        if n > 0 then begin
            BlockWrite(file_in, n, 1);
            dec(size);
        end;
    end;
    
    {Проверка условия: есть ли в файле трехзначное число,
    состоящее из одинаковых цифр}
    reset(file_in);
    repeat
        BlockRead(file_in, x, 1);
        if ((x >= 100) and (x <= 999)) and EqualDigits(x) then 
            check := true;
        BlockWrite(file_out, x, 1);
    until eof(file_in);
    
    {Сортировка}
    reset(file_out);
    if check then begin
        for i:=0 to filesize(file_out)-1 do
            for j:=i+1 to filesize(file_out)-1 do begin
                seek(file_out, i); BlockRead(file_out, x, 1);
                seek(file_out, j); BlockRead(file_out, y, 1);
                if x < y then begin
                    seek(file_out, i); BlockWrite(file_out, y, 1);
                    seek(file_out, j); BlockWrite(file_out, x, 1);
                end;
            end;
    end;
 
 
close(file_in); 
close(file_out);
 
ShowBinFile(paramstr(1));
ShowBinFile(paramstr(2));
end.
0
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
08.06.2014, 18:32 10
Я подправил. Там надо было все вызовы Reset() написать в таком виде: Reset(<F>, SizeOf(Longint)). И ещё увеличил вероятность появления трёхзначного числа с одинаковыми цифрами во всех десятичных разрядах.
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
{Вариант 21.
Создать бинарный файл, содержащий натуральные числа, величина которых не
превосходит 10^9, заполнив его случайной информацией. Если в файле есть хотя бы
одно трехзначное число, все цифры которого одинаковы, упорядочить файл по
невозрастанию. Имя исходного файла, имя упорядоченного файла и размер исходного
файла программа должна получать через командную строку.}
program lab14;
 
{Аргументы коммандной строки: имя исходного файла, имя выходного файла,
размер исходного файла}
 
{Вывод бинарного файла на экран}
procedure showBinFile(filename: string); 
var f : file;
    n: LongInt;
begin
    assign(f, filename);
    reset(f, SizeOf(Longint));
    writeln(filename, ':');
    while not Eof(f) do begin
        BlockRead(f, n, 1);
        write(n, ' ');
    end;
    writeln('');
    close(f);
end;
 
{Проверка того, что все цифры трехзначного числа равны или различны}
function EqualDigits(n: Integer): Boolean;
var one: Integer;
    two: Integer;
    three: Integer;
begin
    n := abs(n);
    one := (n mod 100) mod 10;
    two := (n mod 100 - (n mod 100) mod 10) div 10;
    three := (n - n mod 100) div 100;
    EqualDigits := (one = two) and (two = three);
end;
 
var file_in:    file;
    file_out:   file;
    check: Boolean;
    size, err: Integer;
    i,j: LongInt;
    x,y: LongInt;
    n: LongInt;
begin
    assign(file_in, paramstr(1));   rewrite(file_in, SizeOf(Longint));
    assign(file_out, paramstr(2));  rewrite(file_out, SizeOf(Longint));
    val(paramstr(3), size, err);
    check := false;
 
    {Заполнение файла натуральными числами}
    randomize;
    while (size > 0)  do begin
        if (Size > 1) and (Random(Size) = 0) then
          n := 111
        else
          n := random(1000);
        if n > 0 then begin
            BlockWrite(file_in, n, 1);
            dec(size);
        end;
    end;
 
    {Проверка условия: есть ли в файле трехзначное число,
    состоящее из одинаковых цифр}
    reset(file_in, SizeOf(Longint));
    while not eof(file_in) do
    begin
        BlockRead(file_in, x, 1);
        if ((x >= 100) and (x <= 999)) and EqualDigits(x) then
            check := true;
        BlockWrite(file_out, x, 1);
    end;
    
    {Сортировка}
    reset(file_out, SizeOf(Longint));
    if check then begin
        for i:=0 to filesize(file_out)-1 do
            for j:=i+1 to filesize(file_out)-1 do begin
                seek(file_out, i); BlockRead(file_out, x, 1);
                seek(file_out, j); BlockRead(file_out, y, 1);
                if x < y then begin
                    seek(file_out, i); BlockWrite(file_out, y, 1);
                    seek(file_out, j); BlockWrite(file_out, x, 1);
                end;
            end;
    end;
 
 
close(file_in); 
close(file_out);
 
ShowBinFile(paramstr(1));
ShowBinFile(paramstr(2));
readln;
end.
1
Заблокирован
09.06.2014, 00:39  [ТС] 11
Большое спасибо за помощь!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.06.2014, 00:39

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Чтение после конца потока невозможно
var f:file of integer; i,a,max,l:integer; begin assign(f,'f.txt'); reset(f); i:=0; while...

Чтение после конца потока невозможно
Всем привет, есть функция, которая должна выводить данные из data файла, которые были в неё...

Чтение после конца потока невозможно
Файл для чтения создан в Паскале. type base=record n1,n2:string; tel:string; ...

Чтение после конца потока невозможно
Здравствуйте, упёрся в ошибку по потокам, не могу никак найти решение. Проблема в процедуре...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.