Modules/ooc2Strings

From vishap oberon compiler
Revision as of 19:25, 5 February 2016 by Noch (talk | contribs)
Jump to navigation Jump to search

Deutsch (de) | English (en) | հայերեն (hy)

Module ooc2Strings

Description

As string manipulation is so common to programming problems, the OOC library provides additional string operations to those built into Oberon-2. The Oberon-2 language defines a string as a character array containing 0X as an embedded terminator. This means that an ARRAY OF CHAR isn't necessarily a string. The module `Strings' provides string manipulation operations for use on terminated character arrays.

Recall that string literals are sequences of characters enclosed in single (') or double (") quote marks. The opening quote must be the same as the closing quote and must not occur within the string. Passing a string literal of length n as an argument to a procedure expecting an ARRAY OF CHAR delivers n+1 characters to the parameter.

The number of characters in a string (up to the terminating 0X) is called its length. A string literal of length 1 can be used wherever a character constant is allowed and vice versa.

Please note: All procedures reading and producing strings expect termination with 0X. The behaviour of a procedure is undefined if one of its input parameters is an unterminated character array. Behavior is also undefined if a negative value is used as an input parameter that represents an array position or a string length.

Copying and Concatenation

This section describes procedures that construct a string value, and attempt to assign it to a variable parameter. All of these procedures have the property that if the length of the constructed string value exceeds the capacity of the variable parameter, a truncated value is assigned. The constructed string always ends with a string terminator 0X.

Also described are procedures that provide for pre-testing of the operation-completion conditions for the copying and concatenation procedures.

Procedure: Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR)
This procedure copies the string value of source to destination. It is equivalent to the predefined procedure COPY. Unlike COPY, this procedure can be assigned to a procedure variable.
Function: CanAssignAll (sourceLength: INTEGER; VAR destination: ARRAY OF CHAR): BOOLEAN


Returns TRUE if a number of characters, indicated by sourceLength, will fit into destination; otherwise returns FALSE.


Pre-condition: sourceLength is not negative.

Example:

VAR source:      ARRAY 6 OF CHAR; 
    destination: ARRAY 4 OF CHAR; 

source := ""; 
Strings.CanAssignAll (Strings.Length (source), destination);
=> TRUE
Strings.Assign (source, destination);
=> destination = ""
source := "abc"; 
Strings.CanAssignAll (Strings.Length (source), destination);
=> TRUE
Strings.Assign (source, destination);
=> destination = "abc"
source := "abcd"; 
Strings.CanAssignAll (Strings.Length (source), destination);
=> FALSE
Strings.Assign (source, destination);
=> destination = "abc"
<syntaxhighlight lang="oberon2" style="font-size:10pt">
Procedure: Extract (source: ARRAY OF CHAR; startPos, numberToExtract: INTEGER; VAR destination: ARRAY OF CHAR)


This procedure copies at most numberToExtract characters from source to destination, starting at position startPos in source. An empty string value will be extracted if startPos is greater than or equal to Length(source).


Pre-condition: startPos and numberToExtract are not negative.
Function: CanExtractAll (sourceLength, startPos, numberToExtract: INTEGER; VAR destination: ARRAY OF CHAR): BOOLEAN


Returns TRUE if there are numberToExtract characters starting at startPos and within the sourceLength of some string, and if the capacity of destination is sufficient to hold numberToExtract characters; otherwise returns FALSE.
Pre-condition: sourceLength, startPos, and numberToExtract are not negative.

Example:

VAR source:      ARRAY 6 OF CHAR; 
    destination: ARRAY 4 OF CHAR; 

source := "abcde"; 

Strings.CanExtractAll (Strings.Length (source), 0, 3, destination);
=> TRUE
Strings.Extract (source, 0, 3, destination);
=> destination = "abc"
 
Strings.CanExtractAll (Strings.Length (source), 3, 2, destination);
=> TRUE
Strings.Extract (source, 3, 2, destination);
=> destination = "de"
Strings.CanExtractAll (Strings.Length (source), 0, 4, destination);
=> FALSE
Strings.Extract (source, 0, 4, destination);
=> destination = "abc"
Strings.CanExtractAll (Strings.Length (source), 2, 4, destination);
=> FALSE
Strings.Extract (source, 2, 4, destination);
=> destination = "cde"
Strings.CanExtractAll (Strings.Length (source), 5, 1, destination);
=> FALSE
Strings.Extract (source, 5, 1, destination);
=> destination = ""
Strings.CanExtractAll (Strings.Length (source), 4, 0, destination);
=> TRUE
Strings.Extract (source, 4, 0, destination);
=> destination = ""
Procedure: Delete (VAR stringVar: ARRAY OF CHAR; startPos, numberToDelete: INTEGER)


Deletes at most numberToDelete characters from stringVar, starting at position startPos. The string value in stringVar is not altered if startPos is greater than or equal to Length(stringVar).


Pre-condition: startPos and numberToDelete are not negative.
Function: CanDeleteAll (stringLength, startPos, numberToDelete: INTEGER): BOOLEAN


Returns TRUE if there are numberToDelete characters starting at startPos and within the stringLength of some string; otherwise returns FALSE.


Pre-condition: stringLength, startPos and numberToDelete are not negative.

Example:

VAR stringVar: ARRAY 6 OF CHAR; 
    startPos:  INTEGER; 
 
stringVar := "abcd";
Strings.CanDeleteAll (Strings.Length (stringVar), 0, 4);
=> TRUE
Strings.Delete (stringVar, 0, 4);
=> stringVar = ""
 
stringVar := "abcd";
Strings.CanDeleteAll (Strings.Length (stringVar), 1, 2);
=> TRUE
Strings.Delete (stringVar, 1, 2);
</syntaxhighlight>
=> stringVar = "ad"
stringVar := "abcd";
Strings.CanDeleteAll (Strings.Length (stringVar), 0, 5);
</syntaxhighlight>
=> FALSE
Strings.Delete (stringVar, 0, 5);
</syntaxhighlight>
=> stringVar = ""
Procedure: Insert (source: ARRAY OF CHAR; startPos: INTEGER; VAR destination: ARRAY OF CHAR)


Inserts source into destination at position startPos. After the call, destination contains the string that is contructed by first splitting destination at the position startPos and then concatenating the first half, source, and the second half. The string value in destination is not altered if startPos is greater than Length(source). If startPos=Length(source), then source is appended to destination.


Pre-condition: startPos is not negative.
Function: CanInsertAll (sourceLength, startPos: INTEGER; VAR destination: ARRAY OF CHAR): BOOLEAN
</syntaxhighlighting>


::Returns TRUE if there is room for the insertion of sourceLength characters from some string into destination starting at startPos; otherwise returns FALSE.


::Pre-condition: sourceLength and startPos are not negative. 

Example:

<syntaxhighlight lang="oberon2" style="font-size:10pt">
VAR source:      ARRAY 6 OF CHAR; 
    destination: ARRAY 8 OF CHAR; 

source := "abc";
destination := "012"; 

Strings.CanInsertAll (Strings.Length (source), 1, destination);
=> TRUE
Strings.Insert (source, 1, destination);
=> destination = "0abc12"
Strings.CanInsertAll (Strings.Length (source), 3, destination);
=> TRUE
Strings.Insert (source, 3, destination);
=> destination = "012abc"
Strings.CanInsertAll (Strings.Length (source, 4, destination);
=> FALSE
Strings.Insert (source, 4, destination);
=> destination = "012"
source := "abcde"; 
destination := "012356"; 

Strings.CanInsertAll (Strings.Length (source), 0, destination);
=> FALSE
Strings.Insert (source, 0, destination);
=> destination = "abcde01"
Strings.CanInsertAll (Strings.Length (source), 4, destination);
=> FALSE
Strings.Insert (source, 4, destination);
=> destination = "0123abc"
Procedure: Replace (source: ARRAY OF CHAR; startPos: INTEGER; VAR destination: ARRAY OF CHAR)
::Copies source into destination starting at position startPos. The existing character values of destination are overwritten (i.e., replaced by) source's values. Copying stops when all of source has been copied, or when the last character of the string value in destination has been replaced. The string value in destination is not altered if startPos is greater than or equal to Length(source).

::Notice that Replace does not continue past the string terminator 0X in destination. That is, Length(destination) will never be changed by Replace.


::Pre-condition: startPos is not negative. 

<syntaxhighlight lang="oberon2" style="font-size:10pt">
Function: CanReplaceAll (sourceLength, startPos: INTEGER; VAR destination: ARRAY OF CHAR): BOOLEAN
Returns TRUE if there is room for the replacement of sourceLength characters in destination starting at startPos; otherwise returns FALSE.


Pre-condition: sourceLength and startPos are not negative.

Example:

VAR source, destination: ARRAY 6 OF CHAR; 

source := "ab"; destination := "1234"; 
Strings.CanReplaceAll (Strings.Length (source), 0, destination);
=> TRUE
Strings.Replace (source, 0, destination);
=> destination = "ab34"
source := "abc"; destination := "1234"; 
Strings.CanReplaceAll (Strings.Length (source), 2, destination);
=> FALSE
Strings.Replace (source, 2, destination);
=> destination = "12ab"
source := ""; destination := "1234"; 
Strings.CanReplaceAll (Strings.Length (source), 4, destination);
=> TRUE
Strings.Replace (source, 4, destination);
=> destination = "1234"
source := ""; destination := "1234"; 
Strings.CanReplaceAll (Strings.Length (source), 5, destination);
=> FALSE
Strings.Replace (source, 5, destination);
=> destination = "1234"


Procedure: Append (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR)
Appends source to destination.
Function: CanAppendAll (sourceLength: INTEGER; VAR destination: ARRAY OF CHAR): BOOLEAN
Returns TRUE if there is sufficient room in destination to append a string of length sourceLength to the string in destination; otherwise returns FALSE.


Pre-condition: sourceLength is not negative.

Example:

VAR source, destination: ARRAY 6 OF CHAR; 

source := "12"; destination := "abc"; 
Strings.CanAppendAll (Strings.Length (source), destination);
=> TRUE
Strings.Append (source, destination);
=> destination = "abc12"
source := "123"; destination := "abc"; 
Strings.CanAppendAll (Strings.Length (source), destination);
=> FALSE

Strings.Append (source, destination);

=> destination = "abc12"
source := "123"; destination := "abcde"; 
Strings.CanAppendAll (Strings.Length (source), destination);
=> FALSE
Strings.Append (source, destination);
=> destination = "abcde"


Procedure: Concat (source1, source2: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR)
Concatenates source2 onto source1 and copies the result into destination. Note that any previous contents of destination are destroyed by Concat.
Function: CanConcatAll (source1Length, source2Length: INTEGER; VAR destination: ARRAY OF CHAR): BOOLEAN
Returns TRUE if there is sufficient room in destination for a two strings of lengths source1Length and source2Length; otherwise returns FALSE.


Pre-condition: source1Length and source2Length are not negative.

Example:

VAR source1, source2: ARRAY 5 OF CHAR; 
::destination: ARRAY 6 OF CHAR; 

source1 := "12"; source2 := "abc"; 
Strings.CanConcatAll (Strings.Length (source1), 
::                  Strings.Length (source2), destination);
=> TRUE

Strings.Concat (source1, source2, destination); </syntaxhighlight>

=> destination = "12abc"

source1 := "123"; source2 := "abc"; Strings.CanConcatAll (Strings.Length (source1),

                     Strings.Length (source2), destination);  

</syntaxhighlight>

=> FALSE

Strings.Concat (source1, source2, destination); </syntaxhighlight>

=> destination = "123ab"
source1 := ""; source2 := "abc"; 
Strings.CanConcatAll (Strings.Length (source1), 
                      Strings.Length (source2), destination);
=> TRUE

Strings.Concat (source1, source2, destination); </syntaxhighlight>

=> destination = "abc"

Comparing & Searching Strings

These procedures provide for the comparison of string values, and for the location of substrings within strings.

Function: Compare (stringVal1, stringVal2: ARRAY OF CHAR): CompareResults

Returns less, equal, or greater, according as stringVal1 is lexically less than, equal to, or greater than stringVal2.
Please note: Oberon-2 already contains predefined comparison operators on strings.
Data type: CompareResults = SHORTINT
CompareResults and its related constants are used with procedure Compare. The following constants are defined for its value:
Constant: less
Constant: equal
Constant: greater

Example:

VAR stringVal1, stringVal2: ARRAY 4 OF CHAR; 

stringVal1 := "abc"; stringVal2 := "abc"; 
Strings.Compare (stringVal1, stringVal2);
=> equal

stringVal1 := "abc"; stringVal2 := "abd"; Strings.Compare (stringVal1, stringVal2); </syntaxhighlight>

=> less
stringVal1 := "ab"; stringVal2 := "abc"; 
Strings.Compare (stringVal1, stringVal2);
=> less
stringVal1 := "abd"; stringVal2 := "abc"; 
Strings.Compare (stringVal1, stringVal2);
=> greater
Function: Equal (stringVal1, stringVal2: ARRAY OF CHAR): BOOLEAN
Returns stringVal1=stringVal2. That is, Equal returns TRUE if the string value of stringVal1 is the same as the string value of stringVal2; otherwise, it returns FALSE. Unlike the predefined operator =, this procedure can be assigned to a procedure variable.

Example:

VAR stringVal1, stringVal2: ARRAY 4 OF CHAR; 
 
stringVal1 := "abc"; stringVal2 := "abc"; 
Strings.Equal (stringVal1, stringVal2);
=> TRUE
stringVal1 := "abc"; stringVal2 := "abd"; 
Strings.Equal (stringVal1, stringVal2);
=> FALSE
stringVal1 := "ab"; stringVal2 := "abc"; 
Strings.Equal (stringVal1, stringVal2);
=> FALSE


Procedure: FindNext (pattern, stringToSearch: ARRAY OF CHAR; startPos: INTEGER; VAR patternFound: BOOLEAN; VAR posOfPattern: INTEGER)
This procedure is used to locate a pattern string within another string. It searches forward through stringToSearch for next occurrence of pattern; startPos is the starting position of the search (within stringToSearch).
If startPos<Length(stringToSearch) and pattern is found, patternFound is returned as TRUE and posOfPattern contains the start position in stringToSearch of pattern (i.e., posOfPattern is in the range
[startPos..Length(stringToSearch)-1])
Otherwise, patternFound is returned as FALSE and posOfPattern is unchanged.
If startPos>Length(stringToSearch)-Length(pattern), then patternFound is returned as FALSE.


Pre-condition: startPos is not negative.

Example:

VAR pattern:        ARRAY 4 OF CHAR; 
::stringToSearch: ARRAY 9 OF CHAR; 
::found: BOOLEAN; 
::posOfPattern: INTEGER; 

pattern := "ab"; stringToSearch := "ababcaba"; 
Strings.FindNext (pattern, stringToSearch, 0, found, posOfPattern);
=> TRUE, posOfPattern = 0
Strings.FindNext (pattern, stringToSearch, 1, found, posOfPattern);
:=> TRUE, posOfPattern = 2
Strings.FindNext (pattern, stringToSearch, 2, found, posOfPattern);
:=> TRUE, posOfPattern = 2

<syntaxhighlight lang="oberon2" style="font-size:10pt">
Strings.FindNext (pattern, stringToSearch, 3, found, posOfPattern);
=> TRUE, posOfPattern = 5
Strings.FindNext (pattern, stringToSearch, 4, found, posOfPattern);
=> TRUE, posOfPattern = 5
Strings.FindNext (pattern, stringToSearch, 5, found, posOfPattern);
=> TRUE, posOfPattern = 5
Strings.FindNext (pattern, stringToSearch, 6, found, posOfPattern);
=> FALSE, posOfPattern unchanged
pattern := ""; stringToSearch := "abc"; 
Strings.FindNext (pattern, stringToSearch, 2, found, posOfPattern);
=> TRUE, posOfPattern = 2

Strings.FindNext (pattern, stringToSearch, 3, found, posOfPattern); </syntaxhighlight>

=> FALSE, posOfPattern unchanged


Procedure: FindPrev (pattern, stringToSearch: ARRAY OF CHAR; startPos: INTEGER; VAR patternFound: BOOLEAN; VAR posOfPattern: INTEGER)
::This procedure is used to locate a pattern string within another string. It searches backward through stringToSearch for a previous occurrence of pattern; startPos is the starting position of the search (within stringToSearch).

::If pattern is found, patternFound is returned as TRUE and posOfPattern contains the start position in stringToSearch of pattern (i.e., posOfPattern is in the range [0..startPos]).

::Otherwise, patternFound is returned as FALSE and posOfPattern is unchanged (in this case, the pattern might be found at startPos).

::The search will fail if startPos is negative.

::If startPos>Length(stringToSearch)-Length(pattern) the whole string value is searched. 

Example:

<syntaxhighlight lang="oberon2" style="font-size:10pt">
VAR pattern:        ARRAY 4 OF CHAR; 
::stringToSearch: ARRAY 9 OF CHAR; 
::found: BOOLEAN; 
::posOfPattern: INTEGER; 

pattern := "abc"; stringToSearch := "ababcaba"; 
Strings.FindPrev(pattern, stringToSearch, 1, found, posOfPattern);
=> FALSE, posOfPattern unchanged
Strings.FindPrev(pattern, stringToSearch, 2, found, posOfPattern);
=> TRUE, posOfPattern = 2
Strings.FindPrev(pattern, stringToSearch, 3, found, posOfPattern);
=> TRUE, posOfPattern = 2
pattern := "ab"; stringToSearch := "ababcaba"; 
Strings.FindPrev(pattern, stringToSearch, 0, found, posOfPattern);
=> TRUE, posOfPattern = 0
Strings.FindPrev(pattern, stringToSearch, 1, found, posOfPattern);
=> TRUE, posOfPattern = 0
Strings.FindPrev(pattern, stringToSearch, 2, found, posOfPattern);
=> TRUE, posOfPattern = 2
Strings.FindPrev(pattern, stringToSearch, 3, found, posOfPattern);
=> TRUE, posOfPattern = 2
Strings.FindPrev(pattern, stringToSearch, 4, found, posOfPattern);
=> TRUE, posOfPattern = 2
Strings.FindPrev(pattern, stringToSearch, 5, found, posOfPattern);
=> TRUE, posOfPattern = 5
pattern := ""; stringToSearch := "abc"; 
Strings.FindPrev(pattern, stringToSearch, -1, found, posOfPattern);
=> FALSE, posOfPattern unchanged
Strings.FindPrev(pattern, stringToSearch, 0, found, posOfPattern);
=> TRUE, posOfPattern = 0
Strings.FindPrev(pattern, stringToSearch, 4, found, posOfPattern);
=> TRUE, posOfPattern = 3


Procedure: FindDiff (stringVal1, stringVal2: ARRAY OF CHAR; VAR differenceFound: BOOLEAN; VAR posOfDifference: INTEGER)
Compares the string values in stringVal1 and stringVal2 for differences. If they are equal, differenceFound is returned as FALSE; and TRUE otherwise.


If differenceFound is TRUE, posOfDifference is set to the position of the first difference; otherwise posOfDifference is unchanged.

Example:

VAR stringVal1, stringVal2: ARRAY 4 OF CHAR; 
::diffFound: BOOLEAN;
::posOfDiff: INTEGER; 

stringVal1 := "abc"; stringVal2 := "abc"; 
Strings.FindDiff(stringVal1, stringVal2, diffFound, posOfDiff);
=> FALSE, posOfDifference unchanged
stringVal1 := "ab"; stringVal2 := "ac"; 
Strings.FindDiff(stringVal1, stringVal2, diffFound, posOfDiff);
=> TRUE, posOfDifference = 1
stringVal1 := "ab"; stringVal2 := "a"; 
Strings.FindDiff(stringVal1, stringVal2, diffFound, posOfDiff);
=> TRUE, posOfDifference = 1

Miscellaneous Strings Procedures

Function: Length (stringVal: ARRAY OF CHAR): INTEGER
Returns the string length of stringVal. This is equal to the number of characters in stringVal up to and excluding the first 0X.

Example:

Strings.Length("Hello, world"); 
:
=> 12
VAR stringVal: ARRAY 6 OF CHAR; 
stringVal := ""; 
Strings.Length(stringVal);
=> 0
stringVal := "12"; 
Strings.Length(stringVal);
:
=> 2

Recall that if you instead need the total size of the character array, you should use the standard Oberon-2 function procedure LEN:

VAR aString: ARRAY 32 OF CHAR;
aString := "Hello, world";
LEN(aString)
=> 32


Procedure: Capitalize (VAR stringVar: ARRAY OF CHAR)
Applies the function CAP to each character of the string value in stringVar.

Example:

VAR stringVar: ARRAY 6 OF CHAR; 

stringVar := "abc"; 
Strings.Capitalize (stringVar);
=> stringVar = "ABC"
stringVar := "0aB";
Strings.Capitalize (stringVar);
=> stringVar = "0AB"


Origin

This module have been ported from the Optimizing Oberon Compiler's standard library.

This article was created by using Optimizing Oberon Compiler's Reference Manual as a source.