Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

Problem with list management...


6 replies to this topic

gronchi

gronchi
  • Members
  • 71 posts

Posted 18 November 2004 - 12:04

Hi to all,
in a script I have to do:
Get a list (strings)
Check every string and
if (length(string)<4) delete string from the list

Well, when 2 or more to-be-deleted string are adjacent the above simple algorithm fail!
That is the second to-be-deleted string will not detected.

Example:
CODE

////////////////////////////////////////////////////////////////////////////
//
// Function: checkListCT
// Purpose:  This function check a string List and delete those one with lenght < 4  
// Input:    None
// Output:   None
//
////////////////////////////////////////////////////////////////////////////
function checkListCT()

NUMBER nProgressive;
STRING szProgressive, szCurrentString;
LIST   listCT;

begin
  // list creation for my example
  listCT = ListCreate(STRINGLIST);
  ListAddString(listCT, "1.1");
  ListAddString(listCT, "1.2");
  ListAddString(listCT, "1.3");
  ListAddString(listCT, "1.3.0");
  ListAddString(listCT, "1.3.1");
  ListAddString(listCT, "1.3.1.12");
  ListAddString(listCT, "1.4");
  ListAddString(listCT, "1.4.1.7");
  ListAddString(listCT, "1.4.2.2");
  ListAddString(listCT, "1.4.2.4");
  ListAddString(listCT, "1.5");
  ListAddString(listCT, "1.5.0");

  nProgressive = ListGetFirstString (listCT, szProgressive);
  while (nProgressive != END_OF_LIST)
     // remove fictitious string (lenght < 4) from the list
     ListCurrentString (listCT, szCurrentString);
     SprintfBox(INFORMATION, "ListCurrentString 1", "ListCurrentString now is: %s\nszProgressiveString now is: %s", szCurrentString, szProgressive);
     if (StrLengthChars (szProgressive) < 4) then
        ListDeleteString (listCT);
        #ifdef DEBUG
           SprintfBox(WARNING, "checkListCT", "%s is fictitious (lenght < 4) --> removed!", szProgressive);
        #endif
        ListCurrentString (listCT, szCurrentString);
        SprintfBox(INFORMATION, "ListCurrentString 2", "ListCurrentString now is: %s\nszProgressiveString now is: %s", szCurrentString, szProgressive);
     else
        #ifdef DEBUG
           SprintfBox(INFORMATION, "checkListCT", "%s is  real!", szProgressive);
        #endif
     endif;
     nProgressive = ListGetNextString (listCT, szProgressive);
  endwhile;
  ListDestroy(listCT);

end;


My analysis (comforted by sprintf...):
1. SprintfBox(INFORMATION, "ListCurrentString 1",
ListCurrentString now is: "1.1"
szProgressiveString now is: "1.1"
2. find string "1.1" lenght < 4
3. delete string "1.1"
4. SprintfBox(INFORMATION, "ListCurrentString 2",
ListCurrentString now is: "1.2"
szProgressiveString now is: "1.1"
4. ListGetNextString, repeat while cycle
5. SprintfBox(INFORMATION, "ListCurrentString 1",
ListCurrentString now is: "1.3" <--???
szProgressiveString now is: "1.3" <--???

Where "1.2" string is finished?
Don't try to move ListGetNextString inside the if statment (when string is not deleted branch) because you'll go inside an infinite loop!

Anyone has an idea of what happened?
Solutions? (Apart the way to keep 2 list...)


Thanks to all,
ciao Giuseppe

Edited by gronchi, 18 November 2004 - 13:24.


Perotin

Perotin
  • Full Members
  • 407 posts

Posted 18 November 2004 - 13:10

it may be difficult to step through a list when some entries are deleted while stepping through ... the pointer to the current string may get lost or something.

so, it may be a workaround not to delete the strings, but to add the strings you want to another list.

btw: you should destroy the list you've created :-) (listCT <-> listJRE)
Gruß / regards
Thomas

Stefan Krueger

Stefan Krueger

    InstallSite.org

  • Administrators
  • 13,269 posts

Posted 18 November 2004 - 15:47

If I'm reading your code correctly:
In step 4 your current string is "1.2"
Then you are calling ListGetNextString which make "1.3" the current string and also assigns this to szProgressive (at the end of the while loop), and also assigns it to szCurrentString (ListCurrentString at the beginning of the while loop)

I guess the solution would be not to advance to the next string (don't call ListGetNextString) if you have deleted an entry in the current loop.

gronchi

gronchi
  • Members
  • 71 posts

Posted 18 November 2004 - 16:10

QUOTE (Stefan Krueger @ 2004-11-18 14:47)
If I'm reading your code correctly:
In step 4 your current string is "1.2"
Then you are calling ListGetNextString which make "1.3" the current string and also assigns this to szProgressive (at the end of the while loop), and also assigns it to szCurrentString (ListCurrentString at the beginning of the while loop)

I guess the solution would be not to advance to the next string (don't call ListGetNextString) if you have deleted an entry in the current loop.

I have already tried to do that but it doesn't work!
Moving ListGetNextString inside the if statment (when string is not in the delete-branch) you'll go inside an infinite loop!
That is szProgressiveString still remain "1.1"

Maybe it's a sw bug in the funcion...

AnyWay thank's,
Giuseppe


Stefan Krueger

Stefan Krueger

    InstallSite.org

  • Administrators
  • 13,269 posts

Posted 19 November 2004 - 09:31

Hard to believe. Please double check yur code and make sure it actually gets executed when the string is not deleted. I'd suggest you step through your code with the debugger to see what actually happens.


gronchi

gronchi
  • Members
  • 71 posts

Posted 19 November 2004 - 11:00

Yes hard to believe!
But let me bore you with the bare examples:

I made two blank project differening only in one line code, in the first one the string list is incremented always:
nProgressive = ListGetNextString (listCT, szProgressive);
is out of the if statment

CODE

/////////////////////////////////////////////////////////////////////////////
//                                                                            
//  File Name:    Setup.rul                                                  
//                                                                            
//  Description:  InstallShield script                                        
//                                                                            
//  Comments:     This minimal project is intended for advanced users.   To
//                create a robust project with step-by-step instructions,
//      use the Project Wizard.
//                                                                            
/////////////////////////////////////////////////////////////////////////////

// Include header files /////////////////////////////////////////////////////
#include "ifx.h"

NUMBER nProgressive;
STRING szProgressive, szCurrentString;
LIST   listCT;

program

////////////////////////////////////////////////////////////////////////////
//
// Function: checkListCT
// Purpose:  This function check a string List and delete those one with lenght < 4  
// Input:    None
// Output:   None
//
////////////////////////////////////////////////////////////////////////////


  // list creation for my example
  listCT = ListCreate(STRINGLIST);
  ListAddString(listCT, "1.1", AFTER);
  ListAddString(listCT, "1.2", AFTER);
  ListAddString(listCT, "1.3", AFTER);
  ListAddString(listCT, "1.3.0", AFTER);
  ListAddString(listCT, "1.3.1", AFTER);
  ListAddString(listCT, "1.3.1.12", AFTER);
  ListAddString(listCT, "1.4", AFTER);
  ListAddString(listCT, "1.4.1.7", AFTER);
  ListAddString(listCT, "1.4.2.2", AFTER);
  ListAddString(listCT, "1.4.2.4", AFTER);
  ListAddString(listCT, "1.5", AFTER);
  ListAddString(listCT, "1.5.0", AFTER);

  nProgressive = ListGetFirstString (listCT, szProgressive);
  while (nProgressive != END_OF_LIST)
     // remove fictitious string (lenght < 4) from the list
     ListCurrentString (listCT, szCurrentString);
     SprintfBox(INFORMATION, "ListCurrentString 1", "ListCurrentString now is: %s\nszProgressiveString now is: %s", szCurrentString, szProgressive);
     if (StrLengthChars (szProgressive) < 4) then
        ListDeleteString (listCT);
        #ifdef DEBUG
           SprintfBox(WARNING, "checkListCT", "%s is fictitious (lenght < 4) --> removed!", szProgressive);
        #endif
        ListCurrentString (listCT, szCurrentString);
        SprintfBox(INFORMATION, "ListCurrentString 2", "ListCurrentString now is: %s\nszProgressiveString now is: %s", szCurrentString, szProgressive);
     else
        #ifdef DEBUG
           SprintfBox(INFORMATION, "checkListCT", "%s is  real!", szProgressive);
        #endif
     endif;
     nProgressive = ListGetNextString (listCT, szProgressive);
  endwhile;
  ListDestroy(listCT);

endprogram


This is the Sprintf layout:
1. SprintfBox(INFORMATION, "ListCurrentString 1",
ListCurrentString now is: "1.1"
szProgressiveString now is: "1.1"
2. find string "1.1" lenght < 4
3. delete string "1.1"
4. SprintfBox(INFORMATION, "ListCurrentString 2",
ListCurrentString now is: "1.2"
szProgressiveString now is: "1.1"
4. ListGetNextString, repeat while cycle
5. SprintfBox(INFORMATION, "ListCurrentString 1",
ListCurrentString now is: "1.3" <--???
szProgressiveString now is: "1.3" <--???


... in the second one the string list is incremented only when there is no deleted string:
nProgressive = ListGetNextString (listCT, szProgressive);
is in the else branch of the if statment

CODE

/////////////////////////////////////////////////////////////////////////////
//                                                                            
//  File Name:    Setup.rul                                                  
//                                                                            
//  Description:  InstallShield script                                        
//                                                                            
//  Comments:     This minimal project is intended for advanced users.   To
//                create a robust project with step-by-step instructions,
//      use the Project Wizard.
//                                                                            
/////////////////////////////////////////////////////////////////////////////

// Include header files /////////////////////////////////////////////////////
#include "ifx.h"

NUMBER nProgressive;
STRING szProgressive, szCurrentString;
LIST   listCT;

program

////////////////////////////////////////////////////////////////////////////
//
// Function: checkListCT
// Purpose:  This function check a string List and delete those one with lenght < 4  
// Input:    None
// Output:   None
//
////////////////////////////////////////////////////////////////////////////


  // list creation for my example
  listCT = ListCreate(STRINGLIST);
  ListAddString(listCT, "1.1", AFTER);
  ListAddString(listCT, "1.2", AFTER);
  ListAddString(listCT, "1.3", AFTER);
  ListAddString(listCT, "1.3.0", AFTER);
  ListAddString(listCT, "1.3.1", AFTER);
  ListAddString(listCT, "1.3.1.12", AFTER);
  ListAddString(listCT, "1.4", AFTER);
  ListAddString(listCT, "1.4.1.7", AFTER);
  ListAddString(listCT, "1.4.2.2", AFTER);
  ListAddString(listCT, "1.4.2.4", AFTER);
  ListAddString(listCT, "1.5", AFTER);
  ListAddString(listCT, "1.5.0", AFTER);

  nProgressive = ListGetFirstString (listCT, szProgressive);
  while (nProgressive != END_OF_LIST)
     // remove fictitious string (lenght < 4) from the list
     ListCurrentString (listCT, szCurrentString);
     SprintfBox(INFORMATION, "ListCurrentString 1", "ListCurrentString now is: %s\nszProgressiveString now is: %s", szCurrentString, szProgressive);
     if (StrLengthChars (szProgressive) < 4) then
        ListDeleteString (listCT);
        #ifdef DEBUG
           SprintfBox(WARNING, "checkListCT", "%s is fictitious (lenght < 4) --> removed!", szProgressive);
        #endif
        ListCurrentString (listCT, szCurrentString);
        SprintfBox(INFORMATION, "ListCurrentString 2", "ListCurrentString now is: %s\nszProgressiveString now is: %s", szCurrentString, szProgressive);
     else
        #ifdef DEBUG
           SprintfBox(INFORMATION, "checkListCT", "%s is  real!", szProgressive);
        #endif
        nProgressive = ListGetNextString (listCT, szProgressive);
     endif;
  endwhile;
  ListDestroy(listCT);

endprogram


This is the Sprintf layout:
1. SprintfBox(INFORMATION, "ListCurrentString 1",
ListCurrentString now is: "1.1"
szProgressiveString now is: "1.1"
2. find string "1.1" lenght < 4
3. delete string "1.1"
4. SprintfBox(INFORMATION, "ListCurrentString 2",
ListCurrentString now is: "1.2"
szProgressiveString now is: "1.1"
NO --> ListGetNextString
4. repeat while cycle
5. SprintfBox(INFORMATION, "ListCurrentString 1",
ListCurrentString now is: "1.2"
szProgressiveString now is: "1.1" <--???

...

then ListCurrentString traverse all the list but szProgressiveString still remain on the first element blocking the execution (I had to oper Task Manager to end the process...)



Ozone

Ozone
  • Full Members
  • 77 posts

Posted 19 November 2004 - 18:47

When an item is deleted from the list, the list index is no longer correct.
After you delete an item in the list, your next executable instruction is:
ListCurrentString (listCT, szCurrentString);

You need to use:

ListSetIndex(listCT, LISTFIRST );
ListGetFirstString ( listCT, szProgressive );


This command will reset the list index, and effectively make you restart from the new 1st index. The script will only drop through to the end of the list when all the selected strings that meet your criteria are removed.

CODE
nProgressive = ListGetFirstString ( listCT, szProgressive );
   
while nProgressive != END_OF_LIST
   if (StrLengthChars (szProgressive) < 4) then // string is too short
       ListDeleteString(listCT);                // remove list entry
       ListSetIndex(listCT, LISTFIRST );        // reset index - important
       nProgressive = ListGetFirstString ( listCT, szProgressive );  // new 1st index
   else
       nProgressive = ListGetNextString (listCT, szProgressive );  
   endif;
endwhile;

Hope this helps.

Edited by Ozone, 19 November 2004 - 18:56.