Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с файлами
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Tribunal
у меня есть две задачи:

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

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

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

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

большая просьба помочь)
Lapp
Цитата(Tribunal @ 8.04.2006 5:17) *

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

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

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


f : text;
ch : char;

...

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


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

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

Я бы не стал так критически относиться к чтению текстового файла построчно... Проблема будет существовать только тогда, когда файл читается строками, и эти строки неправильно обрабатываются !!! А вот по скорости все-таки вариант со строками будет предпочтительнее, чем чтение посимвольно...
Lapp
Цитата(volvo @ 8.04.2006 10:13) *

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

В целом, конечно, чтение строками удобнее, но если говорить о скорости, то лучше читать поблочно, заполнять массив символов, а из него брать символы поштучно.. Так наиболее логично. Но при нормальном кеше скорость и так должна быть неплохая (не проверял smile.gif )
Tribunal
вот то,что у меня получилось.только я тут не записываю во второй файл пока.
вообще,она компилируется,
но затем выдает ошибку...
вообще-то я делаю на делфи,но может что-то в самой программе неправильно?
а ошибка выдается до того,как выводить на экран результат
(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
Ну, во-первых, у тебя глобальная и локальная переменные имеют одно и то же имя - oneword, и в этом случае ЛОКАЛЬНОЕ имя внутри процедуры имеет преимущество. То есть, из процедуры НИЧЕГО не будет возвращаться...

Или делай так:
procedure getword(VAR oneword:string);
или вообще работай только с глобальной переменной, то есть делай getword без параметров...
Tribunal
я исправила,но ошибка остается той же(
volvo
А попробуй все-же прогнать вот это (работа со строками) 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
я попробовала сделать так,но
она что-то странное делает с текстом blink.gif
volvo
Ну, не знаю. Я пробовал на своем файле, все отработало, длины всех строк S меньше чем N, что, в принципе, и требовалось... Присоедини свой тестовый файл, я попробую на нем.
Tribunal
ээ...сейчас почему-то ругается на эту строку

while (p > 0) and (st[p] <> ' ') do dec(p);
volvo
Значит, что-то изменила в программе. Знаешь, я не телепат. И если ты показываешь какие-то куски, которые у тебя не работают (причем неизвестно с какими входными данными, и какова ВООБЩЕ ПОЛНАЯ программа), то я тебе ничем помочь не могу.

Не хочешь показывать ВЕСЬ код вместе со входными данными - ищи ошибки сама.
Tribunal
разница лишь в том,что я делаю это в делфи,
и я удалила вот эту строку
repeat
writeln('st = ', st); { <---- }
p := n;


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

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

прикрепила заново
volvo
Файл заново присоедини - архив битый, ошибка при распаковке...
volvo
В следующий раз будь внимательнее при наборе текста, ОК?
Вот что ДОЛЖНО было быть (и я именно это и привел в своей программе), закомментировано - то, что было у тебя:
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
спасибо,я буду внимательнее...(

но теперь этот "хвост" теряется,но не везде...
Tribunal
всё,спасибо большое))
с этой задачей разобралась))
Tribunal
прошу прощения,но
у меня вновь возникли вопросы..
дело в том что программа не может выполнить
нужные операции для 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
Цитата(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
Добавлено:

Так, ну причина того, что это все не работало с 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
большое спасибо за объяснения!=)
теперь всё понятно=)

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

P.S. Все-таки, тему я передвину в Дельфи...
Tribunal
volvo, а можно попросить вас словесно хотя бы кратко объяснить, как
действует программа, которую вы привели , а то вроде бы всё понятно,
а когда начинаю объяснять путаюсь и сама ничего не понимаю. unsure.gif
прошу вас,объясните,а то получается так,что алгоритм
понятен мне только кусками...а хотелось бы хорошо с ним разобраться
Tribunal
спасибо.
уже разобралась сама=)))
ура,ура,ура smile.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.