Recent

Author Topic: Unit variables  (Read 6154 times)

Raindrop

  • Newbie
  • Posts: 3
Unit variables
« on: December 10, 2014, 11:09:20 pm »
Hello, I need help to understand how variables form procedures in units and the main program interact. Since I have to create a program which does basic calculation of matrixes.

What I currently have is this:

Code: [Select]
program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, Wprowadzanie
  { you can add units after this };

Const
     N=20;

Type
    matrix=array [1..N,1..N] of real;

Var
   x1,x2,
   wpr,
   i,j : integer;
   A,B: matrix;

begin
  begin
  repeat
  writeln ('wprowadz macierz kwadratowa');
  writeln ('1 - z pliku');
  writeln ('2 - recznie');
  readln (wpr);
  until (wpr>=1) and (wpr<=2);
  begin
       begin
         repeat
          writeln ('Podaj rozmiar I macierzy kwadratowej:');
          Writeln ('(zakres od 2-20)');
          readln (x1);
         until (x1 >= 2) and (x1 <= 20);
         A:=elementy(x1);
         end;

         begin
         repeat
          writeln ('Podaj rozmiar II macierzy kwadratowej:');
          Writeln ('(zakres od 2-20)');
          readln (x2);
         until (x2 >= 2) and (x2 <= 20);
         B:=elementy(x2);
         end;
   begin
     writeln(x1);
     writeln;
     for i:=0 to x1 do
     begin
         for j:=0 to x1 do
           write(A[i,j]:0:2,' ');
           writeln;
     end;
end;
  end;
end;




Writeln;
Writeln('Press enter to leave');
Readln;

end.

Code: [Select]
unit Wprowadzanie;

interface

Const
     N=20;

Type
    matrix=array [1..N,1..N] of real;

function elementy(x:integer):matrix;

implementation

function elementy(x:integer):matrix;
var
  i,j: integer;
  A:matrix;
begin
  for i:=1 to x do
               for j:=1 to x do
                   begin
                        writeln('Podaj elementy [',i,',',j,']: ');
                        readln(A[i,j]);
                   end;
  A:=elementy;
  writeln;
end;
end.

How it should look like

Unit:
Proc1: Enter x amount of rows for matrix I & II
Proc2: Define each element of matrix 1 & 2
Proc3: Show the Matrix on the screen
Proc4: Calaculate matrix 3

Main program:

Do Proc1.
Do Proc2.
Do Proc3.
Do Proc4.

Since in need value x to callculate Proc2 and then I need each element of matrix 1 & 2 to do a matrix addition.

Problem is I dont know how I pass over the values.

Ergo skiped Proc1 and wrote it into the mainprogram and started with Proc 2, but now I have no idea how to show the element of the matrix on the screen.

All I currently get is:

0 0 0
0 0 0
0 0 0

It would be great if you could help.

Best regards,
Raindrop
« Last Edit: December 10, 2014, 11:11:36 pm by Raindrop »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Unit variables
« Reply #1 on: December 10, 2014, 11:46:39 pm »
Hello, I need help to understand how variables form procedures in units and the main program interact. Since I have to create a program which does basic calculation of matrixes.

Homework?


Code: [Select]
function elementy(x:integer):matrix;
var
  i,j: integer;
  A:matrix;
begin
  for i:=1 to x do
               for j:=1 to x do
                   begin
                        writeln('Podaj elementy [',i,',',j,']: ');
                        readln(A[i,j]);
                   end;
  A:=elementy;
  writeln;
end;
end.

You do not assign a result to function elementy(), so it's result is undefined.

Change the line
Code: [Select]
  A:=elementy;
into
Code: [Select]
  elementy:=A;

Bart
« Last Edit: December 11, 2014, 12:03:32 am by Bart »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Unit variables
« Reply #2 on: December 10, 2014, 11:59:27 pm »
Code: [Select]
   begin
     writeln(x1);
     writeln;
     for i:=0 to x1 do
     begin
         for j:=0 to x1 do
           write(A[i,j]:0:2,' ');
           writeln;
     end;
end;

Will give a range check error because you try to access element [0,0] an you define matrix to start counting at 1...

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Unit variables
« Reply #3 on: December 11, 2014, 12:22:53 am »
If you insist on having the entering in a separate unit (and maybe the displaying as well), I would suggest to have yet another unit that has the type definitions and use that unit (add to uses clause) in both the main project file and all units that use the matrix type.

As a side note: it is considered a good practice to let names of types begin with a T, so I would call the matrix type TMatrix.

You are aware that you do nothing with matrix B (and I can see no matrix calculations)?
You are also aware that you do no checking of the input? If user enters any non-real (e.g. some text) the program crashes.

Code: [Select]
  write('Podaj elementy [',i,',',j,']: ');
  readln(A[i,j]);
looks just a litlle nicer (when excuting the program) then
Code: [Select]
  write('Podaj elementy [',i,',',j,']: ');
  readln(A[i,j]);

Also if you seek help, it may help to have your funtion/procedure/variable names in English, it helps us to understand what a function/procedure is trying to do (if you give meaningful names to them, that is).
Now I had to rely on Google Translate.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Unit variables
« Reply #4 on: December 11, 2014, 12:47:52 am »
Just to get you started a little bit I attached matrix.zip.
It has unit for entering, displaying and type definitions.
It reads and displays 2 matrices.
Note the altered names of functions and varaibles.
I also tidied up the indentation.

This part
Code: [Select]
  repeat
    writeln ('enter the square matrix');
    writeln ('1 - z file (?)');
    writeln ('2 - manually');
    readln (wpr);
  until (wpr>=1) and (wpr<=2);
does nothing at the time, so you must implement what it is supposed to do (manual versus loading from file?).

You could also write a function that asks for this input (as well as one that asks for the size of the matrix).
It makes the code in the main program block better to understand, something like:
Code: [Select]

type
  TIunputMethod = (imManual, imFromFile);

var
  InputMethod: TInputMethod;
...
begin
  InputMethod := AskInputMethod;  //you need to implement this yourself
  case InputMethod of
    imManual:
    begin
      AskSize(SizeA);
      A:= GetMatrixItems(SizeA);
      AskSize(SizeB);
      B := GetMatrixItems(SizeB);
    end;
   im FromFile:
    begin
      ReadFromFile(A, SizeA); //implement this yourself
      ReadFromFile(B, SizeB);
    end;
  end;//case
  DisplayMatrix(SizeA, A);
  DisplayMatrix(SizeB, B);
  CalculateMatrix(A, SizeA, B, SizeB, C, SizeC); //you need to implement this
  DisplayMatrix(SizeC, C);
end.

Raindrop

  • Newbie
  • Posts: 3
Re: Unit variables
« Reply #5 on: December 12, 2014, 01:08:38 pm »
Thank you Bart, really helped me to solve my problems also for your fast answer.

Yes the user is suppossed to choose the matrix input metod:
A)Load it form a .txt file
B)Enter it manually

The matrixes in the file are suppossed to look something like this:

2
  2 2
  3 4

3
 2 3 1
 3 3 2
 1 1 1


The only way to do this is by creating a ReadFileByLine procedure?

I used your matrix.zip and added a calulation unit everything works fine until now.


Code: [Select]
program matrix;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, Wprowadzanie, matrixdefs, Wyswietlajsc, matrixcal;

Var
   SizeA,SizeB,wpr : integer;
   A,B,C: TMatrix;

begin
  repeat
    writeln ('enter the square matrix');
    writeln ('1 - enter manually');
    writeln ('2 - from file');
    readln (wpr);
  until (wpr>=1) and (wpr<=2);

  case wpr of
  1: begin
  SizeofMatrix (SizeA);
  A:=GetMatrixItems(SizeA);

  SizeofMatrix (SizeB);
  B:=GetMatrixItems(SizeB);
  end;

  2: begin

  end;
  end;

  DisplayMatrix(SizeA, A);
  DisplayMatrix(SizeB, B);


  Writeln ('Choose which matrix calculation you want to prefrom');

  C:=Madd(A,B,SizeA,SizeB);

  DisplayMatrix (sizeA, C);

  Writeln;
  Writeln('Press enter to leave');
  Readln;

end.

Code: [Select]
unit matrixcal;

interface

uses
  matrixdefs;


function Madd(A,B : TMatrix; sizeI,sizeII: integer):Tmatrix;

implementation

function Madd(A,B : TMatrix; sizeI,sizeII: integer):Tmatrix;

var
  i,j : integer;
  C:Tmatrix;
begin
  if sizeI < sizeII then exit;

  for i :=1  to sizeI do
  for j :=1  to sizeI do
  C[i,j] := A[i,j] + B[i,j];
  Madd := C;
end;
end.

Well the should have asked for the hardest thing in my first post how do I read a matrix for a note pad file so that the first one is matrix A and the 2nd one is recognized as matrix B ?
« Last Edit: December 12, 2014, 01:59:34 pm by Raindrop »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Unit variables
« Reply #6 on: December 12, 2014, 02:12:30 pm »
Am I right in assuming this is a school assignment?  :)

It would make sense to parse the file line by line (I assume the file is plain text, not binary?).
This can be done using old-fashioned readln(filevar, stringvar) or in modern dialect (as in: fpc, delphi) use a TStringList and load the file in one read, then parse all lines.

If you knew the size of the matrix you could use
Code: [Select]
  readln(matrixfile, val1, val2, val3); //val1 etc of type Real

But since you don't, read each line as a string, then parse the string into the values.
For that you need to run through the string, stop at each space (#32) and parse that piece of the string.
This is teadious work, and again TStringList can do that for you (see TStringList.DelimitedText).

I don't know if you are allowed to use things like TStringList or functions like StrToFloat that would make this task that much easier.
If not you will have to write some functions to do so yourself  :(

So processing a file:
  • Read first line: it contains size of Matrix
  • repeat size times: read next line, parse line
  • make sure you can handle invalid files (non-exsting file, too many or too little lines, invalid value for size etc.)

An observation:
Code: [Select]
function Madd(A,B : TMatrix; sizeI,sizeII: integer):Tmatrix;

It does not return the size of the calculated matrix.
Maybe this is not needed because you know it before the calculation already?

So try to write code that can read a matrix from a file and come back here.
Once you've got that, you're almost done: just sticking the pieces together.

Last piece of advice: include some sort of error handling for the reading of the matices.
You don't want to let invalid input crash you program.
Especially for manual input it is IMO not acceptable that the user gets punished for one false keystroke (I would throw away my keayboard, curse you and maybe hire a hitman, if I mistyped something in the last value of matrix B with both sized 20x20 and the program crashed).
(If this program was for the real world, I would also give the user the ability to abort the program while entering values.)

For file reading, it is acceptable IMO to stop the program (in a nice way, telling the user why) if a non-valid file was presented.
Bart

Raindrop

  • Newbie
  • Posts: 3
Re: Unit variables
« Reply #7 on: December 12, 2014, 07:32:14 pm »
Thanks Bart for all your help.

Am I right in assuming this is a school assignment?  :)

Yes it is a howework but if there a rule that members aren't allowed to help if its a homework? then No. :)

An observation:
Code: [Select]
function Madd(A,B : TMatrix; sizeI,sizeII: integer):Tmatrix;

Fixed, all calculations work fine until now.

Last piece of advice: include some sort of error handling for the reading of the matices.
I added an val function to all the parts were the user needs to input something. Its the only way to do it. Is there an easier way to do it?

I don't know if you are allowed to use things like TStringList or functions like StrToFloat that would make this task that much easier.

Im allowed, just that I have to figure out how to use them.

Raindrop
« Last Edit: December 12, 2014, 08:35:20 pm by Raindrop »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Unit variables
« Reply #8 on: December 13, 2014, 12:38:39 am »
Helping with school assigments is OK, as long as the student shows code and points out what does not work, or what he/she does not understand, basically puts in effort of him/herself.
We have all started at some point and relied upon others helping us learn.


In the past people have been offering money to us for doing their (or their girl/boyfriends homework), which is not OK by any standard.


Some pointers.

You are familiar with Val.
An easier way is to use TryStrToFloat(). It returns a boolean indicating succes.
(Mind you that problems may arise if DecimalSeparator in your local is not '.' and the inputvalues use it)

Splitting a string with real values.
Look up how to create a class (TStringList in this case) and how (and when) to dispose of it.
Look up how to iterate through the strings in a TStringList (use a loop, the property Count and the property Strings[]).

Assuming al values are separated by a space (#32) you can do the following:
  • Create a TStringList
  • Set Delimiter to #32
  • Set StrictDelimiter to True
  • Set DelimitedText to "the string with real values"
  • Now each Strings[n] in the TStringList contains the string representation of the real vaue

Bart

 

TinyPortal © 2005-2018