Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с файлами...
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Akella
Короче задание такое: Создать файл, заполненный целочисленными яислами в диапозоне [-100;100]. Удалить из файла все положительные числа!

У меня короче получаеться вот что: ввожу например 5, т.е. это генирируется 5 чисел. И получается что действие происходит только над четными элементами файла(начиная с 0-го). Например есть числа -10 -11 10 10 -15, то в результате останеться -10 и -15, а -11 куда-то пропадает... помогите... что я только не перепробывал сделать - не получается!

program  _7_14;    
uses crt;    
var    f : file of integer;     
i,n,a : integer;       
begin    clrscr;    
randomize;    
assign(f,'myfile.dat');    
rewrite(f);    
writeln('n=');    
read(n);     
for i:=1 to n do begin      
a:=random(200)-100;       
write(f,a);     
end;     
seek(f,0);       
while not eof(f) do begin         
read(f,a);         
write(a,' ');       
end;       
seek(f,0);         
while not eof(f) do begin  	  
read(f,a);  	   
if a>0 then seek(f,filepos(f)+1)  	      
else begin  		
write(f,a);  		
writeln(a,' ');    	      
end;  	   
end;           
end.   close(f);  
end.
Unconnected
Мне кажется,тут лучше использовать тип text.
volvo
Цитата
И получается что действие происходит только над четными элементами файла(начиная с 0-го)
Угу... А почему - сам виноват:
while not eof(f) do begin
  read(f,a);	   
  if a>0 then seek(f,filepos(f)+1) { <--- Вот тут ошибка }
  else begin
    write(f,a);
    writeln(a,' ');
  end;
end;

(ты уже прочел число из файла, значит указатель передвинулся на следующий элемент автоматически. Зачем ты передвигаешь его еще дальше? Ну, и потом... Тебе надо не напечатать все числа, кроме положительных, а удалить положительные из файла. Этого ты даже не пытаешься сделать... А нужно для этого всего навсего завести еще одну переменную LastNeg, которая будет хранить смещение последнего правильного НЕположительного числа в файле. Идешь дальше, как только встретил очередное отрицательное - записал его на эту, сохраненную позицию и увеличил ее на 1... А в самом конце - Truncate(LastNeg), чтобы отсечь все лишнее)

Кстати, у тебя файл не закрывается... Предпоследнего End-а не должно быть...

Добавлено через 1 мин.
Цитата
Мне кажется,тут лучше использовать тип text.
С чего бы? Чтоб места занимал больше? Или потому что кто-то не умеет работать с ДРУГИМИ файлами? Мне вот вообще кажется, что на другом языке эта задача решается проще, и что? Это не повод советовать автору писать не на Паскале...
Akella
Цитата(volvo @ 26.11.2008 23:19) *

завести еще одну переменную LastNeg, которая будет хранить смещение последнего правильного НЕположительного числа в файле.

что-то я вот это предложение не понял=)) особенно " хранить смещение последнего правильного НЕположительного числа в файле"....
volvo
Смотри:

{ ... заполнил файл ... }
reset(f); { Перешел на начало файла }

LastNeg := -1; { Самое начало, еще не было обработано ничего }
while not eof(f) do begin
  read(f, a); { Читаем очередное число из файла }
  if a < 0 then begin { Отрицательное ? }
    CurrPos := FilePos(f); { Это нам и надо: запоминаем, где мы БЫЛИ. Продолжать будем отсюда же }
    inc(LastNeg); { Увеличиваем счетчик отрицательных чисел ... }
    Seek(f, LastNeg); { ... и переходим на ту позицию, куда очередное число должно быть записано }
    write(f, a); { Собственно, записываем число }
    Seek(f, CurrPos); { И возвращаемся туда, где были, чтобы продолжить сканировать файл }
  end;
end;

Seek(f, LastNeg + 1); { А теперь устанавливаем указатель за последним отрицательным числом }
Truncate(f); { ... и "отсекаем" хвост }
reset(f); { Для сохранности данных... Да и вообще, потом надо печатать содержимое файла }

Akella
огромное спасибо, все понятно мне разжевали....
Akella
а как мне посчитать конечную сумму получившихся цифр по аски таблице, при этом мне надо открыть файл как нетипизированный.....?
volvo
Каких цифр? У тебя нет никаких цифр, у тебя есть числа, представленные НЕ текстом, а двоичным кодом (машинное представление). Что именно тебе надо посчитать?
Akella
мне надо посчитать сумму кодов, которыми зашифрованы числа...
начинаться должно как-то так ( это продолжение этой проги)
close(f);    
assign(g,'myfile.dat');    
reset(g,bufsize);      
blockread(g,buf,bufsize);      


у меня 1-й вопрос: какими типами должны быть переменные? (buf,bufsize)

ВОТ! Нашел как звучит задание! Найти конечную сумму полученного файла, открыв его как нетипизированный!
p.s. открой аську плиз=)
volvo
Повторяю: числа не зашифрованы ничем. Это просто последовательность бит. К примеру, число 25 представлено так: 0000000000011001, а число 126 - так: 0000000001111110. Так что, говоришь, найти-то надо?
Akella
ВОТ задание так в карточки написано:
Найти конечную сумму полученного файла, открыв его как нетипизированный!
volvo
От тебя, как видно, хотят, чтобы ты научился работать с нетипизированными файлами, зная, что именно там находится... Тогда примерно так:

var
  g: file;
  sum, X: integer;

{ ... }

assign(g, 'myfile.dat');
reset(g, sizeof(integer)); { <--- открываешь файл с размером буфера = размеру integer-а }
sum := 0;
while not eof(g) do begin
  blockread(g, X, 1); { <--- читаем блок, соответствующий следующему числу, в X }
  sum := sum + X; { <--- и добавляем к сумме }
end;
{ все, сумма подсчитана, выводим }

(можешь добавить еще проверку ошибок, для этого у BlockRead есть четвертый параметр)
Akella
я так делал, но у меня ошибка 200... что это такое?
вот готовая прога, все работает... спасибо Volvo
program  _7_14;    

uses crt;    
var    
  f : file of integer;    
  g : file;    
  i,n,a,CurrPos,LastNeg,sum,buf : integer;        

begin    
clrscr;     
 randomize;      
  assign(f,'myfile.dat');      
   rewrite(f);     
    write('n=');    
    read(n);     
  for i:=1 to n do begin       
    a:=random(200)-100;       
      write(f,a);     
  end;    
  seek(f,0);       
    while not eof(f) do begin         
      read(f,a);         
       write(a,' ');       
    end;    
  reset(f);    
  LastNeg := -1;       
   while not eof(f) do begin         
     read(f, a);  	 
        if a < 0 then begin  	    
           CurrPos := FilePos(f);  	     
             inc(LastNeg);  	      
               Seek(f, LastNeg);  	     
               write(f, a);  	    
              Seek(f, CurrPos);  	 
        end;       
   end;    
  Seek(f, LastNeg + 1);    
   Truncate(f);    
    reset(f);    
    gotoxy(1,5);      
      while not eof(f) do begin         
          read(f,a);         
          write(a,' ');      
      end;      
  close(f);    
   assign(g,'myfile.dat');    
   reset(g,sizeof(integer));    
    sum:=0;    
      while not eof(g) do begin      
        blockread(g,buf,1);      
        sum:=sum + buf;    
      end;    
   gotoxy(1,10);    
   write(sum);  
end.
Ozzя
Help (Ctrl + F1) по слову blockread Вам окажет неоценимую помощь.

Добавлено через 3 мин.
Обнови tpl'ки - http://pascal.sources.ru/misc/bp7_tpl.htm
Akella
Помогите сделать похожую задачу, все тоже самое только условие другое: удалить из файла повторяющиеся включения одного и того же числа (массивы нельзя!) ...
мне бы токо условие, 3 часа бьюсь, только паскаль зависает, толку нету=))
volvo
Цитата
3 часа бьюсь, только паскаль зависает
Значит, что-то начал делать? Можно посмотреть, как именно ты начал решать задачу?
Akella
прога зависала из-за условия, потому что оно зацикливалось, поэтому я его удалил, а все остальное как в проге выше!
volvo
Akella, смотри как это делается:
var
  f: file of integer;
  i, X, Y: integer;
  pos, curr: longint;
  found: boolean;

begin
  assign(f, 'test.dat'); rewrite(f);

  {  Запрашиваем данные у пользователя и пишем в файл }
  for i := 1 to 10 do begin
    write(i:2, ' -> '); readln(X);
    write(f, X);
  end;

  reset(f); pos := 0; { переоткрываем файл и начинаем с самого начала }
  while not eof(f) do begin
    read(f, X);		{ прочитали число }
    curr := filepos(f);	{ запомнили, где были в файле }
    seek(f, 0);		{ идем в самое начало }

    found := false;
  
    { и пока не добрались до позиции, в которую записали последнее число }
    while filepos(f) < pos do begin
      read(f, Y);		{ Читаем ранее записанные числа, и ищем среди них X }
      if Y = X then found := true;
    end;
    if not found then begin { X не был найден }
      { Значит, пишем его в файл в позицию Pos, и увеличиваем Pos на 1 }
      seek(f, pos); write(f, X); inc(pos);	
    end;
    seek(f, curr); { Возвращаемся туда, где остановились, и продлолжим просматривать файл }
  end;

  { Все, весь файл пересмотрен, записано Pos чисел, остальные - дубликаты }
  seek(f, pos);
  { Отсекаем эти дубликаты }
  truncate(f);

  { Проверка, получилось ли то, что задумывалось }
  reset(f);
  while not eof(f) do begin
    read(f, X); write(X:3);
  end;
  writeln;
  close(f);
end.


Но больше на твои вопросы отвечать не буду, до тех пор, пока сам не будешь хотя бы пытаться что-то решить, и показывать результаты своих попыток. Сказать, что ты пытался, но ничего не получилось - очень просто, правда? Но это не проходит больше одного раза...
Akella
спасибо, но мне чуток по другому надо, повторяющиеся цифры вообще не должны потом выводиться=)
Akella
Помогите, что я не правильно написал? wacko.gif Задача такая: В последовательность K вещ. чисел на позицию N вставить число M, следущие за M числа сдвинуть на N+1, N+2 и т.д., т.е.
0.123 0.123 .123 0.123 на позицию 1(считая с нуля) поставим число 1.234 - получим:
0.123. 1.234 0.123 0.123 0.123

program  _7_1;   

 uses crt;    

var    f : file of real;    
g : file;    
N,K,sum,buf,i,kurpos : integer;   
 M,x,y,z : real;        

begin    
 clrscr;    
  randomize;      
   assign(f,'myfile.dat');      
     rewrite(f);     
 write('vvedite kolichestvo sluchainih chisel K=');    
   readln(K);     
 for i:=1 to K do begin       
   x:=random;       
     write(f,x);     
 end;     
 write('vvedite chislo M=');      
   readln(M);     
 write('vvedite poziciu zameni N=');      
   readln(N);    
 seek(f,0);     
 writeln('sluchainie chisla');       
   while not eof(f) do begin         
     read(f,x);         
     write(x:2:3,' ');       
   end;    
 reset(f);     
  seek(f,N);      
    read(f,x);      
      y := x;      
   seek(f,N);       
     write(f,M);       
  while not eof(f) do begin         
    kurpos := FilePos(f);  	
      read(f, x);  	 
      z := x;  	 
     seek(f,kurpos);  	 
       write(f,y);  	 
     seek(f,kurpos);  	 
       y := z;  	 
end;     
   { Seek(f, );    Truncate(f);}   
 reset(f);    gotoxy(1,7);     write('posle udaleniya polojitelnih chisel');      gotoxy(1,9);      
   while not eof(f) do begin         
     read(f,x);         
     write(x:2:3,' ');      
   end;      
 close(f);  
end.
volvo
После того как записал в файл все нужные тебе числа, лучше сделать так:

  reset(f);
  seek(f,filesize(f));

  X := 0; write(f, X);		{ <--- Пишем 0 в самый конец файла, увеличивая его размер }
  seek(f, filepos(f) - 2);	{ <--- Устанавливаем указатель на число, с которого начнем перемещение }
					{ Это как раз то самое число, которое было последним в файле, }
					{ пока туда не записали 0 }

  {
	А дальше - все просто: читаем число, при этом указатель сам перемещается
	на следующую позицию в файле, туда прочитанное число и пишем, указатель
	опять перемещается еще дальше, а мы его перебрасываем на 3 (!!!) позиции
	назад, чтобы на следующем круге начать перемещение на одну позицию раньше.

	Повторять, пока не дойдем до нужной позиции
  }
  while filepos(f) >= N do begin
    read(f, x); write(f, x);
    seek(f, filepos(f) - 3);
  end;

  seek(f, N); write(f, M);	{ Все, пишем туда куда надо введенное число }
  { И выводишь файл на печать для проверки }

Akella
ааааааааааааа я понял, блин я даже и не додумался с конца начать=))
Akella
извините за оформление(торопился). Вопрос: почему не считает контрольную сумму получившихся элементов? Не понимаю, в другой программе все работало....
uses crt;
    var    f: file of integer;
    g : file;
    i, X, Y, N, buf, sum: integer;
    pos, curr: longint;
    found: boolean;
begin    clrscr;
    randomize;
    assign(f, 'test.dat'); rewrite(f);
    write('vvedite chislo elementov faila N=');
    readln(N);   
 for i := 1 to N do begin      
    X := random(10);      
    write(X,' ');      
    write(f, X);     
 end;    
   writeln;    
reset(f); pos := 0; 
  while not eof(f) do begin      
read(f, X);		      
curr := filepos(f);
 seek(f, 0);	
 found := false;         
while filepos(f) < pos do begin        read(f, Y);		
   if Y = X then found := true;      
   end;     
  if not found then begin      
    seek(f, pos); 
    write(f, X);  
    inc(pos);	      
  end;      
 seek(f, curr);     
 end;          
seek(f, pos);   truncate(f);       
reset(f);    
while not eof(f) do begin      
read(f, X); 
write(X:3);    
end;    
writeln;    
close(f);     
assign(g,'test.dat');       
reset(g,1);       
sum:=0;    
while not eof(g) do begin      
blockread(g,buf,1);      
sum:=sum + ord(buf);    
end;    
write('kontrolnaya summa ravna ',sum);  
end.
volvo
assign(g,'test.dat');       
reset(g,1); { <--- После вот такого открытия }
надо как минимум сделать buf не Integer-ом, а Char-ом (или Byte, неважно, но размером в один байт), потому что и читаешь ты тоже
blockread(g,buf,1); { <--- Один блок }
Akella
почему же тогда у меня в другой проге работает и считает, да и типы по моему одинаковые...

все равно не считает, то что нужно!
volvo
Цитата
все равно не считает, то что нужно!
Значит, говори, что тебе нужно... Контрольная сумма - понятие растяжимое... Можно назвать так сумму элементов, можно - CRC файла, да мало ли что еще...
Akella
в этой проге мне считает, а почему в проге выше не работает я не знаю...
program  _7_14;    
uses crt;    
var    f : file of integer;    
g : file;   
 i,n,a,CurrPos,LastNeg,sum,buf : integer;        
begin    
clrscr;     
randomize;      
assign(f,'myfile.dat');      
rewrite(f);     
write('vvedite kolichestvo sluchainih chisel n=');    
read(n);     
for i:=1 to n do begin       
a:=random(200)-100;       
write(f,a);     
end;    
seek(f,0);     
gotoxy(1,3);      
write('sluchainie chisla');       
gotoxy(1,5);       
while not eof(f) do begin         
read(f,a);         
write(a,' ');       
end;    
reset(f);    
LastNeg := -1;       
while not eof(f) do begin         
read(f, a);  	 
if a < 0 then begin  	    
CurrPos := FilePos(f);  	     
inc(LastNeg);  	      
Seek(f, LastNeg);  	     
write(f, a);  	   
 Seek(f, CurrPos);  	 
end;       
end;    
Seek(f, LastNeg + 1);    
Truncate(f);    
reset(f);    
gotoxy(1,7);     
write('posle udaleniya polojitelnih chisel');      
gotoxy(1,9);      
while not eof(f) do begin         
read(f,a);         
write(a,' ');      
end;      
close(f);    
assign(g,'myfile.dat');    
reset(g,1);    
sum:=0;    
while not eof(g) do begin      
blockread(g,buf,1);      
sum:=sum + ord(buf);    
end;    
gotoxy(1,11);    
write('kontrolnaya summa = ',sum);  
end.
volvo
И что это? Ты на вопрос ответь, а не подсовывай что-то что "работает"... Насчет того, работает это или нет - большой вопрос, у меня и первый твой код работает... ЧТО СЧИТАЕТ он?
Akella
я затупил, и скорее всего препод тоже..... извиняюсь... mega_chok.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.