0
var
RegNo: array of string;
Speed: array of real;
cars : integer;
time : real;
begin
Setlength(RegNo, 99);
Setlength(Speed, 99);
Writeln ('The speed limit is 50km/h');
Writeln ('The distance between the two points is 50m');
cars := 0;
time := 1;
while time>0
  do
    begin
    cars := cars + 1;
    Writeln ('Enter the car takes to pass the two points');
    Readln (time);
      if time = 0 then
      Writeln
      else
        if time < 1 then
          begin
           Writeln ('Enter the registration plate for the car');
           Readln (RegNo[cars]);
          Speed[cars]:= 50/time;
          end
        else
    end;
Setlength (RegNo, cars);
Setlength (Speed, cars);
Writeln (RegNo[cars]);
Writeln (Speed[cars]:5:2);
Readln;
end.

I don't understand what I'm doing wrong. This is supposed to be a program to read out the cars speeding using arrays. It says that the variable RegNo may not have been initialized. It says that the variable Speed may not have been initialized.

KKP
  • 1
  • 2

2 Answers2

0

That is because for the first time you access those variables inside a conditional if clause.

So if specific condition that is expected by that conditional clause isn't met that code would never run.

That is the reason why compiler generates mentioned warning.

But you have bigger problem in your code. Since you are using dynamic arrays you need to set their size using SetLength(YourArray, NewSize) before you can store any data to them.

Failing to do so would raise EOutOfRange exception if you have range checking enabled in your project.

And if don't have range checking enabled (which is by default) you could easily overwrite part of memory that belongs to some other object or variable and thus cause havoc with your program.

SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • i have added the Setlength's but i am still getting the error access violation how would I change it to access the variables outside the conditional if clause – KKP Oct 11 '15 at 00:29
  • When do you get Access Violation error now. Perhaps when you are trying to enter information for last car (100th)? You see dynamic arrays are `zero based` which means that first item in array has an index of `0`. But your code writes information about first car to 2nd item in the array. And when you are trying to write data to last item you are actually trying to access memory out of bounds of your array. So I suggest that you enable range checking. – SilverWarior Oct 11 '15 at 00:59
  • Also have you perhaps considered of having one array or records where each record would contain all necessary information (speed, registration plate) about each car. – SilverWarior Oct 11 '15 at 01:01
0

I'm not sure where you got the idea to use dynamic arrays in what is obviously a beginner's programming task, because the complications of having to handle memory allocations and zero-based array indexes are a bit of a distraction from the task you're at.

One of the main reason Delphi implements dynamic arrays is to handle the situation where the number of elements isn't know until run-time (another is to allow the writing of routines that aren't tied to a specific number of array elements). However, in your case, you don't need the complications of using dynamic arrays, they just introduce possibilities for avoidable errors.

In a traditional version of an exercise like this, one would use static arrays:

var
  RegNo: array[1..100] of string;  // assuming you actually want 100 elements
  Speed: array[1..100] of real;

The advantages of doing it that way include

  • The arrays can have intuitive lower and upper bounds, not 0 and 98: Of course, that's assuming you really did intend to have 99 elements in your arrays, not 100, and that illustrates the sort of mistake it's easy to make if you use dynamic arrays, or zero-based arrays generally when they're not a natural fit to your programming task.

  • If the arrays are global variables (not local variables of a procedure or function) you can just use the arrays without further ado, i.e. no need to do memory allocation (SetLength) on them before you use them and no need to release the memory afterwards. The reason for that is that at run-time, global variables are automatically filled with zeroes as the program starts, so the program starts with them in a known state.

I agree with David Heffernan's comment that having range checking on can help pick up out-of-range array indexes, but in something as simple as this, it's probably best not to rely on "training wheels" and instead get used to getting your array indexes correct in the first place. Having to mentally jump back and forth between your mental model of the array and the array bounds and indexing of a zero-based array is probably one of the most frequent sources of error. And unless someone has deliberately made life difficult for you by insisting on zero-bases arrays, use the luxury of natural array bounds that Pascal permits to make life easier on yourself.

Local variables are allocated on the stack (and with certain exceptions, managed-lifetime variables which are a bit of an advanced topic) and therefore contain random values, so they should be initialized before use, by doing something like:

FillChar(MyArray, SizeOf(MyArray), Chr(0));

Some may disagree, but imo, it's better to get in the habit of initializing variables even when you don't need to (like global variables), rather than trip over an uninitialized one.

It's worth mentioning that the bounds of an array don't need to be overtly numeric. For example, given an enumeration

type

  TFruit = (apple, pear, banana);

you can then declare an array

var
  Calories : array[apple..banana] of real;

This is a style you often see in Pascal tutorials which predate Delphi and is mainly thanks to its objective as a strongly-typed, teaching language.

MartynA
  • 30,454
  • 4
  • 32
  • 73
  • There's nothing in the code that says that 100 is enough. Why wouldn't the user enter more than 100 items? As for `FillChar`, that's poor advice for managed types. – David Heffernan Oct 11 '15 at 08:37
  • 1
    @DavidHeffernan: a) It looked to me that the OP wants (or has been told to use) an array of a fixed size (maybe just to get used to the idea of arrays), not to support some whim about "How big shall we have our array today?". b) Seeing as I'm suggesting that the the OP doesn't need a managed type, I don't see what's wrong with FillChar, especially as it's the technique the OP is likely to find in traditional tutorial texts, e.g. the TP3 manual and its ilk. – MartynA Oct 11 '15 at 08:42
  • Oh, and see http://stackoverflow.com/questions/783825/why-most-delphi-examples-use-fillchar-to-initialize-records – MartynA Oct 11 '15 at 08:46
  • The problem with learning 1 based indexing is that somewhere down the line 0 based indexing will take over and then there will be severe confusion. Sadly Delphi screwed this up a long time ago with the bogus 1 based indexing of strings. – David Heffernan Oct 11 '15 at 10:43
  • @MartynA I agree with David about learning to work with 1 based arrays. – SilverWarior Oct 11 '15 at 23:48
  • @SilverWarior: What, you agree with the idea that zero-based arrays will take over, you mean? – MartynA Oct 12 '15 at 07:43
  • @MartynA Hard not to agree with that. Pretty hard to avoid dynamic arrays. – David Heffernan Oct 12 '15 at 17:31
  • @DavidHeffernan; Maybe, but tbh my mind was a bit more boggled by your crack about Delphi having "screwed up .. bogus 1 based indexing or strings" Were you referring to indexing in pre-32-but ShortStrings? – MartynA Oct 12 '15 at 19:30