Functional Decomposition

layarish
layarish used Ask the Experts™
on
I need a bit of help with this problem, I cant do proper functional decomposition; and my code doesnt work so pls can some one give me some code to solve the problem below, also it has to have good functional decomposition:
A program which displays all valid records in a memo control, it must read the file input and the invalid data and valid data must go in 2 seperate memo boxes, also can u pls use GetField Function to read the lines of the file, if u dont know this function it is provided below. The validation rules are as follows: (This is code for Delphi 7)

The first field in each record is the name of a company, the second is the customer code of that company.  The third field is the number of deliveries to that company that have been recorded.  After that should come a series of dates, one for each delivery.

Validation
The rules are as follows:
-      Names consist of letters, spaces, apostrophes or hyphens only.  A name must contain at least 2 letters.
-      The customer code consists of 7 digits, followed by a “/” character, followed by a single digit.
-      The number of deliveries must be a non-negative number.  There must be one date for each delivery.
-      A date must contain day, month and year separated by “-“ characters.  The date must be a valid date within the last 12 months.

Sample valid data:
Zappo Pizzas, 8976609/3, 1, 31-7-2002
Grubstakes, 4459873/1, 3, 24-7-2002, 12-8-2002, 26-8-2002

GetField:

function GetField(var sLine: string): string;
{ Purpose :       Searches an input string and returns the first
                  field it finds
  Params in/out:  sLine, the text to search
  Returns:        The text representing the first field found
  Comment:        This function is local to FileRead and may be called
                  ONLY from within it.
                  A field is defined as any text before a comma or line
                  break. The data in this file is comma separated:
                    <Part ID> , <Part cost> , <Quantity in stock> <LB>
                  Once a field is copied it is deleted.
}
var
   iCount :         integer;  // Loop counter only
   iCommaPos : integer;  // Holds the position of the first comma
   sField :    string;   // Holds the return string
begin
   // Make sure a string has been supplied!
   if Length(sLine) > 0 then
   begin
       // Find the first comma, if any
       iCommaPos := Pos(',', sLine);

       // Has a comma been found?  Pos returns zero if not.
       if iCommaPos > 0 then
       begin
          sField := '';
          // Copy from start of string up to, but not including, the comma
          for iCount := 1 to iCommaPos - 1 do
          begin
              sField := sField + sLine[iCount];     // Copy one character
          end;

          { Delete the field just copied.  As sLine is passed by
            reference (using var), the deletion will affect the
            string held in FileRead.
          }
          Delete(sLine, 1, iCommaPos);
       end
       else
       begin // No commas - copy all the text
           sField := sLine;
           sLine := '';      // Delete line
       end;
   end
   else
   begin
       sField := '';    // Empty string in, empty string out!
   end;

   // Return the extracted field
   Result := Trim(sField);
end;

Thanx
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2004

Commented:
a fastcoded sample

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Memo2: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    sourceList : TstringList;  //simulate Input
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  SourceList := TstringList.Create;  //simulate Input
  SourceList.Add('Zappo Pizzas, 8976609/3, 1, 31-7-2002');
  SourceList.Add('Grubstakes, 4459873/1, 3, 24-7-2002, 12-8-2002, 26-8-2002');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  SourceList.Free;
end;

function splitstr(var astring : String; Delimiter : String) : String;
var
  p : Integer;
begin
  result := '';
  if AString <> '' then
  begin
    p := pos(Delimiter,AString);
    if p > 0 then
    begin
      result := copy(AString,1,p-1);
      AString := copy(AString,p+length(Delimiter),maxLongInt);
    end
    else
    begin
      result := AString;
      AString := '';
    end;
  end;
end;

Function CheckName(AString : String) : Boolean;
const
  ValidChars = [' '..'Z','a'..'z']; //expand to your needs
var
  i : Integer;
begin
  i := 1;
  Result := length(AString) > i;
  if Result then
    while (result) and
          (i <= length(AString)) do
    begin
      result := (AString[i] in ValidChars);
      inc(i);
    end;
end;

Function CheckCode(AString : String) : Boolean;
const
  ValidChars = ['0'..'9']; //expand to your needs
var
  i : Integer;
  s1, s2 : String;
begin
  s2 := AString;
  s1 := splitstr(s2,'/');
  //check prefix
  result := length(s1) = 7;
  if result then
  begin
    i := 1;
    while (result) and (i <= 7) do
    begin
      result := s1[i] in ValidChars;
      inc(i);
    end;
  end;
  //check suffix
  if result then
  begin
    result := (length(s2) = 1) and (s2[1] in ValidChars);
  end;
end;

function Checkdelivery(AString : String) : Boolean;
var i : integer;
begin
  result := true;
  try
    i := strToint(Astring);
  except
    result := false;
  end;
  if result then
    result := i > 0;
end;

function CheckDate(AString : String) : Boolean;
var
  s,ds,ms,ys : String;
  d,m,y : Integer;
  TestDate : TDateTime;
begin
  s := AString;
  ds := SplitStr(s,'-');
  ms := SplitStr(s,'-');
  ys := SplitStr(s,'-');
  result := s = '';
  if result then
  try
    d := StrToInt(ds);
    m := StrToInt(ms);
    y := StrToInt(ys);
  except
    result := false;
  end;
  if result then
  try
    testdate := EnCodeDate(y,m,d);
  except
     result := false;
  end;
end;

Function RulesOK(AFieldList : TStrings) : Boolean;
var I,n : integer;
begin
  result := True;
  i := 0;
  Result := AFieldList.Count >= 4;  //First Check
  while (Result) and (i < AFieldList.Count) do
  begin
    case i of
      0 : result := CheckName(AFieldList[i]);
      1 : result := CheckCode(AFieldList[i]);
      2 : begin
            result := CheckDelivery(AFieldList[i]);
            if result then
            begin
              n := strToInt(AFieldList[i]);
              result := AFieldList.Count - 3 = n;
            end;
          end;
      else
        result := CheckDate(AFieldList[i]);
    end;
    inc(i);
  end;
end;



Procedure DoProcessInput(ASource,AValidList,AInvalidList : TStrings);
var
  I : Integer;
  sl : TstringList;
  s : String;
begin
  sl := TstringList.Create;
  try
    for i := 0 to ASource.Count-1 do
    begin
      sl.Clear;
      s := ASource[i];
      while s <> '' do
        sl.Add(trim(splitStr(s,',')));
      if RulesOK(sl) then
        AValidList.Add(ASource[i])
      else
        AInValidList.Add(ASource[i]);
    end;
  finally
    sl.Free;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Clear;
  Memo2.Lines.Clear;
  DoProcessInput(SourceList,Memo1.Lines,Memo2.Lines);
end;

end.

meikl ;-)

Author

Commented:
Thanx for the code but can u pls modify it so that I can use GetField function, bec it has to be in the code.

Cheers

Author

Commented:
Also with that code how am I suppose to read a file into the memo box? & it doesnt follow the rules I have mentioned
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

Top Expert 2004

Commented:
>Also with that code how am I suppose to read a file into the memo box?
procedure TForm1.Button1Click(Sender: TObject);
begin
  SourceList.Lines.LoadFromFile('PutYourFileNameHere');  //i.e you may use an opendialog here
  Memo1.Lines.Clear;
  Memo2.Lines.Clear;
  DoProcessInput(SourceList,Memo1.Lines,Memo2.Lines);
end;

>code but can u pls modify it so that I can use GetField function
see the splitstr function

wrapper
Function GetField(Var Str : String) : String;
begin
  result := Trim(Splistr(Str,','));
end;


>it doesnt follow the rules I have mentioned
which rule does you mean?

be a bit flexibel

meikl ;-)

Author

Commented:
Sorry abt all the hassel bro
but can u ps use the getfield function I used at the top
Top Expert 2004

Commented:
why i should, your code above isn't very performant,
but well

Procedure DoProcessInput(ASource,AValidList,AInvalidList : TStrings);
var
  I : Integer;
  sl : TstringList;
  s : String;
begin
  sl := TstringList.Create;
  try
    for i := 0 to ASource.Count-1 do
    begin
      sl.Clear;
      s := ASource[i];
      while s <> '' do
        sl.Add(GetField(s));  //here you may use it
      if RulesOK(sl) then
        AValidList.Add(ASource[i])
      else
        AInValidList.Add(ASource[i]);
    end;
  finally
    sl.Free;
  end;
end;

is it i kind of homework?

meikl ;-)
Top Expert 2004
Commented:
any further question about this?

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial