Page 1 of 1

SortStructuredArray Problems

Posted: Sun Jun 21, 2009 11:41 pm
by trather
I very much like and use PB for a number of small applications to make things easier but I am having problems with the following code. I can load the array and get the data out of the array fine but when I go to sort it I get nothing out. The data is wiped from the array.

Code: Select all

Structure EmailData
  FullName.s
  Eid.s
  Size.s
  E_Server.s
  Marsha.s
  Domain.s
  Dept.s
EndStructure

Global Dim Exchange.EmailData(1000)

;Loop to load the data in 

      Exchange(Counter)\FullName = Name$
      Exchange(Counter)\Eid = EID$
      Exchange(Counter)\Size = StrF(MG_Size,2)
      Exchange(Counter)\E_Server = Server$
      Exchange(Counter)\Marsha = Marsh$
      Exchange(Counter)\Domain = Domain$
      Exchange(Counter)\Dept = Department$


SortStructuredArray(Exchange(), 0, OffsetOf(EmailData\FullName), #PB_Sort_String)
When I take the Sortstructured command out I can get the data out to the the file but when I sort it it appeard to be deleted.

Posted: Sun Jun 21, 2009 11:56 pm
by djes
Try to initialise all your strings with ""

Posted: Mon Jun 22, 2009 12:33 am
by netmaestro
You'll need to remove any empty array elements. If your array wasn't full all the first entries will be blank and it'll look like your data was destroyed. You can also employ the optional start/end parameters if you know how many entries were read in. Possibly do a redim, etc.

Blank

Posted: Mon Jun 22, 2009 1:46 am
by trather
I thought that it might be something like that so I took the data and wrote it to a file and the array was really gone. There was nothing but the counters that I put in just to make sure that it was writing data to the file.

Also I have tried to set the whole structure to null and that also didn't work.


I am using PB version 4.30

Posted: Mon Jun 22, 2009 1:49 am
by netmaestro
iirc there was a bug in 4.30 for SortStructuredArray. Upgrade to 4.31 final and the problem should be gone.

Upgraded

Posted: Mon Jun 22, 2009 8:08 pm
by trather
I have upgraded to PB 4.31 and I still can't sort this structure. There are only about 330 item used at this time but the size may grow to about 800 in the end. So I have 1000 set as the limit for right now.

Posted: Mon Jun 22, 2009 8:36 pm
by djes
I don't see what is the point. Maybe the size of the array, but we can't be sure without a code. Here's a functional sample, showing a partially filled array, and displaying datas after sort:

Code: Select all

Structure EmailData
  FullName.s
  Eid.s
  Size.s
  E_Server.s
  Marsha.s
  Domain.s
  Dept.s
EndStructure

Global Dim Exchange.EmailData(9)

;Loop to load the data in

For counter=0 To 5

      Exchange(Counter)\FullName = Chr(65+Random(26))
;      Exchange(Counter)\FullName = Name$
      Exchange(Counter)\Eid = EID$
      Exchange(Counter)\Size = StrF(MG_Size,2)
      Exchange(Counter)\E_Server = Server$
      Exchange(Counter)\Marsha = Marsh$
      Exchange(Counter)\Domain = Domain$
      Exchange(Counter)\Dept = Department$
  Debug Exchange(Counter)\FullName
Next counter

SortStructuredArray(Exchange(), #PB_Sort_Ascending, OffsetOf(EmailData\FullName), #PB_Sort_String) 

For counter=0 To 9
  Debug Exchange(Counter)\FullName
Next counter

Re: Upgraded

Posted: Mon Jun 22, 2009 10:15 pm
by Psychophanta
trather wrote:I have upgraded to PB 4.31 and I still can't sort this structure. There are only about 330 item used at this time but the size may grow to about 800 in the end. So I have 1000 set as the limit for right now.
Put a sample showing your problem.

Full Code

Posted: Tue Jun 23, 2009 6:08 pm
by trather
Here is the full list of code with the procedures.

Code: Select all


Global Counter.l

Structure EmailData
  FullName.s
  Eid.s
  Size.s
  E_Server.s
  Marsha.s
  Domain.s
  Dept.s
EndStructure

Global Dim Exchange.EmailData(1000)


Procedure Get_Data(MailBoxFile.s)
  Master_Marsha.s = "XXXX1"
  OpenFile(1,MailBoxFile)
  Counter=1
  Header$=ReadString(1)
  Line$ = ReadString(1) 
  Repeat
    LastName$ = StringField(Line$, 1, ",")
    Last_Name$ = Right(LastName$,Len(LastName$)-1) ; remove Quotes at the start of the name
    
    FirstName$ =StringField(Line$, 2, ",")
    First_Name$ = Left(FirstName$,Len(FirstName$)-1); remove Quotes at the end of the name
    
    Name$ = Last_Name$+", "+First_Name$ ; Put Name back together with a Common
    
    EID$ =StringField(Line$, 3, ",")
    EID$ = Mid(EID$,2,Len(EID$)-2)
    
    Size$=StringField(Line$, 4, ",")
    MG_Size.f = ValF(Size$) /1024
    
    
    Server$=StringField(Line$, 5, ",")
    Server$ = Mid(Server$,2,Len(Server$)-2)
    
    Marsh$=StringField(Line$, 6, ",")
    Marsh$ = Mid(Marsh$,2,Len(Marsh$)-2)
    
    Domain$=StringField(Line$, 7, ",")
    Domain$ = Mid(Domain$,2,Len(Domain$)-2)
    
    Department$=StringField(Line$, 8, ",")
    Department$ = Mid(Department$,2,Len(Department$)-2) 
    
    If Marsh$ = Master_Marsha
      Exchange(Counter)\FullName = Name$
      Exchange(Counter)\Eid = EID$
      Exchange(Counter)\Size = StrF(MG_Size,2)
      Exchange(Counter)\E_Server = Server$
      Exchange(Counter)\Marsha = Marsh$
      Exchange(Counter)\Domain = Domain$
      Exchange(Counter)\Dept = Department$
      Counter +1
    EndIf
    Line$ = ReadString(1)
  Until Eof(1) = 1
  CloseFile(1)
EndProcedure

Procedure Write_Data(Mailout.s) 
  
  Sp$=Chr(34)+","+Chr(34)
  Header$ = Chr(34)+"Display Name"+Sp$+"EID"+Sp$+"Mailbox Size Megs"+Sp$+"Server"+Sp$+"Department"+Sp$
  Header$ + "Limit"+Sp$+"Cost"+Chr(34)
  
  OpenFile(2,Mailout)
  WriteStringN(2,Header$)
  
  For loop = 1 To Counter -1
    
    H_Nm$ = Exchange(loop)\FullName
    H_Eid$ = Exchange(loop)\Eid
    H_SZ$ = Exchange(loop)\Size
    H_Srv$ = Exchange(loop)\E_Server
    H_Mar$ = Exchange(loop)\Marsha
    H_Dom$ = Exchange(loop)\Domain
    H_DP$ = Exchange(loop)\Dept
    
    Tmp.f = ValF(H_SZ$)
    If Tmp > 100.5
      Limit$="OVER"
      TotalOver.f = (Tmp-100)*0.024
      Cost$ = StrF(TotalOver,2)
      GrandTotal.f +TotalOver
    Else 
      Limit$="------"
      Cost$ =""
    EndIf
    
    StringLine$ = Chr(34)+H_Nm$+Sp$+H_Eid$+Sp$+H_SZ$+Sp$+H_Srv$+Sp$+H_DP$+Sp$
    StringLine$ + Limit$+Sp$+Cost$+Chr(34)
    WriteStringN(2,StringLine$)
  Next
  WriteStringN(2,"")
  WriteStringN(2,Chr(34)+Sp$+Sp$+Sp$+Sp$+Sp$+"Overage Total"+Sp$+StrF(GrandTotal,2)+Chr(34))
  CloseFile(2)
EndProcedure

Get_Data("c:\test\test.csv") ; Read the data from file This works fine

SortStructuredArray(Exchange(),#PB_Sort_Ascending, OffsetOf(EmailData\FullName), #PB_Sort_String)

Write_Data("c:\test\new.csv") ; Write the data from the array to a new file This also works as long as I don't sort the array. 
  MessageRequester("Completed","Check the Drive") 
The Get _Data and the Write_Data both work fine as long as I don't sort the array. So I fuess that I am loading the data into the structured array in a format that Sort doesn't like.


Here is the header line and an example of the data that I am reading in.
"DisplayName","EID","MailboxSizeKB","Server","Marsha","Domain","department"
"Smith, Bob","SmithB007",101975,"HOTELEXCH1","XXXX1","ds","12/AAA.00"

Thank you.

Posted: Tue Jun 23, 2009 7:36 pm
by djes
Really easy! Your array is full of void, so after the sort, the datas are at the end... Try to change your line

Code: Select all

  For loop = 0 To Counter -1
to

Code: Select all

  For loop = 0 To 1000
and you'll see the result ;) (1000, as your array is 1001 elements, change your dim to 999 to have 1000 elements; I know it's a bit strange but it's an old BASIC behaviour)

Posted: Tue Jun 23, 2009 7:49 pm
by Demivec
@trather: You are misusing the array's index to write the data with. This was mentioned earlier by netmaestro.
netmaestro wrote:You'll need to remove any empty array elements. If your array wasn't full all the first entries will be blank and it'll look like your data was destroyed. You can also employ the optional start/end parameters if you know how many entries were read in. Possibly do a redim, etc.
You're doing this:

Code: Select all

After array is constructed it looks like this, counter = 2

index  data
-----  ------
0	   empty
1	   info
2      empty
.      empty
.      empty
1000   empty

After array is sorted it looks like this, counter = 2

index  data
-----  ------
0	   empty
1	   empty
2      empty
.      empty
.      empty
1000   info
When you are writing the arrays contents to disk you are looping from 1 to (counter - 1), which means you won't see the data at index 1000.

You can also simply sort the entries you read like so using the optional Start and Stop parameters in the sort. You would sort then indexes 1 to (counter-1). Sorthing this way will keep them at the indexes from 1 to (counter - 1) so they will be written out properly.

Use this to sort them properly:

Code: Select all

SortStructuredArray(Exchange(),#PB_Sort_Ascending, OffsetOf(EmailData\FullName), #PB_Sort_String,1,Counter - 1)

Thank You all

Posted: Tue Jun 23, 2009 10:19 pm
by trather
Thank you.
I got it. I changed the loop to go from 1 to 1000 and then I put in a an if statment that if the name$ was blank to no write it to the file. I thought that the empty would be at the end of the file but they are null so they are at the top of the array.

That is why even when I nulled the array elements at first I got the same results.

I was just missing that part.

Thank you all again.

Re: Thank You all

Posted: Tue Jun 23, 2009 10:23 pm
by Kaeru Gaman
trather wrote:I changed the loop to go from 1 to 1000 ...
still wrong. first element is always index 0.
in Purebasic, you Dim with the last index, not with the number of elements.
when you Dim var(1000), you have 1001 elements, from 0 to 1000.

Posted: Wed Jun 24, 2009 10:35 pm
by djes
Demivec> Very nice explanation!

Posted: Thu Jun 25, 2009 12:12 am
by Demivec
djes wrote:Demivec> Very nice explanation!
Thanks.