Set the task for Pascal: To simulate the work of a photo studio serving reporters, photographers and paparazzi, with the paparazzi being served last. In the preparation of photographs consumed resources in the required quantity. As resources run out, service is suspended until new resources arrive, and there is a reserve that can be used to service reporters. Information about available resources and unserved customers in the queue should be available at any time.

The question is actually not in the construction of the program, but in some parts of it, namely, the program closes with an error - "" Unexpected exception to EAccessViolation. Access violation at address 0075CD31 in module 'PascalABC.exe'. Read of address 00003288. The program is completed (photo.pas line 45) "

The program is still far from complete, but it has already driven me into a dead end, please help me figure out what my mistakes are.

Here is the code:

program photo; uses crt, timers; type ukazatel = ^elem_spiska; elem_spiska = record znach : Integer; next : ukazatel; end; var reporter, photographer, paparazzi, rand, i, resources, rezerv, m: integer; head, p, q : ukazatel; {процедура обслуживания} procedure service; begin if resources = 0 then begin p := head; {начать с головы списка} while p^.next^.znach <> 2 do p := p^.next; q := p^.next; {удаляемый элемент} p^.next := q^.next; {связка «через один»} dispose(q); rezerv := rezerv - 1; end else begin p := p^.next; {переход к следующему элементу списка} resources := resources - 1; end; end; {процедура добавления очереди} procedure turn; var t, o: integer; begin t := Random(3)+0; writeln(t); p := head^.next; if p = nil then begin new(p); p^.znach := t; p^.next := nil; end else if (p^.znach = 0) and (t > 0) then begin p^.znach := t; p^.next^.znach := 0; p^.next^.next := nil; end else begin new(q); q := p^.next; q^.znach := t; p^ := q^; dispose(q); end; end; {процедура запуска обслуживания} procedure open_service; var u: integer; begin u := 1; new(p); new(q); new(head); head^.znach := u; randomize; reporter := 2; photographer := 1; paparazzi := 0; resources := 100; rezerv := 100; while rezerv > 0 do begin turn; writeln(p^.znach); sleep(1000); turn; sleep(1000); writeln(p^.znach); service; sleep(1500); end; end; begin WriteLn('Фото Ателье'); writeln('1 - открыть заведение'); writeln('2 - Закрыть заведение'); read(m); case m of 1: open_service; 0: exit; end; end. 

    1 answer 1

    Initially, there should be an empty queue, i.e. instead

      new(p); new(q); new(head); 

    must be

     p:=nil; q:=nil; head:=nil; 

    and memory allocation should be when adding each new element within the turn procedure.

    About the error:

      p := head^.next; if p = nil then begin p^.znach := t; p^.next := nil; end 

    data is written by a null pointer. I think that after begin it is necessary to make new (p). Given that the original queue is empty:

      p := head; if p = nil then begin new(p); p^.znach := t; p^.next := nil; end 

    UPD. Here's what I got:

     {...} {процедура обслуживания} procedure service(var p:ukazatel); var temp:ukazatel; begin if p <> nil then if resources = 0 then begin if p^.znach = 2 then {если первый элемент - тот что нам нужен} begin q := p^.next; {запоминаем следующий элемент} dispose(p); {освобождаем первый элемент} p := q; {перенаправляем указатели} rezerv := rezerv - 1; end else begin q := p^.next; {цикл пока не достигнем конца или пока не найдем:} while (q^.next <> nil) and (q^.next^.znach <> 2) do q := q^.next; if q^.next <> nil then {если это не конец списка, то} begin temp:=q^.next; {временно сохраняем указатель на удаляемый элемент} q^.next := temp^.next; {перенаправляем связи} dispose(temp); {освобождаем удаляемый элемент} rezerv := rezerv - 1; end; end; end else begin q := p^.next; {запоминаем следующий элемент} dispose(p); {освобождаем текущий элемент} p := q; {переход к следующему элементу списка} resources := resources - 1; end; end; {процедура добавления очереди} procedure turn(var p:ukazatel); var t, o: integer; begin t := Random(3); writeln(t); if p = nil then {пустая очередь} begin new(p); p^.znach := t; p^.next := nil; end else if t > 0 then begin {добавление в начало списка} new(q); q^.znach := t; q^.next := p; p := q; end else begin {добавление вторым элементом списка} new(q); q^.znach := t; q^.next := p^.next; p^.next := q; end; end; {процедура запуска обслуживания} procedure open_service; var u: integer; begin head:=nil; {пустой список} randomize; reporter := 2; photographer := 1; paparazzi := 0; resources := 100; rezerv := 100; while rezerv > 0 do begin turn(head); writeln(head^.znach); sleep(1000); turn(head); sleep(1000); writeln(head^.znach); service(head); sleep(1500); end; end; {...} 

    In general, I advise you to read about working with lists, for example here: Fundamental algorithms and data structures in Delphi . All the same should work on PascalABC.

    PS Only it turned out not a queue, but a stack. To get a queue, you need to add to the end of the list, and pick up from the beginning.

    • thanks, corrected. but the error occurs below, but as I can see on the first else (after if p = nil), the problem remains: ( - Vladimir Archi
    • Question: p, q and head pointers - what is each of them used for? - insolor
    • Well, sort of like head is the head of a dynamic list (it should always point to the first element of the list - I line up in the studio), p - all subsequent elements and q - to remove from the middle and the link after one. - Vladimir Archi
    • that is good. Thank you, insolor. I think I will now deal with the queue myself (at least I will try) - Vladimir Archi