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

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

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

Автор: Tribunal 8.04.2006 9:17

у меня есть две задачи:

1. Даны два целых числа i и j и файл вещественных чисел, содержащий ненулевую часть верхней треугольной матрицы (по строкам). Вывести порядок матрицы и ее элемент, расположенный в i-й строке и j-м столбце (строки и столбцы нумеруются от 1). Если требуемый элемент находится в нулевой части матрицы, то вывести 0; если элемент отсутствует, то вывести –1.

2. Дано целое число N и текстовый файл с именем Name1, содержащий один абзац текста, выровненный по левому краю. Отформатировать текст так, чтобы его ширина не превосходила N позиций, и выровнять текст по левому краю. Пробелы в конце строк удалить. Сохранить отформатированный текст в новом текстовом файле с именем Name2.

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

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

большая просьба помочь)

Автор: lapp 8.04.2006 9:54

Цитата(Tribunal @ 8.04.2006 5:17) *

проблема состоит в том,что у меня не получается сделать так,чтобы переносилось слово целиком,то есть первый случай.

Проблема твоя, мне кажется, абсолютно надумана. Ее вообще нету. То есть она есть, если читать файл строками. Но это делать не нужно, и тогда она просто исчезнет. Просто сделай себе процедуру, скажем, GetWord, которая читает из файла посимвольно, и формирует переменную OneWord типа string, добавляя в конец по символу. При натыкании на пробел или конец строки она останавливается, сформированное слово выводится в новый файл (если нужно, с переводом строки). Как видишь, проблемы просто не стало..

Да, если нужно сохранять число пробелов между словами в строчке, то процедуру GetWord нужно перемежать с процедурой GetSpace, которая читает пробелы и формирует переменную OneSpace, которую тоже нужно писать в файл, если это не переход на другую строку.

Автор: Tribunal 8.04.2006 12:52

а как читать из файла посимвольно?

Автор: klem4 8.04.2006 12:58

goto http://forum.pascal.net.ru/index.php?showtopic=3584


f : text;
ch : char;

...

while not(eof(f)) do begin
read(f, ch);
writeln(ch);
end;


- это для текстовых файлов.

Для типизированный ты кроме как покомпонентно больше никак читать не можешь.

Автор: volvo 8.04.2006 14:13

Цитата(lapp @ 8.04.2006 5:54)
То есть она есть, если читать файл строками. Но это делать не нужно, и тогда она просто исчезнет.

Я бы не стал так критически относиться к чтению текстового файла построчно... Проблема будет существовать только тогда, когда файл читается строками, и эти строки неправильно обрабатываются !!! А вот по скорости все-таки вариант со строками будет предпочтительнее, чем чтение посимвольно...

Автор: lapp 8.04.2006 14:38

Цитата(volvo @ 8.04.2006 10:13) *

Я бы не стал так критически относиться к чтению текстового файла построчно... Проблема будет существовать только тогда, когда файл читается строками, и эти строки неправильно обрабатываются !!! А вот по скорости все-таки вариант со строками будет предпочтительнее, чем чтение посимвольно...

В целом, конечно, чтение строками удобнее, но если говорить о скорости, то лучше читать поблочно, заполнять массив символов, а из него брать символы поштучно.. Так наиболее логично. Но при нормальном кеше скорость и так должна быть неплохая (не проверял smile.gif )

Автор: Tribunal 8.04.2006 15:59

вот то,что у меня получилось.только я тут не записываю во второй файл пока.
вообще,она компилируется,
но затем выдает ошибку...
вообще-то я делаю на делфи,но может что-то в самой программе неправильно?
а ошибка выдается до того,как выводить на экран результат
(Access violation at adress 004045A0 in module 'Project1.exe'.Read adress FFFFFFF7.)
Может подскажете,что за ошибка?))

Код
var
   n,m,ln,i,j:byte;
   x:char;
   oneword:string;
   s:array [1..40] of string;
   f:textfile;

   procedure getword(oneword:string);
   begin
    oneword:='';
    repeat
    read(f,x);
    oneword:=oneword+x;
    m:=m+1;
    until (x=' ') or eoln(f);
   end;

begin
read(n);
assign(f,'name1.txt');
reset(f);

ln:=0;
i:=1;
while (not eof(f)) do
  begin
    getword(oneword);
    ln:=ln+m;
    if ln>n then inc(i);
    s[i]:=s[i]+oneword;
         if eoln(f) then inc(i);
  end;
close(f);
for j:=1 to i do
   writeln(s[j]);
end;

Автор: volvo 8.04.2006 16:12

Ну, во-первых, у тебя глобальная и локальная переменные имеют одно и то же имя - oneword, и в этом случае ЛОКАЛЬНОЕ имя внутри процедуры имеет преимущество. То есть, из процедуры НИЧЕГО не будет возвращаться...

Или делай так:

procedure getword(VAR oneword:string);
или вообще работай только с глобальной переменной, то есть делай getword без параметров...

Автор: Tribunal 8.04.2006 16:22

я исправила,но ошибка остается той же(

Автор: volvo 8.04.2006 16:59

А попробуй все-же прогнать вот это (работа со строками) smile.gif
Вроде работает...

var
i, j, p, n: integer;
f: text;
s: array[1 .. 40] of string;
st, prev: string;

begin
n := 25; // readln(n) - для удобства отладки
assign(f,'name1.txt');
reset(f);

prev := ''; i := 0;
while not eof(f) do begin
readln(f, st);
st := prev + st; prev := '';

if length(st) > n then begin

repeat

writeln('st = ', st);
p := n;
while (p > 0) and (st[p] <> ' ') do dec(p);

if p = 0 then p := pred(n);
inc(i); s[i] := copy(st, 1, p);
prev := copy(st, succ(p), 255) + ' ';
delete(st, 1, p);

until length(prev) < n;

end
else begin
inc(i); s[i] := st;
end;
end;

for j := 1 to i do
// length - только для контроля результатов
writeln(s[j], ' len = ', length(s[j]));
end.

Автор: Tribunal 8.04.2006 17:30

я попробовала сделать так,но
она что-то странное делает с текстом blink.gif

Автор: volvo 8.04.2006 17:37

Ну, не знаю. Я пробовал на своем файле, все отработало, длины всех строк S меньше чем N, что, в принципе, и требовалось... Присоедини свой тестовый файл, я попробую на нем.

Автор: Tribunal 8.04.2006 17:59

ээ...сейчас почему-то ругается на эту строку

while (p > 0) and (st[p] <> ' ') do dec(p);

Автор: volvo 8.04.2006 18:02

Значит, что-то изменила в программе. Знаешь, я не телепат. И если ты показываешь какие-то куски, которые у тебя не работают (причем неизвестно с какими входными данными, и какова ВООБЩЕ ПОЛНАЯ программа), то я тебе ничем помочь не могу.

Не хочешь показывать ВЕСЬ код вместе со входными данными - ищи ошибки сама.

Автор: Tribunal 8.04.2006 18:25

разница лишь в том,что я делаю это в делфи,
и я удалила вот эту строку

repeat
writeln('st = ', st); { <---- }
p := n;


а вот текстовый файл,на котором я всё это тестирую.

я проверяла на паскале.там действительно всё работает.
а у меня нет((


Прикрепленные файлы
Прикрепленный файл  name1.txt ( 365 байт ) Кол-во скачиваний: 259

Автор: Tribunal 8.04.2006 19:01

вот вся программа в целом

прикрепила заново


Прикрепленные файлы
Прикрепленный файл  files.rar ( 3.86 килобайт ) Кол-во скачиваний: 205

Автор: volvo 8.04.2006 19:49

Файл заново присоедини - архив битый, ошибка при распаковке...

Автор: volvo 8.04.2006 20:38

В следующий раз будь внимательнее при наборе текста, ОК?
Вот что ДОЛЖНО было быть (и я именно это и привел в своей программе), закомментировано - то, что было у тебя:

procedure TForm1.Button2Click(Sender: TObject);
var
n,p,i,j:byte;
st,prev:string;

begin
n:=StrToInt(Edit1.Text);
reset(f);
prev:='';
i:=0;
while not eof(f) do
begin
readln(f,st);
st:= prev+st;

// prev:=prev+st;

prev:='';
if length(st)>n then
begin
// while not eof(f) do begin

repeat

p := n;
while (p > 0) and (st[p] <> ' ') do dec(p);

if p = 0 then p := pred(n);
inc(i);
s[i] := copy(st, 1, p);

prev := copy(st, succ(p), 255) + ' ';
delete(st, 1, p);
until length(prev) < n;
// end;
end
else begin
inc(i);
s[i]:=st;
end;
end;

// Это я добавил позже, сразу не обратил внимание, что теряется "хвост" текста
if st <> '' then begin
inc(i);
s[i] := st;
end;

for j:=1 to i do
Memo2.Lines.Append(s[j]+inttostr(length(s[j])));

end;
Все нормально работает...

Автор: Tribunal 8.04.2006 22:35

спасибо,я буду внимательнее...(

но теперь этот "хвост" теряется,но не везде...

Автор: Tribunal 9.04.2006 8:38

всё,спасибо большое))
с этой задачей разобралась))

Автор: Tribunal 9.04.2006 10:09

прошу прощения,но
у меня вновь возникли вопросы..
дело в том что программа не может выполнить
нужные операции для n<12, если я не ошибаюсь.
почему это происходит?

и еще вопрос:а для чего нужно

if (p=0) then p:=pred(n);
?

и почему
  if st<>'' then begin
inc(i);
s[i]:=st;
end;

работает только вне цикла
while not eof(f) do
....
end;

?

пожалуйста,помогите разобраться((

Автор: volvo 9.04.2006 12:30

Цитата(Tribunal @ 9.04.2006 6:09)
дело в том что программа не может выполнить
нужные операции для n<12, если я не ошибаюсь. почему это происходит?
Не знаю, я проверял только при n >= 25... Попробую подставить маленькие значения - потом напишу, что происходит...

Цитата(Tribunal @ 9.04.2006 6:09)
а для чего нужно
if (p=0) then p:=pred(n);
?

А подумай, когда, собственно, p может быть равно 0? По-моему, есть только один случай, когда это может произойти - если в строке есть только одно слово, более длинное чем N... В этом случае нам надо, чтобы слово было "разрезано" по N-му символу, так? А в программе есть запись:
prev := copy(st, succ(p), 255) + ' ';
Чтобы не делать лишних If ... Then ... Else, я просто присвоил в p значение N - 1, и это удовлетворяет всем условиям...

Цитата(Tribunal @ 9.04.2006 6:09)
почему
  if st<>'' then begin
inc(i);
s[i]:=st;
end;

работает только вне цикла
while not eof(f) do
....
end;

?
Ну, а это - как раз и есть тот самый "хвост", про который я сразу забыл. А "хвост" остается только после обработки всего файла, в самом конце. Вот я и проверяю это уже ПОСЛЕ цикла
While not eof(f) do

Автор: volvo 9.04.2006 12:59

Добавлено:

Так, ну причина того, что это все не работало с N < 12 очень прозаическая - размерности массива S просто напросто не хватало для того, чтобы он мог вместить все строки smile.gif Поскольку реализация идет на Дельфи - я СВОЙ код переписал с использованием динамических массивов вот так:

var
s: array of string;

...

procedure TForm1.Button2Click(Sender: TObject);
var
i, j, p, n: integer;
st, prev: string;

procedure add_string(str: string);
begin
setlength(s, length(s) + 1);
s[length(s) - 1] := str;
end;

begin
n := StrToInt(Edit1.Text); // n = 10
reset(f);

prev := '';
setlength(s, 0);
while not eof(f) do begin
readln(f, st);
st := prev + st; prev := '';

if length(st) > n then begin

repeat

p := n;
while (p > 0) and (st[p] <> ' ') do dec(p);

if p = 0 then p := pred(n);
add_string( copy(st, 1, p) );
prev := copy(st, succ(p), 255) + ' ';
delete(st, 1, p);

until length(prev) < n;

end
else add_string( st );

end;

if st <> '' then add_string( st );

for j := 0 to length(s) - 1 do
Memo2.Lines.Append(s[j] + inttostr(length(s[j])));

setlength(s, 0); // Освобождаем S
end.
и все заработало (если ты что-то меняла после того, как я привел предыдущий вариант - внеси соответствующие изменения и сюда...)

Автор: Tribunal 9.04.2006 13:26

большое спасибо за объяснения!=)
теперь всё понятно=)

я в начале этой темы приводила условие еще одной задачи.
вот то,что я сделала.
но там выдается ошибка о том,что
чтение из файла идет после его закрытия,но
я проверила этот факт.
вроде всё открывается и закрывается в нужных местах...
что не так?посмотрите,пожалуйста...))


Прикрепленные файлы
Прикрепленный файл  matrix_file.rar ( 3.58 килобайт ) Кол-во скачиваний: 146

Автор: volvo 9.04.2006 13:41

А тебя не смущает тот факт, что ты записываешь в файл одно число, а читать из того же файла пытаешься несколько чисел? ;)

P.S. Все-таки, тему я передвину в Дельфи...

Автор: Tribunal 12.04.2006 16:48

volvo, а можно попросить вас словесно хотя бы кратко объяснить, как
действует программа, которую вы привели , а то вроде бы всё понятно,
а когда начинаю объяснять путаюсь и сама ничего не понимаю. unsure.gif
прошу вас,объясните,а то получается так,что алгоритм
понятен мне только кусками...а хотелось бы хорошо с ним разобраться

Автор: Tribunal 12.04.2006 21:25

спасибо.
уже разобралась сама=)))
ура,ура,ура smile.gif