Linear Programmer looking for a clue

Just starting out? Need help? Post your questions and find answers here.
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Linear Programmer looking for a clue

Post by glennj.0158 »

Hi all -- I''m an embarrassed old fart. Began programming in the '60s and worked with linear languages like Fortran and COBOL with a little C and several more obscure languages thrown in. While I understand the conceptual basis for event-driven programming I have zero experience.

I'm looking for a resource which will answer questions like "I have the form and supporting code so what do I do to make it run?" There is clearly a user conceptual error involved because the program compiles, flashes a window, and vanishes into the night.

Files are another area where I don't even know what I don't know. I'm used to a language with some sort of record structure associated with file read/write operations. Copying a structure containing strings and/or lists cannot be as simple as getting the size of the structure and writing that many bytes to disk. Even if that worked reading it back would not correctly allocate the memory. I think I have to write the strings individually and loop through arrays and lists. A proper meta-structure will let me do this but it seems more complex than necessary.

Any pointers or suggested reading material appreciated.

Regards
Glenn
Bitblazer
Enthusiast
Enthusiast
Posts: 761
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Linear Programmer looking for a clue

Post by Bitblazer »

Welcome to Purebasic.
glennj.0158 wrote: Sat Feb 05, 2022 3:22 am Hi all -- I''m an embarrassed old fart. Began programming in the '60s and worked with linear languages like Fortran and COBOL with a little C and several more obscure languages thrown in. While I understand the conceptual basis for event-driven programming I have zero experience.

I'm looking for a resource which will answer questions like "I have the form and supporting code so what do I do to make it run?" There is clearly a user conceptual error involved because the program compiles, flashes a window, and vanishes into the night.
The crucial concept difference is the windows event loop. I suggest you start following the Purebasic survival guide or Kale's PureBasic book and use the PureBasic online documentation as additional help.

If you have any questions while doing that, you can best join the PureBasic Discord chat.
glennj.0158 wrote: Sat Feb 05, 2022 3:22 amFiles are another area where I don't even know what I don't know. I'm used to a language with some sort of record structure associated with file read/write operations. Copying a structure containing strings and/or lists cannot be as simple as getting the size of the structure and writing that many bytes to disk.
You can actually do that with PureBasic.
glennj.0158 wrote: Sat Feb 05, 2022 3:22 amEven if that worked reading it back would not correctly allocate the memory. I think I have to write the strings individually and loop through arrays and lists. A proper meta-structure will let me do this but it seems more complex than necessary.
You could just use a database to handle all the lowlevel stuff for you.

For example - the basic problem with strings is the question of length. In 2022 you additionally have to consider that every single character is likely 2 bytes in length (unicode) and not just one byte (ascii). But what (and how!) you save and restore data, depends on yourself. Either way, the fundamental problem is the size. Here is the PureBasic File function documentation. Another crucial element of PureBasic are structures. Some people store strings by a fixed length and for short strings, simply waste some disk space and limit long strings to a certain maximum size, others store strings fully dynamic by writing a header in front of any dynamic field, that contains the following length. Nowadays most people don't even use these basic methods of writing data and structures by hand anymore and instead use databases and let the database do the lowlevel handling.

With PureBasic you can do all of the approaches. Start learning the language by doing it the old way "as usual" and later use databases like the new kids who use a full blown multi-megabyte relational database to store a 8 byte fixed size username ;)

I suggest that you install discord and join the purebasic chat and start reading a lot. PureBasic as procedural language will soon feel like good old times because the conceptual hurdle of object oriented languages is not needed.
infratec
Always Here
Always Here
Posts: 7588
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Linear Programmer looking for a clue

Post by infratec »

for structures to disk ...

the simplest way is to convert the structure to a JSON string and write this to the file.
Youn can read it in again and import the JSON string to the structure.

look at the help for

Code: Select all

InsertJSONStructure()
ExtractJSONStructure()
SaveJSON()
LoadJSON()
https://www.purebasic.fr/english/viewto ... 85#p552485

With additional crypting:
https://www.purebasic.fr/english/viewto ... 30#p548630
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Re: Linear Programmer looking for a clue

Post by glennj.0158 »

Thank you both (and others who may follow) for the assist. I did find and am already reading the survival guide and will pick up and read the other references. I will have to look at the JSON as this looks like a workable short-term solution but I agree that using a DBMS to pick up the slack is a better long term solution. I'm currently using Access, Oracle and some lesser known platforms in other contexts.

The push to get back into programming came from my wife's quilting hobby. Cutting and putting together the quilt can require a lot of not-difficult-but-tedious calculation and planning. Found I enjoy the problem solving aspect a lot and learning a new language and approach is just a different kind of (sometimes frustrating) problem.

Regards
Glenn
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Re: Linear Programmer looking for a clue

Post by glennj.0158 »

I've downloaded Discord but it looks like I need an invite to the PB community server.

Glennj.0158 is my Discord handle

Regards
Glenn
infratec
Always Here
Always Here
Posts: 7588
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Linear Programmer looking for a clue

Post by infratec »

The easiest database for such a 'single' case is ... sqlite.
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Linear Programmer looking for a clue

Post by mk-soft »

The best way is via databases (SQLite, etc).

But you can also use your own file format and structures where the strings have a fixed size.
Just like you wrote your own databases back then.

Example (Had too much time)

Update 2

Code: Select all

;-TOP

; Comment : Own DataBase with static structure
; Author  : mk-soft
; Version : v1.01.2
; Create  : 05.02.2022

DeclareModule MyData
  
  Structure udtRecord
    Delete.w    ; Base flag is mark as delete. Always first entry (2 Bytes)
    ; User Data
    ID.q        ; Quad Own ID (8 Bytes)
    Name.s{20}  ; Static Unicode String (40 Bytes) 
    Age.l       ; Long (4 Bytes)
  EndStructure
  
  Declare OpenData(Filename.s)
  Declare CloseData(DataID)
  Declare CompressData(DataID)
  Declare CountRecord(DataID)
  Declare ReadRecord(DataID, RecID, *Record.udtRecord, All = #True)
  Declare WriteRecord(DataID, RecID, *Record.udtRecord)
  Declare DeleteRecord(DataID, RecID, State = #True)
  
EndDeclareModule

Module MyData
  
  EnableExplicit
  
  ; Base for all record types
  
  Macro cntRecord()
    (Lof(DataID) / SizeOf(udtRecord))
  EndMacro
  
  ; ----
  
  Procedure OpenData(Filename.s) ; Result: Database ID
    Protected DataID
    DataID = OpenFile(#PB_Any, Filename, #PB_File_SharedRead | #PB_File_SharedWrite)
    ProcedureReturn DataID
  EndProcedure
  
  Procedure CloseData(DataID)
    If IsFile(DataID)
      CloseFile(DataID)
    EndIf
  EndProcedure
  
  Procedure CompressData(DataID) ; Result: Count of delete records
    Protected readOffset.q, writeOffset, rec, cnt, delete
    Protected *record.udtRecord
    
    cnt = cntRecord() - 1
    *record = AllocateStructure(udtRecord)
    For rec = 0 To cnt
      readOffset = rec * SizeOf(udtRecord)
      FileSeek(DataID, readOffset)
      ReadData(DataID, *record, SizeOf(udtRecord))
      If *record\Delete = #True
        delete + 1
      EndIf
      If *record\Delete = #False
        FileSeek(DataID, writeOffset)
        WriteData(DataID, *record, SizeOf(udtRecord))
        writeOffset + SizeOf(udtRecord)
      EndIf
    Next
    FreeStructure(*record)
    If delete
      FileSeek(DataID, writeOffset)
      TruncateFile(DataID)
    EndIf
    ProcedureReturn delete
  EndProcedure
  
  ; ----
  
  Procedure CountRecord(DataID) ; Result: Count of records
    ProcedureReturn cntRecord()
  EndProcedure
  
  ; ----
  
  Procedure ReadRecord(DataID, RecID, *Record.udtRecord, All = #True) ; Result: Bool record read
    Protected OffRecord.q, cnt
    
    If Not *Record
      ProcedureReturn #False
    EndIf
    
    If Not IsFile(DataID)
      ProcedureReturn #False
    EndIf
    
    If RecID < 1 Or RecID > cntRecord()
      ProcedureReturn #False
    EndIf
    
    OffRecord = (RecID - 1) * SizeOf(udtRecord)
    FileSeek(DataID, OffRecord, #PB_Absolute)
    ; Mark as delete ?
    If Not All
      If ReadWord(DataID) = #True
        ProcedureReturn #False
      EndIf
    EndIf
    ; Read record
    FileSeek(DataID, OffRecord, #PB_Absolute)
    cnt = ReadData(DataID, *Record, SizeOf(udtRecord))
    If cnt <> SizeOf(udtRecord)
      ProcedureReturn #False
    Else
      ProcedureReturn #True
    EndIf
  EndProcedure
  
  Procedure WriteRecord(DataID, RecID, *Record.udtRecord) ; Result: Bool record write
    Protected OffRecord.q, cnt, new
    
    If Not *Record
      ProcedureReturn #False
    EndIf
    
    If Not IsFile(DataID)
      ProcedureReturn #False
    EndIf
    
    If RecID < 0 Or RecID > cntRecord()
      ProcedureReturn #False
    EndIf
    
    If RecID = 0
      OffRecord = Lof(DataID)
      new = #True
    Else
      OffRecord = (RecID - 1) * SizeOf(udtRecord)
    EndIf
    FileSeek(DataID, OffRecord, #PB_Absolute)
    cnt = WriteData(DataID, *Record, SizeOf(udtRecord))
    If cnt <> SizeOf(udtRecord)
      ProcedureReturn #False
    Else
      ProcedureReturn #True
    EndIf
  EndProcedure
  
  Procedure DeleteRecord(DataID, RecID, State = #True) ; Result: Bool state changed
    Protected OffRecord.q, cnt, *Record.udtRecord
    
    If Not IsFile(DataID)
      ProcedureReturn #False
    EndIf
    
    If RecID < 1 Or RecID > cntRecord()
      ProcedureReturn #False
    EndIf
    
    OffRecord = (RecID - 1) * SizeOf(udtRecord)
    FileSeek(DataID, OffRecord, #PB_Absolute)
    If WriteWord(DataID, State)
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  EndProcedure
    
EndModule

;- Example

CompilerIf #PB_Compiler_IsMainFile
  
  Global Record.MyData::udtRecord
  Global file.s, base, cnt, rec
  
  file = GetHomeDirectory() + "MyDataBase.dat"
  DeleteFile(file)
  base = MyData::OpenData(file)
  If base
    ; Add records
    Record\Name = "Tom"
    Record\Age = 8
    MyData::WriteRecord(base, 0, @Record)
    Record\Name = "Jerry"
    Record\Age = 6
    MyData::WriteRecord(base, 0, @Record)
    Record\Name = "Michael"
    Record\Age = 65
    MyData::WriteRecord(base, 0, @Record)
    
    For cnt = 1 To 100
      Record\Name = "Number " + cnt
      Record\Age = Random(100, 1)
      MyData::WriteRecord(base, 0, @Record)
    Next
    ; Delete age over 50
    cnt = MyData::CountRecord(base)
    For rec = 1 To cnt
      If MyData::ReadRecord(base, rec, @Record)
        If Record\Age > 50
          MyData::DeleteRecord(base, rec)
        EndIf
      EndIf
    Next
    
    ; Output record
    cnt = MyData::CountRecord(base)
    Debug "Count = " + cnt
    For rec = 1 To cnt
      If MyData::ReadRecord(base, rec, @Record)
        Debug "RecID " + rec + ": Mark delete = " + Record\Delete + " : Name = " + Record\Name + " / Age  = " + Record\Age
      EndIf
    Next
    
    Debug "Compress " + file
    cnt = MyData::CompressData(base)
    Debug "- " + cnt + " records deleted"
    ; Output record
    cnt = MyData::CountRecord(base)
    Debug "Count = " + cnt
    For rec = 1 To cnt
      MyData::ReadRecord(base, rec, @Record)
      Debug "RecID " + rec + ": Mark delete = " + Record\Delete + " : Name = " + Record\Name + " / Age  = " + Record\Age
    Next
    
  Else
    Debug "Error: Open " + file
  EndIf
  
CompilerEndIf

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Bitblazer
Enthusiast
Enthusiast
Posts: 761
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Linear Programmer looking for a clue

Post by Bitblazer »

glennj.0158 wrote: Sat Feb 05, 2022 3:14 pm I've downloaded Discord but it looks like I need an invite to the PB community server.

Glennj.0158 is my Discord handle

Regards
Glenn
PureBasic Discord chat
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Re: Linear Programmer looking for a clue

Post by glennj.0158 »

Thank you Bitblazer for the invite.
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Re: Linear Programmer looking for a clue

Post by glennj.0158 »

Thanks mk-soft, a much more involved response than expected!

I've just gotten onto GitHub to get the SQLite tools. I agree this is the best long-term solution.

If the quilting utilities actually become ready for prime time I will post them there.

Until/unless I migrate you get credit for the read/write scheme.

-Regards
Glenn
glennj.0158
User
User
Posts: 21
Joined: Tue Mar 31, 2020 4:43 pm
Location: Lawrenceville, NJ, USA

Field order on a form -- how to fix what the IDE gave

Post by glennj.0158 »

OK - I have a new burning question.

I used the IDE to create a simple form with 6 fields and two buttons. The fields 1-5 run down the left margin, field 6 is to the right of 5 and the buttons are on the bottom.

I expected the progression to be F1 - F2 - ... F5 - F6 - B1 -B2 and back to F1

i Get F1 - F2 - f4 - F3 - B1 - B2 - F6 - F5 and back to F1

I suspect this has something to do with field Creation order rather than screen geometry. Can I fix this without deleting and creating the form.

Regards
Glenn
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Linear Programmer looking for a clue

Post by skywalk »

Post the code created by the form editor.
You will find it is just lines of text you can edit without manipulating graphically on a screen.
I never use a form editor cause I hate wasting time clicking and dragging and clicking inside so many input fields.
Cut and paste and search and replace are your friend.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: Field order on a form -- how to fix what the IDE gave

Post by Marc56us »

glennj.0158 wrote: Tue Feb 08, 2022 3:39 am I used the IDE to create a simple form with 6 fields and two buttons. The fields 1-5 run down the left margin, field 6 is to the right of 5 and the buttons are on the bottom.
I expected the progression to be F1 - F2 - ... F5 - F6 - B1 -B2 and back to F1
i Get F1 - F2 - f4 - F3 - B1 - B2 - F6 - F5 and back to F1
I suspect this has something to do with field Creation order rather than screen geometry. Can I fix this without deleting and creating the form.
Yes,
There is no "tab-order" field. Moving from gadget to gadget is set by order in creation.
:arrow: You can edit source of form (From > Switch code / Design View) and change order of lines.

If you do not work with project, F5 launch form preview and you can verify order.
(Do not change anything else in code mode (except strings or numeric values))

I use the FD all the time, even for small applications. It saves a lot of time by taking care of the laborious part of coding (ie: anchoring gadgets in different places and resizing them automatically, creating menus, including image codes in memory, pre-filling lists, etc). For everything it can't do (popup, toolbar with 24x24 icons and multiple status bars), you can add it afterwards in the application code

:wink:
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Linear Programmer looking for a clue

Post by mk-soft »

I also use FormDesigner a lot. But under Preferences -> Form make the following setting
- New gadgets use #PB_Any by default (off)
- Generate event procedures (off)

With constants for the windows and gadgets I find better.
Even if the FormDesigner works well. I do not like the event management so and write this rather myself Or use with many gadgets also my EventDesigner V3 to create the creation of all necessary procedures and event management (see signature)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Linear Programmer looking for a clue

Post by netmaestro »

I don't recommend that new PB coders start with the form designer. The form you're making sounds relatively straightforward so it won't take much work to put a few gadgets on it with straight coding. This way you'll rapidly come to understand the workings of the event loop and my personal favorite, event binding. An event loop in one of my projects will often be no more than:

Code: Select all

Repeat : Event = WaitWindowEvent() : Until Quit
with all events bound to their individual procedures. You'll make a few mistakes, count on it. But if you follow this path you'll find that corrections to your malfunctioning code are available on the forum within minutes. Lots of us monitor Coding Questions routinely and are always glad to show the way. (There is even a bit of lighthearted competition for being first with an answer! You've gotta watch CQ like a hawk to beat RASHAD, that's for sure.)
In this way you'll come to learn the important things and understand them before letting a tool do them for you. Anyway, that's just one man's opinion.
BERESHEIT
Post Reply