Wątek przeniesiony 2014-03-19 13:41 z Delphi i Pascal przez furious programming.

Bufor cykliczny na jednowymiarowej tablicy

0

Witam. Mam prośbę, czy mógłby ktoś pomóc, napisać co tutaj mam zmienić aby osiągnąć taki efekt:

Bufor cykliczny na jednowymiarowej tablicy
Najprostszy bufor cykliczny o stałym rozmiarze można zrealizować na bazie tablicy jednowymiarowej.
Z tablicą związane będą dwa indeksatory "in" oraz "out". Ten pierwszy wskazuje w które miejsca należy wpisać nowy element, ten drugi z której pozycji możemy odczytać element.
Gdy "in"="out" oznacza, że bufor jest pusty. Kiedy dodajemy element przesuwamy indeksator "in" o jeden dalej. Gdybyśmy doszli do końca tablicy należy wrócić na jej początek (obliczyć modulo).
"In" powinien wskazywać zawsze na puste miejsce. Jeżeli "Out" byłby tylko o jeden dalej (uwzględniając modulo czyli "zapętlenie" w tablicy) niż "In" oznaczałoby to zapełnioną tablicę.
W takiej sytuacji nie powinniśmy dodawać elementów, gdyż indeksator "In" musiałby się zrównać z "out", co oznaczałoby pusty bufor.

Należy napisać program bazujący na 8 elementowym buforze cyklicznym.
Program powinien posiadać menu, w którym użytkownik wybiera sobie rodzaj działania, zakolejkowanie lub zdjęcie z kojki jednego elementu lub wszystkich.

Za każdą operacją wyświetlić zawartość bufora oraz indeksatory in oraz out. Gdy element jest zdejmowany z kolejki, także wyświetlić ten element.
W przypadku, gdy podczas dodawania kolejka jest pełna, należy zdjąć 4 elementy naraz a następnie dodać żądany element.

Elementy będą typu char.

program zadanie1;
uses crt;

const
  max = 8;

type
  queue = record
    element: array[1 .. max] of char;
    first, last:byte;
  end;

var
  kolejka: queue;
  ne: byte;
  znak: char;

function addone(i: byte):byte;
begin
  addone := i mod max + 1;
end;

procedure makenil(var q: queue);
begin
  q.first := 1;
  q.last := max;
end;

function empty(const q: queue):boolean;
begin
   if addone(q.last) = q.first then
     empty := true
   else
     empty:=false;
end;

function firstone(const q: queue):char;
begin
  firstone:=' ';

  if empty(q) then
    exit
  else
    firstone := q.element[q.first];
end;

procedure dequeue(var q: queue);
begin
  if empty(q) then
    exit
  else
    q.first := addone(q.first);
end;

procedure enqueue(var q: queue; a: char);
var
  i: byte;
begin
  if addone(addone(q.last)) = q.first then
  begin
    for i := 0 to 3 do
      dequeue(q);
  end;

  q.last := addone(q.last);
  q.element[q.last] := a;
end;

procedure wyswietl(q: queue);
var
  i: byte;
begin
  {
  writeln('first: ', q.first, 'last: ', q.last);

  for i := 1 to 9 do
  begin
    write(q.element[i], i, ' ');
  end;

  for i:=q.first to q.last do
  begin
    write(q.element[i], i, ' ');
  end;
  }

  write('kolejka     ->');

  while not empty(q) do
  begin
    znak := firstone(q);
    //zdejmij(kolejka,znak);
    dequeue(q);
    write(znak, #32);
    //wyswietl(kolejka);
  end;

  writeln;
  write('indeksatory ->');

  for i := 0 to 8 do
  begin
    if i = q.first then
    begin
      write('o ')
    end
    else
      if i = q.last then
        write('i ')
      else
        write('  ');;
  end;

  writeln;
end;

procedure dodaj(var q: queue; a: char);
var
  i: byte;
begin
  if addone(addone(q.last)) = q.first then
  begin
    for i := 0 to 3 do
      dequeue(q);
  end;

  q.last := addone(q.last);
  q.element[q.last] := a;
end;

procedure zdejmij(var q: queue; var a: char);
begin
  a := firstone(q);

  if empty(q) then
    exit
  else
    q.first := addone(q.first);
end;

begin
  clrscr;
  makenil(kolejka);
  writeln('Ile elementów umieścić w kolejce: ');
  readln(ne);

  while ne > 0 do
  begin
    readln(znak);
    enqueue(kolejka, znak);
    dec(ne);
    wyswietl(kolejka);
  end;

  clrscr;
  writeln('Elementy umieszczone w kolejce: ');

  while not empty(kolejka) do
  begin
    znak := firstone(kolejka);
    //zdejmij(kolejka,znak);
    dequeue(kolejka);
    write(znak, #32);
    //wyswietl(kolejka);
  end;

  readln;
end.

Ten kod jest naprawdę "pomieszany" ale sporo różnych kombinacji tutaj robiłem i taki jest efekt.
Szczerze powiedziawszy, tyle zrobiłem ale nie mam pojęcia co tutaj napisałem i co mam zmienić.
Proszę bardzo o pomoc, sprawa bardzo pilna.

0

Albo jest tak późno albo to jest tak pomieszanie że tego nie łapie xD
To jest treść zadania czy ty sobie tak wymyśliłeś żeby to zrobić w tablicy?

0

Ponieważ długość buforu jest potęgą dwójki, można to wykorzystać maskując odpowiednie bity indeksów, zamiast mod.
czyli:

in := (in + 1) and 7;
0

pomoże ktoś? Mam podobny program do zrobienia, a nie mam kompletnie pomyslu jak to wykonac ;/

program zad1;
uses crt;
const max=8;
  type
    kolejka=record
      element:array[1..max]of char;
      first,last:byte;
    end;

var ko:kolejka; ne:byte; nu:char; menu:integer; znak:char;

  function addone(i:byte):byte;
  begin
    addone:=i mod max+1;
    end;

procedure makenil(var k:kolejka);
begin
  k.first:=1;
  k.last:=max;
end;

function empty(k:kolejka):boolean;
begin
  if addone(k.last)=k.first then empty:=true
  else
    empty:=false;
  end;

function firstone(k:kolejka):char;
begin
firstone:=' ';
if empty(k) then exit
else
firstone:=k.element[k.first];
end;

procedure dequeue(var k:kolejka);
begin
  if empty(k) then
    exit
  else
    k.first := addone(k.first);
end;

procedure enqueue(var k:kolejka; var a:char);
var i: byte;
begin
  if addone(addone(k.last))=k.first then
  begin
    for i := 0 to max do
      dequeue(k);
  end;

  k.last := addone(k.last);
  k.element[k.last] := a;
end;

procedure wyswietl(var k:kolejka);
var i: byte;
begin
  write('kolejka     ->');

  while not empty(k) do
  begin
    znak := firstone(k);;
    dequeue(k);
    write(znak, #32);
  end;

  writeln;
  write('indeksatory ->');

  for i := 0 to 8 do
  begin
    if i = k.first then
    begin
      write('o ')
    end
    else
      if i = k.last then
        write('i ')
      else
        write('  ');;
  end;
  writeln;
end;

procedure usun(var ko:kolejka; var a:char);
begin
  a:=firstone(ko);
  if empty(ko) then exit
  else
    ko.first:=addone(ko.first);
end;

begin
  clrscr;
  makenil(ko);
  repeat
    wyswietl(ko);
    repeat
 readln(menu);
 until(menu=1)or(menu=2)or(menu=3);
 if menu=1 then
 begin
   readln(znak);
   enqueue(ko,znak);
 end;
 if menu=2 then
 begin
   readln(znak);
   usun(ko,znak);
   end;
 if menu=3 then exit
  until menu=3;
  readln;
end.    

zrobilem cos takiego, ale nie dziala tak jak powinien ;/

0

Mam podobny program do zrobienia, a nie mam kompletnie pomyslu jak to wykonac ;/

@zupaaa - masz ze 100 linii kodu i nie masz pojęcia jak to wykonać? Obstawiam, że dostałeś lub "pożyczyłeś" od kogoś kod i w ogóle nie rozumiesz jak działa (o ile w ogóle działa prawidłowo), dlatego nie wiesz jak się za to zadanie zabrać i nie umiesz opisać co jest nie tak;

zrobilem cos takiego, ale nie dziala tak jak powinien ;/

Tak to możesz tłumaczyć pani od polskiego - tutaj wypada podać cenne informacje, takie jak błędy czy opisy niepożądanych zachować programu;

Poza tym podany przez Ciebie kod to spory WTF - skasuj go i napisz go jeszcze; Jeśli nie wiesz jak się za to zabrać - w sieci jest mnóstwo materiałów opisujących zasadę działania bufora cyklicznego; Jeśli brak Ci wiedzy - zaglądnij do jakiegoś kursu programowania w Pascalu;

A jeśli oczekujesz gotowca (warto od razu i o nim wspomnieć), to zleć to komuś na PM lub załóż osobny wątek w dziale z drobnymi ogłoszeniami.

0

nie wiem jak zrobic, aby za pomoca menu dodac iles-tam elementow do kolejki, po czym usuwac, te ktore chce. Bo bez menu, normalnie w tablice laduje elementy i wyswietlaja sie ladnie. Skasowac, kasuje mi wszystkie

0

Napisałem Ci, żebyś skasował ten kod i napisał nowy, tyle że z głową; Obecny kod jest pomieszany i zagmatwany, dlatego nie masz pojęcia co w nim jest źle;

Jeśli bufor koniecznie chcesz wpakować do rekordu, to zadeklaruj sobie rekord z tablicą (pamięcią bufora), indeksy na pierwszy i ostatni element tablicy (do sprawdzania indeksów zapisu i odczytu) oraz indeks elementu do odczytu danych i indeks elementu do zapisu danych; Czyli coś w tym rodzaju:

const
  BUFF_SIZE = 8; // rozmiar bufora

type
  TCircularBuffer = record
    Buffer: array [0 .. BUFF_SIZE - 1] of Char; // pamięć bufora
    First, Last: Byte; // indeksy pierwszego i ostatniego elementu bufora
    Write, Read: Byte; // indeksy aktualnego elementu do odczytu i zapisu
  end;

Pola First i Last możesz pominąć, dlatego że możesz się statycznie odwoływać do pierwszego i ostatniego elementu macierzy Buffer - pierwszy ma indeks 0, ostatni BUFF_SIZE - 1 lub High(Buffer);

Zadeklaruj sobie procedurę, która zainicjuje pola rekordu bufora - wyczyści pamięć bufora i ustawi wartości pozostałych pól; Tę procedurę wywołaj przed użyciem bufora; Przy dodawaniu nowego elementu do bufora wstaw go do pamięci bufora pod indeks zawarty w polu Write, po czym zwiększ ten indeks; Jeśli Write będzie zawierać indeks większy od tego z pola Last - ustaw go na wartość z First; Przy odczycie pobierz dane z pamięci bufora z elementu o indeksie zawartym w polu Read, po czym zwiększ ten indeks o jeden; I pobodnie - jeśli indeks jest większy niż ten z pola Last - ustaw go na wartość z First;

W przypadku dodawania/zdejmowania elementu musisz sprawdzić, czy pamięć bufora jest zapełniona/pusta - inaczej kolejka się przepełni (przekręcisz licznik) albo wczytasz poprzednie wartości/śmieci;

To tyle teorii, teraz trzeba to zaimplementować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1