HOME - - / - - / - - LAZARUS/ DELPHI TUTORIALS
LAZARUS/ DELPHI COURSE - - / - - / - - Other material for programmers

Lazarus and Delphi Course: Manipulating string type data.

Page URL: StrMani1.htm

This page is information rich, and a has search button at the bottom of the page.

Please don't dismiss it because it isn't full of graphics, scripts, cookies, etc!



You will probably find the text easier to read if you make your browser window much narrower than usual. You may also want to change your browser's zoom level, to enlarge the text. Opera (at least) lets you change zoom level easily. The text will adapt nicely to the settings you decide give the best results for your needs!

The lines of sample Lazarus/ Delphi code in these pages will not "wrap". I.e., if a line is too long to show in the width you have set your browser too, parts of the line will be "off the page". Those lines will still copy/paste properly, at least in Opera. Please feel free to send feedback on the choices I've made! (Will you forgive me for not forcing upon you a column of links on the left and a column of ads on the right?)

This is just one exercise in a series of Lazarus / Delphi exercises. You will probably be best served by doing them in sequence... each assumes some prior knowledge. Material © TK Boyd, sheepdogsoftware.co.uk, 4/05-6/20.

You may find typos and rough edges in this. None-the-less, the basic information should be accurate. If something seems wrong, or if you find I've assumed knowledge without explaining it in a previous lesson, please let me know. Please forgive matters of typos, etc. for now. I am not inherently sloppy! The blemishes will be dealt with later.




In this lesson,.
--- You create an application which uses string manipulation to produce some pretty patterns.

You should learn about...
--- Manipulating data which is in a string type variable
--- The words "sourcecode" and "code"
--- Sourcecode layout

You should learn more about....
--- Using loops, especially about loops within loops.
--- Putting comments in your work

Lazarus/ Delphi built in functions:
--- Copy (a part of a string)
In this lesson, you will create an application which makes pretty patterns in a memo, derived from text in a string. Most of what's in this lesson is re-use of things you already know. The "copy" function will be new.

Start a new application. Rename the form strmani1. (Name derived from "STRing MANIpulation".) Save the unit as strmani1u1. Save the project as strmani1.

Put an edit box and a memo on the form. Rename the edit box eSource. Make the edit box's OnChange handler...
procedure Tstrmani11.eSourceChange(Sender: TObject);
var sTmp,sSource:string;
    iCount:integer;
begin
memo1.clear;
sSource:=eSource.text;
sTmp:=sSource;
for iCount:=1 to 4 do begin
   memo1.lines.add(sTmp);
   sTmp:=sTmp+sTmp;
   end;//for..begin..
end;//eSourceChange
... which should give you an application which gives you...
Tst
TstTst
TstTstTstTst
TstTstTstTstTstTstTstTst
... if you enter Tst into the edit box. A fair bit of "fun" for the very small amount of work it entailled, don't you think?

Something new: Programmers often call the stuff that they write "code". This isn't "code" in the sense of secret codes, beloved of spies. It is just a noun for things like "memo1.clear; sSource:=eSource.text; sTmp:=sSource;...". It is an abbRev (u/d (c) message too. Search on "terial") 9 Jun 20. iated form of "sourcecode", which means the same thing. The .exe files which make your computer do what you want come from the sourcecode you write.

In the 60's writing programs was such hard work that it was thought that if a commercial programmer produced a line of code a day, he was making reasonable progress. In those days, a lot more planning went into program writing. Planning will always save you time, but, thankfully, our computers are more capable, and share the burden of application development better, so we can do less laborious planning (that doesn't excuse us from doing any planning!). Of course modern machines are also code gluttons. to accomplish almost the same thing probably takes ten times as many lines of code. That reactionary comment is "blind", though, like someone saying that his horse took him to the store as effectively as that newfangled, complicated, noisy, pestilential Model T thing would.
Another new thing: The Copy function.
copy('ABCDEFGHIJ',3,2)
.... boils down to 'CD'. The code fragment above says, "Look in ABCDEFGHIJ. Copy from it the part of the string starting at the third character, and take a substring that is two characters long." Note that "third character" means what it would mean in every day life. (Delphi sometimes numbers things from zero, in which case "character 3" would be the D)

There are many places where the copy function can do good work. For now we're just going to have a little fun. Eventually, we'll write out application so that if you type "This is just for fun", the computer will output...
This i
 his is
  is is
   s is j
     is ju
     is jus
      s just
        just
        just f
         ust fo
As a step towards that, make eSource.text be 'This is just for fu'. (Yes, I did leave the 'n' off on purpose.) Change the font of memo1 to Courier New, or some other monospaced font. Make eSource's OnChange handler....
procedure Tstrmani11.eSourceChange(Sender: TObject);
var sTmp,sSource:string;
    iCount:integer;
begin
memo1.clear;
sSource:=eSource.text;
if length(sSource)<10 then begin
     sTmp:='You need to input a longer line';
     memo1.lines.add(sTmp);
     end//no ; here
  else begin
     for iCount:=1 to 4 do begin
          sTmp:=copy(sSource,iCount,iCount+5);
          memo1.lines.add(sTmp);
          end;//for..begin..
     end;//.. of else block
end;//eSourceChange
When you add the "n" to "This is just for fun", you should get...
This i
his is
is is ju
s is just
You did notice I said to make the memo's font Courier New, didn't you? Most Windows fonts are proportionally spaced. An "i", say, is not as wide as a "w". The effect our application gives isn't as fun unless each letter is as wide as every other.

Before we go on, notice how the code is laid out. The indents help us keep track of the blocks in the program. For instance, we do two things if the length of eSource is less than 10. Where what we do if it isn't is easy to find because of the way the "else" sticks out.

Still on the subject of indenting for clarity: When we used Repeat...Until we wrote things like....
repeat
     sTmp:=sTmp+'x";
     inc(icount);
until iCount=5;
The until was indented the same amount as the repeat. This makes sense, because the until is the "other half" of the repeat

Somewhat inconsistently, with the end which is the "other half" of a begin, I tend to indent the end as far as all the things within the Begin... End block.

Also illogically, I tend to do If... then... else... blocks as you see above.... with the then and the else indented more than the if of which they are part.

You can be logical and consistent... or you can use something that works better! Alternatively, though it is a Very Bad Idea, you could write the Onchange handler like....
begin
memo1.clear;
sSource:=eSource.text;
if length(sSource)<10 then begin
sTmp:='You need to input a longer line';
memo1.lines.add(sTmp);
end
else begin
for iCount:=1 to 4 do begin
sTmp:=copy(sSource,iCount,iCount+5);
memo1.lines.add(sTmp);
end;
end;
end;
or even like....
begin
memo1.clear;sSource:=eSource.text;
if length(sSource)<10 then begin
sTmp:='You need to input a longer line';
memo1.lines.add(sTmp);end else begin
for iCount:=1 to 4 do begin
sTmp:=copy(sSource,iCount,iCount+5);
memo1.lines.add(sTmp); end; end; end;
.... Delphi wouldn;t care. But you would, when you tried to see what the code was doing! Generally speaking, you can break lines where you want to. One major exeption: If you are in the midst of something like 'This is a string literal', then you can't break that across two lines....

E.g. NOT allowed....
if iCount=4 then sTmp:='iCount is now
     equal to four.'
If you want to do something like that, you simply do this....
if iCount=4 then sTmp:='iCount is now '+
     'equal to four.'
Notice the space after "now". Without it, sTmp would hold 'iCount is nowequal to four.'

Multi-line comments: For little things like no ; here, you just stick // in front of the comment. If you want to write a comment that extends over several lines, you do it as follows...
(* The bracket-apostrophe pair starts
a comment running over several lines.
The comment ends when you enter an apostophe-bracket pair *)

{Curley brackets also create multi-line
comments, as you see here.}

(*You can even nest the two sorts
of comments. I recommend
using (*...*) for things which will
be in the finished sourcecode,
and {} for temporary stuff.
{be sure to spellcheck this before
it is released.} *)
Enough about all that? Back to our application....


So far, we can produce....
This i
his is
is is ju
s is just
... but we wanted....
This i
 his is
  is is ju
   s is just
Think before you try to write code. What is missing? In precise detail? What we need are some spaces. We need them at the start of each line. We need no spaces on the first line, one space on the next, two on the next, etc. If we can accept an extra space on each line (we can), then the programming becomes easier. All we need to do is change...
  else begin
     for iCount:=1 to 4 do begin
          sTmp:=copy(sSource,iCount,iCount+5);
          memo1.lines.add(sTmp);
          end;//for..begin..
     end;//.. of else block
....to......
  else begin
     for iCount:=1 to 4 do begin
          sTmp:=copy(sSource,iCount,iCount+5);
          sTmp:=copy('          ',1,iCount-1)+sTmp;
          memo1.lines.add(sTmp);
          end;//for..begin..
     end;//.. of else block
We are "nesting" things, i.e. putting one inside another. Nesting loops is a powerful tool.

If we want to produce the following without doing it the obvious way,....
123456
123456
123456
.... it is merely a matter of something like....
var iCountCol,icountRow:integer;
sTmp:string;
begin
memo1.clear;
for iCountRow:=1 to 3 do begin
   sTmp:='';
   for iCountCol:=1 to 6 do begin
      sTmp:=sTmp+inttostr(icountCol);
      end;//iCountCol
   memo1.lines.add(sTmp);
   end;//iCountRow
It may not be obvious to you at this stage, but, oddly enough, we do want to do such seemingly arcane things this "hard" way more often that you would guess!

Now that things are up and running, of course you can (and you should) tinker with the program. Make "for iCount:=1 to 4" something like "for iCount:=1 to 10;" While you are tinkering, you may well "break" the program. Try to figure out how you broke it. What is going on? You need to understand what is presented in the illustrative programs. If you just copy/paste the code from here into your Delphi without mentally wrestling with it along the way, you won't learn much. One of the great problems with any programming course is that being shown how someone else solved the problem they were interested in takes you only part of the way towards being able to define do-able things, and writing the code for them yourself. The only way to get to that skill level, I'm afraid, is lots and lots of trying. Looking at what other people have done certainly helps.. but it isn't enough.


For fun.... you don't have to do what follows. Nothing essential is introduced. New things appear, but they will also be brought up in "mainstream" lessons at some point.

You can make the display produced by the application "animated" with the following code. You should get something like what we had before, but the text will scroll up the memo, and it will move across the space of the memo several times. Besides changing the else clause as shown below, add iCount2 to the var iCount:integer; declaration at the start of the OnChange handler.
  else begin
     for iCount:=1 to 4 do begin
          sTmp:=copy(sSource,iCount,iCount+5);
          sTmp:=copy('          ',1,iCount-1)+sTmp;
          memo1.lines.add(sTmp);
          end;//for..begin..
          (*Same as before, down to here*)
     for iCount2:=0 to 3 do begin
       for iCount:=1 to 4 do begin
            memo1.lines.delete(1);
            sTmp:=copy(sSource,iCount,iCount+5);
            sTmp:=copy('          ',1,iCount-1)+sTmp;
            memo1.lines.add(sTmp);
            sleep(100);
            end;//for..begin..
            (*end of inserted stuff*)
       end; //for iCount2...
     end;//.. of else block
This, by the way, is a dreadful bit of programming. Try to forget you ever saw the sleep function. And avoid putting any program into a long loop which it has to go all the way through before anything else happens.

But I thought you'd like the "little pretty", even if I can't face explaining the right way to do something like this!



Search just this site without using forms,
Or... again to search just this site, use...

Powered by FreeFind

Site search Web search

The search engine merely looks for the words you type, so....
  *!  Spell them properly   !*
  Don't bother with "How do I get rich?" That will merely return pages with "how", "do", "I", "get" and "rich".



I have other sites...
   SheepdogSoftware site.
   My site at Arunet.


Ad from page's editor: Yes.. I do enjoy compiling these things for you... I hope they are helpful. However.. they don't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated.
Click here to visit editor's Sheepdog Software freeware, shareware page.
Link to Tutorials main page Link to Lazarus/ Delphi Course index

To email this page's editor, Tom Boyd.... Editor's email address. Suggestions welcomed! Please cite "strmani1.htm".

Click for W3.org HTML validity test Page has been tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes.

AND passes... Click to check CSS validity


One final suggestion: Be sure you know all you need to about spyware.

. . . . . P a g e . . . E n d s . . . . .