В поток записана последовательность целых чисел. Найти минимум и максимум и поменять их местами, не используя дополнительных потоков.
Начала я с того, что попыталась сосчитать первое число, чтоб было с чем сравнивать...
Проблема в том, что если в файле одно число - то оно фиксируется и выводиться (в компонент Memo) как надо, но если больше - приложение вылетает с ошибкой " '1-е число из файла' is not a valid integer value"..
структура файла:
11
22
56
...
и т.д
Объясните, как исправить, чтоб отработало без ошибок?
procedure TForm1.Convert;
var
i, j, k: Word;
c: Char;
l,numb,min,max: Integer;
str:string;
f: Boolean;
S: TStream; // переменная потокового типа
begin
S := TFileStream.Create(FName, fmOpenReadWrite);
//загружаем в поток типа FileStream содержимое файла FName
//тело алгоритма
with S do
begin
Position := 0; // установка указателя потока в начало
i := 0;
k := Size; // в k - размер потока в байтах
Read(c,1);
j:=1;
while (c<>#10)and(i<=k-1) do
begin
inc(i);
inc(j);
str:=str+c;
read(c,1);
end;
min:=StrToInt(str);
memo1.Lines.Add(IntToStr(min));
end
end;
while (c<>#13)and(i<=k-1) do // <--- Признак конца строки - это #13#10, а не наоборот...
while (c<>#13)and(i<=k-1) do // <--- Признак конца строки - это #13#10, а не наоборот...
procedure TForm1.Convert;
var
i, j, k: Word;
c: Char;
l,numb,min,max: Integer;
str:string;
f: Boolean;
S: TStream; // переменная потокового типа
begin
S := TFileStream.Create(FName, fmOpenReadWrite);
//загружаем в поток типа FileStream содержимое файла FName
with S do
begin
Position := 0; // установка указателя потока в начало
i := 0;
k := Size; // в k - размер потока в байтах
Read(c,1);
j:=1;
while (c<>#13)and(i<=k-1) do
begin
inc(i);
inc(j);
str:=str+c;
read(c,1);
end;
min:=StrToInt(str);
max:=StrToInt(str);
Position := i+1; // установка указателя потока после 1-го элемента
while i <> k do
begin
Read(c, 1);
inc(i);
j := 1;
while (c <> #13) and (i <= k - 1) do
begin
str:=str+c;
Read(c, 1);
inc(i);
inc(j);
end;
numb:=StrToInt(str);
if numb<min then min:=numb;
if numb>max then max:=numb;
end; {end while i<>k}
// загружаем в Memo1 содержимое преобразованного файла
//Memo1.Lines.LoadFromFile(FName);
memo1.Lines.Add(IntToStr(min)); {ну это просто для собственного контроля) }
memo1.Lines.Add(IntToStr(max));
end
end;
Во-первых, вот тут:
Position := i+1; // установка указателя потока после 1-го элемента
procedure TForm1.Convert;
var
i, k: Word;
c: Char;
numb,min,max: Integer;
str:string;
S: TStream; // переменная потокового типа
begin
S := TFileStream.Create(FName, fmOpenReadWrite);
min := MaxInt;
max := -MaxInt;
//загружаем в поток типа FileStream содержимое файла FName
with S do begin
Position := 0; i := 0;
k := Size;
repeat
c := #0; str := '';
while (i < k) do begin
read(c, 1);
if c = #13 then break;
inc(i); str := str + c;
end;
numb:=StrToInt(str);
if numb<min then min:=numb;
if numb>max then max:=numb;
Read(c, 1); // read #10
until Position = Size;
memo1.Lines.Add(IntToStr(min));
memo1.Lines.Add(IntToStr(max));
end; // with
end;
Добавила нахождение позиций максимального и минимального элемента, и запись элементов от этих позиции во вспомогательные..
Только не знаю, как записать вместо одного другое..Объясните пожалуста!
procedure TForm1.Convert;
var
i, j, k,pos_max, pos_min, dl_min, dl_max: Word;
c: Char;
numb,min,max: Integer;
str,help,help1:string;
S: TStream; // переменная потокового типа
begin
S := TFileStream.Create(FName, fmOpenReadWrite);
min := MaxInt;
max := -MaxInt;
//загружаем в поток типа FileStream содержимое файла FName
with S do begin
Position := 0; i := 0;
k := Size;
repeat
c := #0; str := '';
j:=0;
while (i < k) do begin
read(c, 1);
inc(j);
if c = #13 then break;
inc(i); str := str + c;
end;
numb:=StrToInt(str);
if numb<min then
begin
min:=numb;
pos_min:=i-j-1;
dl_min:=j;
end;
if numb>max then
begin
max:=numb;
pos_max:=i-j-1;
dl_max:=j;
end;
position:=pos_min;
for k:=pos_min to pos_min+dl_min do
begin
read(c,1);
help:=help+c;
end;
position:=pos_max;
for k:=pos_max to pos_max+dl_max do
begin
read(c,1);
help1:=help1+c;
end;
Read(c, 1); // read #10
until Position = Size;
memo1.Lines.Add(IntToStr(min));
memo1.Lines.Add(IntToStr(max));
end; // with
end;
И даже то, что дописала про нахождение позиций не работает - вылетает ошибка..
А про перезапись так и не могу понять...Пожалуста, объясните...
Вот что я добавила:перезаписала на место максимального миниальный..Но снова ошибка: " '' is not a valid integer value"..
Объясните, что я не так делаю...
Вот код для предыдущего сообщения..
procedure TForm1.Convert;
var
i, j, k, pos_max, pos_min: integer;
c: Char;
numb,min,max,mins,maxs: Integer;
str,help,help1:string;
S: TStream; // переменная потокового типа
begin
S := TFileStream.Create(FName, fmOpenReadWrite);
numb:=0;
min := MaxInt;
max := -MaxInt;
pos_max:=0;
pos_min:=0;
mins:=0;
maxs:=0;
//загружаем в поток типа FileStream содержимое файла FName
with S do begin
Position := 0; i := 0;
k := Size;
Edit1.Text:=IntToStr(k);
repeat
c := #0; str := '';
j:=0;
while (i < k) do begin
read(c, 1);
inc(i);
if c = #13 then break;
inc(j);
str := str + c;
end;
numb:=StrToInt(str);
if numb<min then
begin
min:=numb;
pos_min:=i-j;
mins:=j;
end;
if numb>max then
begin
max:=numb;
pos_max:=i-j;
maxs:=j;
end;
Read(c, 1); // read #10
inc(i);
until Position = Size;
position:=pos_min;
while (c<>#13) do
begin
position:=pos_min;
inc(pos_min);
read(c,1);
position:=pos_max;
inc(pos_max);
write(c,1);
end;
Free;
memo1.Lines.LoadFromFile(FName);
end; // with
end;
mins:=0;
...........
maxs:=0;
..............
mins:=j;
...........
maxs:=j;
Если минимальное и максимальное числа состоят из разного количества цифр - придется извращаться дополнительно...
...
//загружаем в поток типа FileStream содержимое файла FName
with S do begin
Position := 0; i := 0;
k := Size;
repeat
c := #0; str := '';
while (i < k) do begin
read(c, 1);
if c = #13 then break;
inc(i); str := str + c;
end;
numb:=StrToInt(str);
if numb<min then begin
min:=numb; pos_min := Position - length(str) - 1;
end;
if numb>max then begin
max:=numb; pos_max := Position - length(str) - 1;
end;
Read(c, 1); // read #10
until Position = Size;
Position := pos_min;
str := IntToStr(max);
for i := 1 to length(str) do begin
Write(str[i], 1);
end;
Position := pos_max;
str := IntToStr(min);
for i := 1 to length(str) do begin
Write(str[i], 1);
end;
end; // with
S.Destroy;
memo1.Lines.LoadFromFile(FName);
...
Угу... Только следить за тем, чтобы копирование шло в правильном направлении... Если pos_max > pos_min, то проще копировать символы "назад" (перемещая их ближе к концу потока), а если наоборот - то "вперед", перемещая ближе к началу...
Вот моя попытка разобрать случай, если кол-во цифр в максим. и миним. элементах не равно: пока сделала для случая если pos_max>pos_min...
Перезапись происходит, но на первоначальном месте максимального элемента я получаю минимальный элемент с некоторыми цифрами от максимального...
Объясните пожалуста, как это исправить?
procedure TForm1.Convert;
var
i, j, k, pos_max, pos_min: integer;
c: Char;
numb,min,max,dif: Integer;
str,help:string;
S: TStream; // переменная потокового типа
begin
S := TFileStream.Create(FName, fmOpenReadWrite);
numb:=0; dif:=0;
min := MaxInt;
max := -MaxInt;
pos_max:=0;
pos_min:=0;
help:='';
with S do begin
Position := 0; i := 0;
k := Size;
while (i<k) do
begin
read(c,1);
inc(i);
help:=help+c;
end;
edit1.Text:=inttostr(k);
Position := 0; i := 0;
k := Size;
repeat
c := #0; str := '';
while (i < k) do begin
read(c, 1);
if c = #13 then break;
inc(i); str := str + c;
end;
numb:=StrToInt(str);
if numb<min then begin
min:=numb; pos_min := Position - length(str) - 1;
end;
if numb>max then begin
max:=numb; pos_max := Position - length(str) - 1;
end;
Read(c, 1); // read #10
until Position = Size;
dif:=Length(IntToStr(max)) - Length(IntToStr(min));
if dif=0 then
begin
Position := pos_min;
str := IntToStr(max);
for i := 1 to length(str) do begin
Write(str[i], 1);
end;
Position := pos_max;
str := IntToStr(min);
for i := 1 to length(str) do begin
Write(str[i], 1);
end;
end {end if dif=0}
else
begin
if pos_max > pos_min then
begin
position:=pos_min+dif;
for i:=pos_min+2 to pos_max-1 do
Write(help[i], 1);
Position := pos_min;
str := IntToStr(max);
for i := 1 to length(str) do
Write(str[i], 1);
Position := pos_max;
str := IntToStr(min);
for i := 1 to length(str) do
Write(str[i], 1);
end {end if pos_max > pos_min}
else
begin
{дописать}
end; {end else pos_max > pos_min}
end; {end else of dif=0}
end; // with
S.Destroy;
memo1.Lines.LoadFromFile(FName);
end;
Пожалуста, объясните, как избавиться от лишних цифр, остающихся от максимального элемента, рядом с минимальным после изменения их порядка..??
Лень запускать Дельфи , я сделал эмуляцию работы с потоком при помощи строки на FPC:
uses sysutils;
const
s: string =
// '72'#13#10'21543'#13#10'57'#13#10'19'#13#10'14'#13#10'84'; (* 1 *)
'72'#13#10'14'#13#10'57'#13#10'19'#13#10'8874'#13#10'84'; (* 2 *)
var
pos_min, pos_max: integer;
i, j, min, max, delta: integer;
st: string;
begin
writeln(s);
(* // 1
pos_max := 5; max := 21543;
pos_min := 20; min := 14;
*)
// 2
pos_min := 5; min := 14;
pos_max := 17; max := 8874;
delta := length(inttostr(max)) - length(inttostr(min));
if pos_max < pos_min then begin // Первый случай
i := pos_max + length(inttostr(min));
while i < pos_min do begin
s[i] := s[i + delta]; inc(i);
end;
st := inttostr(min);
for i := 1 to length(st) do begin
s[pos_max + i - 1] := st[i]
end;
st := inttostr(max);
for i := 1 to length(st) do begin
s[pos_min - delta + i - 1] := st[i]
end;
end
else begin // Второй случай
i := pos_max + length(inttostr(min)) - 1;
while i - delta > pos_min do begin
s[i] := s[i - delta]; dec(i);
end;
st := inttostr(min);
for i := 1 to length(st) do begin
s[pos_max + delta + i - 1] := st[i]
end;
st := inttostr(max);
for i := 1 to length(st) do begin
s[pos_min + i - 1] := st[i]
end;
end;
writeln('final = ', s);
end.
Снова я что-то напутала...Результаты работы приложения далеко не те, какими должны быть..
Содержимое файла:
45
2
3
1
Результат:
45
2
3
145
Содержимое файла:
1
2
3
45
Результат:
1452
3
1
2
1
dif:=Length(IntToStr(max)) - Length(IntToStr(min));
if pos_max < pos_min then
begin
i := pos_max + length(IntToStr(min));
position:=i;
while i < pos_min do begin
help[i] := help[i + dif];
inc(i);
write(help[i],1);
end;
str := inttostr(min);
position:= pos_max + i - 1;
for i := 1 to length(str) do begin
//help[pos_max + i - 1] := str[i];
write(str[i],1);//write(help[pos_max + i - 1],1);
end;
str := inttostr(max);
position:= pos_min - dif + i - 1;
for i := 1 to length(str) do begin
//help[pos_min - dif + i - 1] := str[i];
write(str[i],1);//write(help[pos_min - dif + i - 1],1);
end;
end {end if pos_max < pos_min}
else
begin
i := pos_max + length(inttostr(min)) - 1;
position:=i;
while i - dif > pos_min do begin
help[i] := help[i - dif];
dec(i);
write(help[i],1);
end;
str := inttostr(min);
position:= pos_max + dif + i - 1;
for i := 1 to length(str) do begin
//help[pos_max + dif + i - 1] := str[i];
write(str[i],1);//write(help[pos_max + dif + i - 1],1);
end;
str := inttostr(max);
position:= pos_min + i - 1;
for i := 1 to length(str) do begin
//help[pos_min + i - 1] := str[i];
write(str[i],1);//write(help[pos_min + i - 1],1);
end;
end; {end else pos_max < pos_min}
...
delta := length(inttostr(max)) - length(inttostr(min));
if pos_max < pos_min then begin
i := pos_max + length(inttostr(min));
while i < pos_min do begin
S.Position := i + delta; S.Read(C, 1);
S.Position := i; S.Write(C, 1);
inc(i);
end;
str := inttostr(min);
S.Position := pos_max;
for i := 1 to length(str) do begin
S.Write(str[i], 1);
end;
str := inttostr(max);
S.Position := pos_min - delta;
for i := 1 to length(str) do begin
S.Write(str[i], 1);
end;
end
else begin
i := pos_max + length(inttostr(min));
while i - delta > pos_min do begin
S.Position := i - delta; S.Read(C, 1);
S.Position := i; S.Write(C, 1);
dec(i);
end;
str := inttostr(min);
S.Position := pos_max + delta;
for i := 1 to length(str) do begin
S.Write(str[i], 1);
end;
str := inttostr(max);
S.Position := pos_min;
for i := 1 to length(str) do begin
S.Write(str[i], 1);
end;
end;
...