| **Navigation:**  [[introduction.htm|Language Reference]] > 13 - Built-in Functions >====== SUB (return substring of string) ====== | [[strpos return matching value position .htm|{{btn_prev_n.gif|Previous page}}]][[introduction.htm|{{btn_home_n.gif|Return to chapter overview}}]][[suspend suspend thread execution.htm|{{btn_next_n.gif|Next page}}]] | | || **SUB(**//string//,//position//,//length//**)** {{blk2blue.jpg|blk2blue.jpg}} | **SUB** | Returns a portion of a string. | | //string// | A string constant, variable or expression. | | //position// | A integer constant, variable, or expression. If positive, it points to a character position relative to the beginning of the //string//. If negative, it points to the character position relative to the end of the //string// (i.e., a //position// value of -3 points to a position 3 characters from the end of the //string//). If position is omitted or zero, the default in Clarion Win32 is 1.In Clarion#, //position// uses a zero-based index. A value of zero (0) points to character position 1, 1 points to 2, etc. | | //length// | A numeric constant, variable, or expression of number of characters to return. | The **SUB** procedure parses out a sub-string from a //string// by returning //length// characters from the //string//, starting at //position//. The SUB procedure is similar to the "string slicing" operation on STRING, CSTRING, and PSTRING variables. SUB is less flexible and efficient than string slicing, but SUB is "safer" because it ensures that the operation does not overflow the bounds of the //string//. "String slicing" is more flexible than SUB because it may be used on both the destination and source sides of an assignment statement, while the SUB procedure can only be used as the source. It is more efficient because it takes less memory than individual character assignments or the SUB procedure (however, no bounds checking occurs). To take a "slice" of a string, the beginning and ending character numbers are separated by a colon (:) and placed in the implicit array dimension position within the square brackets ([]) of the string. The position numbers may be integer constants, variables, or expressions. If variables are used, there must be at least one blank space between the variable name and the colon separating the beginning and ending number (to prevent PREfix confusion). **Return Data Type:     **STRING **Example:** | ** !SUB('ABCDEFGHI',1,1) returns 'A'** | | ** !SUB('ABCDEFGHI',-1,1) returns 'I'** | | ** !SUB('ABCDEFGHI',4,3) returns 'DEF'** | | **!Get the file extension using SUB procedure** | | ** Extension = ****SUB****(FileName,INSTRING('.',FileName,1,1)+1,3)** | | | | **!The same operation using string slicing** | | ** Extension = FileName[(INSTRING('.',FileName,1,1)+1) : (INSTRING('.',FileName,1,1)+3)]** | | **!********************** | | **IF FILEDIALOG('Pick file',FileName)** | | **   IF ****SUB****(FileName,1,2)='\\' THEN ** | | **      STOP('\\UNC paths are not supported!')** | | **   ELSIF UPPER(****SUB****(FileName,1,11))='C:\WINDOWS\' THEN ** | | **      STOP('Do not select Windows folder!')** | | **   END** | | **END** | | | | **IF FILEDIALOG('Pick file',FileName)** | | **   CASE UPPER(****SUB****(CLIP(FileName),-4,4))  !Note CLIP(), else get trailing spaces** | | **   OF '.TPS' ; DO TPS_File** | | **   OF '.DBF' ; DO DBase_File** | | **   OF '.CSV' ; DO Text_File** | | **   ELSE** | | **      Message('Unknown file type ' & RIGHT(FileName,4))** | | **   END** | | **END** | | | **See Also:** [[left return left justified string .htm|LEFT]] [[right return right justified string .htm|RIGHT]] [[instring return substring position .htm|INSTRING]] [[string fixed length string .htm|STRING]] [[cstring fixed length null terminated string .htm|CSTRING]] [[pstring embedded length byte string .htm|PSTRING]] [[implicit string arrays and string slicing.htm|String Slicing]]