В поток записана последовательность целых чисел. Найти минимум и максимум и поменять их местами, не используя дополнительных потоков.
Начала я с того, что попыталась сосчитать первое число, чтоб было с чем сравнивать... Проблема в том, что если в файле одно число - то оно фиксируется и выводиться (в компонент 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;
volvo
24.04.2008 20:03
Цитата
как исправить, чтоб отработало без ошибок?
Вот так:
while (c<>#13)and(i<=k-1) do // <--- Признак конца строки - это #13#10, а не наоборот...
18192123
24.04.2008 20:53
Цитата(volvo @ 24.04.2008 17:03)
Вот так:
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;
volvo
24.04.2008 21:25
Во-первых, вот тут:
Цитата
Position := i+1; // установка указателя потока после 1-го элемента
Почему увеличиваешь на 1? Надо на 2, #13#10 - это 2 символа...
Во-вторых, надо при чтении следующего числа сбрасывать str в пустую строку...
А вообще, я бы сделал так:
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;
18192123
24.04.2008 22:14
Цитата(volvo @ 24.04.2008 18:25)
А вообще, я бы сделал так:
Спасибо за объяснение! С этим ясно..
А как теперь переставить местами найденные элементы? Наверное можно "запоминать" кол-во символов для каждого из них ещё в процессе поиска, а ещё нужно позицию мах и мин отследить...А как это осуществить?? И как в принципе осуществить саму перезапись?
18192123
24.04.2008 23:48
Добавила нахождение позиций максимального и минимального элемента, и запись элементов от этих позиции во вспомогательные.. Только не знаю, как записать вместо одного другое..Объясните пожалуста!
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;
18192123
25.04.2008 2:09
И даже то, что дописала про нахождение позиций не работает - вылетает ошибка.. А про перезапись так и не могу понять...Пожалуста, объясните...
18192123
25.04.2008 2:31
Вот что я добавила:перезаписала на место максимального миниальный..Но снова ошибка: " '' is not a valid integer value"..
Объясните, что я не так делаю...
18192123
27.04.2008 16:30
Вот код для предыдущего сообщения..
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/maxs? Нет... Вот когда будешь использовать - компилятор будет обрабатывать их изменение...
Вот отработавший код (для случая, когда min и max содержат одинаковое число цифр!!!):
... //загружаем в поток типа 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); ...
Если минимальное и максимальное числа состоят из разного количества цифр - придется извращаться дополнительно...
18192123
27.04.2008 17:03
Цитата(volvo @ 27.04.2008 13:42)
Если минимальное и максимальное числа состоят из разного количества цифр - придется извращаться дополнительно...
А как быть в этом случае? Сдвигать остальное на разницу между длинами максимального и минимального элементов?
volvo
27.04.2008 17:11
Угу... Только следить за тем, чтобы копирование шло в правильном направлении... Если pos_max > pos_min, то проще копировать символы "назад" (перемещая их ближе к концу потока), а если наоборот - то "вперед", перемещая ближе к началу...
18192123
27.04.2008 17:18
Цитата(volvo @ 27.04.2008 14:11)
...то проще копировать символы "назад" (перемещая их ближе к концу потока), а если наоборот - то "вперед", перемещая ближе к началу...
а как это лучше (разумнее) сделать?
18192123
27.04.2008 19:13
Вот моя попытка разобрать случай, если кол-во цифр в максим. и миним. элементах не равно: пока сделала для случая если 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;
18192123
27.04.2008 21:17
Пожалуста, объясните, как избавиться от лишних цифр, остающихся от максимального элемента, рядом с минимальным после изменения их порядка..??
volvo
27.04.2008 22:35
Лень запускать Дельфи , я сделал эмуляцию работы с потоком при помощи строки на FPC:
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;
(сначала - первый случай (pos_max < pos_min), потом - второй... Вроде ничего лишнего в строке-результате нет)... В принципе, можно пошаманить и сделать все без двух веток if/else, но так как есть - более понятен алгоритм, поэтому я оставил без "шаманства".
18192123
27.04.2008 23:34
Снова я что-то напутала...Результаты работы приложения далеко не те, какими должны быть..
Содержимое файла: 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}
Уже и не знаю, что я снова не правильно делаю..Объясните пожалуста!..
volvo
28.04.2008 0:05
... 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; ...
Содержимое файла: 72 11245 57 19 12 84
в Memo: 72 12 57 19 11245 84
Что я делаю не так?
18192123
28.04.2008 0:36
Цитата(volvo @ 27.04.2008 21:05)
Что я делаю не так?
Всё так)) Спасибо большое!!)
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.