/* ForEach.prg In addition clasical FOR..NEXT loop, Harbour offers another FOR loop : FOR EACH..NEXT. Simplest syntax of this loop is : FOR EACH <xValue> IN <xList> ... NEXT For arrays, this structure is equivalent to : FOR <nIndex> := 1 TO LEN( <aArray> ) <xValue> := <aArray>[ nIndex ] ... NEXT Relations and rules for <xValue> and <xList> in FOR EACH loop : If <xList> is ... <xValue> is ... ----------------- ---------------- <array> an element of <array> <string> a single character in the <string> <hash> <xValue> of <xKey> => <xValue> pair in the <hash> Strings can be processed by indexing like arrays. For string iteration, lib is xHB, so you need add xHB lib calling in the your compile command: hbmk2 -lxHB ForEach and add your source prg file : #include "xhb.ch" */ #include "xhb.ch" PROCEDURE Main() CLS aFruits := { "appricot", "cherry", "melon", "pear", "grapes", "mulberry" } c1Fruit := '' // Variable for iteration value must be exist // before FOR ... statement ? ? "Traversing an array :" ? FOR EACH c1Fruit IN aFruits ?? c1Fruit, '' NEXT /* Note that this loop is equivalent to : ? FOR n1Fruit := 1 TO LEN( aFruits ) c1Fruit := aFruits[ n1Fruit ] ?? c1Fruit, '' NEXT */ /* For a list in reverse order with classical FOR ? FOR n1Fruit := LEN( aFruits ) TO 1 STEP -1 c1Fruit := aFruits[ n1Fruit ] ?? c1Fruit, '' NEXT */ /* ... and with FOR EACH*/ ? ? "Traversing an array in revers order :" ? FOR EACH c1Fruit IN aFruits DESCEND ?? c1Fruit, '' NEXT /* Sometime we needs something like this : ? FOR n1Fruit := 1 TO LEN( aFruits ) c1Fruit := aFruits[ n1Fruit ] ?? STR( n1Fruit, 2 ), ":", c1Fruit + ';' NEXT */ /* FOR EACH loop allow us using some 'internal' functions; but a 'special' way : */ ? ? "Traversing an array with indexs :" ? FOR EACH c1Fruit IN aFruits ?? STR( c1Fruit:__ENUMINDEX(), 2 ), ":", c1Fruit + ';' NEXT cString := "This is a string" /* ... and a string example : ? ? "Iterating a string by FOR .. NEXT :" ? FOR nIndex := 1 TO LEN( cString ) ?? cString[ nIndex ] NEXT */ c1Char := '' ? ? "Iterating a string :" ? FOR EACH c1Char IN cString ?? c1Char NEXT ? ? "Iterating a string in reverse order :" ? FOR EACH c1Char IN cString DESCEND ?? c1Char NEXT ? ? "Nested loop example :" aArray := { "This is", "an array" } c1String := '' FOR EACH c1String IN aArray ? "----- Outer Loop -----" ? c1String:__ENUMINDEX(), c1String ? "----- Inner Loop -----" FOR EACH c1Char IN c1String ? c1Char:__ENUMINDEX(), c1Char NEXT NEXT ? ? "Traversing a Hash : " ? "EnumKey EnumValue EnumBase[ EnumKey ]" ? "-------- ---------------- -------------------" hSoftWare := { => } HB_HKeepOrder( hSoftWare, .T. ) hSoftWare['MinGW ' ] := 'C Compiler ' hSoftWare['Harbour' ] := 'Clipper Compiler' hSoftWare['HMG ' ] := 'GUI Library ' hProgram := NIL // { => } FOR EACH hProgram IN hSoftWare ? hProgram:__ENUMKEY(), "=>", hProgram:__ENUMVALUE(),; hProgram:__ENUMBASE()[hProgram:__ENUMKEY()] // Alternate syntax NEXT ? ? "Multiple base, multiple value : " aArrayNr := { 1, 2, 3 } aArrayEn := { "one", "two", "three" } aArrayFr := { "un", "deux", "Trois" } cNumNr := 0 cNumEn := '' cNumFr := '' FOR EACH cNumNr, cNumEn, cNumFr IN aArrayNr, aArrayEn, aArrayFr ? cNumNr, cNumEn, cNumFr NEXT @ MAXROW(), 0 WAIT "EOF ForEach.prg" RETURN // ForEach.Prg.Main()
Monthly Archives: December 2012
Operator overloading
/* Operator overloading Some operators overloaded by extending their functionalities. "$" was an operator for "checking substring existence in a string" For example : ? "A" $ "ABC" // Result: .T. ? "Z" $ "ABC" // Result: .F. Now, this operator can be used for arrays and hashs too, not only strings. See examples below. "=>" was a preprocessor operator with meaning "translate to : ...". Now, this operator can be used as a <key> - <value> separator in Hashs for define and / or assign <key> - <value> to Hashs. See examples below. "[ ]" was Array element indicator (Special) "{ }" was Literal array and code block delimiters (Special) Now, this indicators can be used for hashs too. See examples below. "+=" is self-increment operator that can be used both numeric and string values. Such as : cTest := "This" cTest += " is" ? cTest // This is nTest := 3 nTest += 10 ? nTest // 13 Now, this operator can be used for adding elements to an existing hash; ( but no for arrays ! ). Note : Extended functionalities of $ and += operators depends xHB lib. So need this usages to xHB lib and xHB.ch. See examples below. */ #include "xhb.ch" PROCEDURE Main() CLS aFruits := { "apple", "appricot", "cherry", "melon", "pear", "mulberry" } ? "aFruits", IF( "pear" $ aFruits, '', 'not ' ) + "contain pear" ? "aFruits", IF( "grapes" $ aFruits, '', 'not ' ) +"contain grapes" aComplex := ARRAY( 10 ) AEVAL( aComplex, { | x1, i1 | aComplex[ i1 ] := i1 } ) aComplex[ 5 ] := DATE() aComplex[ 7 ] := .F. ? ? "aComplex", IF( 3 $ aComplex, '', 'not ' ) + "contain 3" ? "aComplex", IF( 13 $ aComplex, '', 'not ' ) + "contain 13" ? "aComplex", IF( .T. $ aComplex, '', 'not ' ) + "contain .T." ? "aComplex", IF( .F. $ aComplex, '', 'not ' ) + "contain .F." hEmpty := { => } ? ? "hEmpty is a", VALTYPE( hEmpty ), "type variable have",; STR( LEN( hEmpty ), 1 ), "element and it's",; IF( EMPTY( hEmpty ), '', 'not' ), "Empty" hCountries := { 'Argentina' => "Buenos Aires" } hCountries += { 'Brasil' => "Brasilia" } hCountries += { 'Chile' => "Santiago" } hCountries += { 'Mexico' => "Mexico City" } ? ? "hCountries is a", VALTYPE( hCountries ), "type variable have",; STR( LEN( hCountries ), 1 ), "elements and and it's",; IF( EMPTY( hCountries ), '', 'not' ), "Empty" cCountry := NIL FOR EACH cCountry IN hCountries ? cCountry:__ENUMKEY(), "=>", cCountry:__ENUMVALUE() NEXT hDays := { 'Days' => { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" } } ? ? "hDays", IF( 'Days' $ hDays, '', 'not ' ) + "contain Days" ? "hDays", IF( "Mon" $ hDays, '', 'not ' ) + "contain Mon" ? "hDays['Days']", IF( "Fri" $ hDays["Days"], '', 'not ' ) + "contain Fri" hLanguages := { "EN" => "English" } +; { "DE" => "Deutsche" } +; { "ES" => "Español" } +; { "FR" => "Français" } +; { "IT" => "Italiano" } +; { "PL" => "Polkski" } +; { "PT" => "Português" } +; { "RU" => "Russkî" } +; { "TR" => "Türkçe" } ? ? "hLanguages is a", VALTYPE( hLanguages ), "type variable have",; STR( LEN( hLanguages ), 1 ), "elements and and it's",; IF( EMPTY( hLanguages ), '', 'not' ), "Empty" cLanguage := NIL FOR EACH cLanguage IN hLanguages ? cLanguage:__ENUMKEY(), "=>", cLanguage:__ENUMVALUE() NEXT @ MAXROW(), 0 WAIT "EOF OprOLoad.prg" RETURN // OprOLoad.Prg.Main()
Strings as array
/* StrAsArr.prg Harbour offers a very handy string manipulation method: strings can be processed by indexing as array. This sample inverts a string while converting it to uppercase. lib is xHB, so you need add xHB lib calling in the your compile command: hbmk2 -lxHB StrAsArr -run */ #include "xhb.ch" PROCEDURE Main() CLS cString := "This is a string" ? cString ? FOR n1Char := LEN( cString ) TO 1 STEP -1 cString[ n1Char ] := UPPER( cString[ n1Char ] ) ?? cString[ n1Char ] NEXT /* Result: This is a string GNIRTS A SI SIHT */ @ MAXROW(), 0 WAIT "EOF StrAsArr.prg" RETURN // StrAsArr.Main()