String matching

From Rosetta Code
(Redirected from Character matching)
Jump to: navigation, search
Task
String matching
You are encouraged to solve this task according to the task description, using any language you may know.

Basic Data Operation
This is a basic data operation. It represents a fundamental action on a basic data type.

You may see other such operations in the Basic Data Operations category, or:

Integer Operations
Arithmetic | Comparison

Boolean Operations
Bitwise | Logical

String Operations
Concatenation | Interpolation | Comparison | Matching

Memory Operations
Pointers & references | Addresses

Given two strings, demonstrate the following 3 types of matchings:

  1. Determining if the first string starts with second string
  2. Determining if the first string contains the second string at any location
  3. Determining if the first string ends with the second string

Optional requirements:

  1. Print the location of the match for part 2
  2. Handle multiple occurrences of a string for part 2.

Contents

[edit] Ada

 
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO; use Ada.Text_IO;
 
procedure Match_Strings is
S1 : constant String := "abcd";
S2 : constant String := "abab";
S3 : constant String := "ab";
begin
if S1'Length >= S3'Length and then S1 (S1'First..S1'First + S3'Length - 1) = S3 then
Put_Line (''' & S1 & "' starts with '" & S3 & ''');
end if;
if S2'Length >= S3'Length and then S2 (S2'Last - S3'Length + 1..S2'Last) = S3 then
Put_Line (''' & S2 & "' ends with '" & S3 & ''');
end if;
Put_Line (''' & S3 & "' first appears in '" & S1 & "' at" & Integer'Image (Index (S1, S3)));
Put_Line
( ''' & S3 & "' appears in '" & S2 & ''' &
Integer'Image (Ada.Strings.Fixed.Count (S2, S3)) & " times"
);
end Match_Strings;
 

Sample output:

'abcd' starts with 'ab'
'abab' ends with 'ab'
'ab' first appears in 'abcd' at 1
'ab' appears in 'abab' 2 times

[edit] Aime

text s, t;
data b;
 
s = "Bangkok";
t = "Bang";
 
b_cast(b, s);
 
o_form("starts with, embeds, ends with \"~\": ~, ~, ~\n", t, b_seek(b, t) == 0,
b_seek(b, t) != -1,
b_seek(b, t) != -1 && b_seek(b, t) + length(t) == length(s));
 
t = "ok";
 
o_form("starts with, embeds, ends with \"~\": ~, ~, ~\n", t, b_seek(b, t) == 0,
b_seek(b, t) != -1,
b_seek(b, t) != -1 && b_seek(b, t) + length(t) == length(s));
 
t = "Summer";
 
o_form("starts with, embeds, ends with \"~\": ~, ~, ~\n", t, b_seek(b, t) == 0,
b_seek(b, t) != -1,
b_seek(b, t) != -1 && b_seek(b, t) + length(t) == length(s));

Output:

starts with, embeds, ends with "Bang": 1, 1, 0
starts with, embeds, ends with "ok": 0, 1, 1
starts with, embeds, ends with "Summer": 0, 0, 0

[edit] ALGOL 68

Translation of: python
Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
# define some appropriate OPerators #
PRIO STARTSWITH = 5, ENDSWITH = 5;
OP STARTSWITH = (STRING str, prefix)BOOL: # assuming LWB = 1 #
IF UPB str < UPB prefix THEN FALSE ELSE str[:UPB prefix]=prefix FI;
OP ENDSWITH = (STRING str, suffix)BOOL: # assuming LWB = 1 #
IF UPB str < UPB suffix THEN FALSE ELSE str[UPB str-UPB suffix+1:]=suffix FI;
 
INT loc, loc2;
 
print((
"abcd" STARTSWITH "ab", # returns TRUE #
"abcd" ENDSWITH "zn", # returns FALSE #
string in string("bb",loc,"abab"), # returns FALSE #
string in string("ab",loc,"abab"), # returns TRUE #
(string in string("bb",loc,"abab")|loc|-1), # returns -1 #
(string in string("ab",loc,"abab")|loc|-1), # returns +1 #
(string in string("ab",loc2,"abab"[loc+1:])|loc+loc2|-1) # returns +3 #
))

Output:

TFFT         -1         +1         +3

[edit] AutoHotkey

 
String1 = abcd
String2 = abab
 
If (SubStr(String1,1,StrLen(String2)) = String2)
MsgBox, "%String1%" starts with "%String2%".
IfInString, String1, %String2%
{
Position := InStr(String1,String2)
StringReplace, String1, String1, %String2%, %String2%, UseErrorLevel
MsgBox, "%String1%" contains "%String2%" at position %Position%`, and appears %ErrorLevel% times.
}
StringRight, TempVar, String1, StrLen(String2)
If TempVar = %String2%
MsgBox, "%String1%" ends with "%String2%".
 

[edit] AutoIt

$string1 = "arduinoardblobard"
$string2 = "ard"
 
; == Determining if the first string starts with second string
If StringLeft($string1, StringLen($string2)) = $string2 Then
ConsoleWrite("1st string starts with 2nd string." & @CRLF)
Else
ConsoleWrite("1st string does'nt starts with 2nd string." & @CRLF)
EndIf
 
; == Determining if the first string contains the second string at any location
; == Print the location of the match for part 2
; == Handle multiple occurrences of a string for part 2
$start = 1
$count = 0
$pos = StringInStr($string1, $string2)
While $pos
$count += 1
ConsoleWrite("1st string contains 2nd string at position: " & $pos & @CRLF)
$pos = StringInStr($string1, $string2, 0, 1, $start + $pos + StringLen($string2))
WEnd
If $count = 0 Then ConsoleWrite("1st string does'nt contain 2nd string." & @CRLF)
 
; == Determining if the first string ends with the second string
If StringRight($string1, StringLen($string2)) = $string2 Then
ConsoleWrite("1st string ends with 2nd string." & @CRLF)
Else
ConsoleWrite("1st string does'nt ends with 2nd string." & @CRLF)
EndIf
 
 

[edit] AWK

#!/usr/bin/awk -f
{
if ($1 ~ "^"$2) {
print $1" begins with "$2;
} else {
print $1" does not begin with "$2;
}
 
if ($1 ~ $2) {
print $1" contains "$2;
} else {
print $1" does not contain "$2;
}
 
if ($1 ~ $2"$") {
print $1" ends with "$2;
} else {
print $1" does not end with "$2;
}
}
 


[edit] BASIC

Works with: QBasic
first$ = "qwertyuiop"
 
'Determining if the first string starts with second string
second$ = "qwerty"
IF LEFT$(first$, LEN(second$)) = second$ THEN
PRINT "'"; first$; "' starts with '"; second$; "'"
ELSE
PRINT "'"; first$; "' does not start with '"; second$; "'"
END IF
 
'Determining if the first string contains the second string at any location
'Print the location of the match for part 2
second$ = "wert"
x = INSTR(first$, second$)
IF x THEN
PRINT "'"; first$; "' contains '"; second$; "' at position "; x
ELSE
PRINT "'"; first$; "' does not contain '"; second$; "'"
END IF
 
' Determining if the first string ends with the second string
second$ = "random garbage"
IF RIGHT$(first$, LEN(second$)) = second$ THEN
PRINT "'"; first$; "' ends with '"; second$; "'"
ELSE
PRINT "'"; first$; "' does not end with '"; second$; "'"
END IF
 
 

Output:

'qwertyuiop' starts with 'qwerty'
'qwertyuiop' contains 'wert' at position  2
'qwertyuiop' does not end with 'random garbage'

[edit] Applesoft BASIC

10 A$ = "THIS, THAT, AND THE OTHER THING"
20 S$ = "TH"
30 DEF FN S(P) = MID$(A$, P, LEN(S$)) = S$
40 PRINT A$ : PRINT
 
110 S$(1) = "STARTS"
120 S$(0) = "DOES NOT START"
130 PRINT S$(FN S(1))" WITH "S$ : PRINT
 
210 R$ = "" : FOR I = 1 TO LEN(A$) - LEN(S$) : IF FN S(I) THEN R$ = R$ + STR$(I) + " "
220 NEXT I
230 IF LEN(R$) = 0 THEN PRINT "DOES NOT CONTAIN "S$
240 IF LEN(R$) THEN PRINT "CONTAINS "S$" LOCATED AT POSITION "R$
250 PRINT
 
310 E$(1) = "ENDS"
320 E$(0) = "DOES NOT END"
330 PRINT E$(FN S(LEN(A$) - LEN(S$) + 1))" WITH "S$

[edit] BBC BASIC

      first$ = "The fox jumps over the dog"
 
FOR test% = 1 TO 3
READ second$
starts% = FN_first_starts_with_second(first$, second$)
IF starts% PRINT """" first$ """ starts with """ second$ """"
ends% = FN_first_ends_with_second(first$, second$)
IF ends% PRINT """" first$ """ ends with """ second$ """"
where% = FN_first_contains_second_where(first$, second$)
IF where% PRINT """" first$ """ contains """ second$ """ at position " ; where%
howmany% = FN_first_contains_second_howmany(first$, second$)
IF howmany% PRINT """" first$ """ contains """ second$ """ " ; howmany% " time(s)"
NEXT
DATA "The", "he", "dog"
END
 
DEF FN_first_starts_with_second(A$, B$)
= B$ = LEFT$(A$, LEN(B$))
 
DEF FN_first_ends_with_second(A$, B$)
= B$ = RIGHT$(A$, LEN(B$))
 
DEF FN_first_contains_second_where(A$, B$)
= INSTR(A$, B$)
 
DEF FN_first_contains_second_howmany(A$, B$)
LOCAL I%, N% : I% = 0
REPEAT
I% = INSTR(A$, B$, I%+1)
IF I% THEN N% += 1
UNTIL I% = 0
= N%
 

Output:

"The fox jumps over the dog" starts with "The"
"The fox jumps over the dog" contains "The" at position 1
"The fox jumps over the dog" contains "The" 1 time(s)
"The fox jumps over the dog" contains "he" at position 2
"The fox jumps over the dog" contains "he" 2 time(s)
"The fox jumps over the dog" ends with "dog"
"The fox jumps over the dog" contains "dog" at position 24
"The fox jumps over the dog" contains "dog" 1 time(s)

[edit] Bracmat

Bracmat does pattern matching in expressions subject:pattern and in strings @(subject:pattern). The (sub)pattern ? is a wild card.

( (sentence="I want a number such that that number will be even.")
& out$(@(!sentence:I ?) & "sentence starts with 'I'" | "sentence does not start with 'I'")
& out$(@(!sentence:? such ?) & "sentence contains 'such'" | "sentence does not contain 'such'")
& out$(@(!sentence:? "even.") & "sentence ends with 'even.'" | "sentence does not end with 'even.'")
& 0:?N
& ( @(!sentence:? be (? & !N+1:?N & ~))
| out$str$("sentence contains " !N " occurrences of 'be'")
)
)

In the last line, Bracmat is forced by the always failing node ~ to backtrack until all occurrences of 'be' are found. Thereafter the pattern match expression fails. The interesting part is the side effect: while backtracking, the accumulator N keeps track of how many are found.

Output:

sentence starts with 'I'
sentence contains 'such'
sentence ends with 'even.'
sentence contains 3 occurrences of 'be'

[edit] C

Case sensitive matching:

#include <string.h>
#include <stdio.h>
 
int startsWith(const char* container, const char* target)
{
size_t clen = strlen(container), tlen = strlen(target);
if (clen < tlen)
return 0;
return strncmp(container, target, tlen) == 0;
}
 
int endsWith(const char* container, const char* target)
{
size_t clen = strlen(container), tlen = strlen(target);
if (clen < tlen)
return 0;
return strncmp(container + clen - tlen, target, tlen) == 0;
}
 
int doesContain(const char* container, const char* target)
{
return strstr(container, target) != 0;
}
 
int main(void)
{
printf("Starts with Test ( Hello,Hell ) : %d\n", startsWith("Hello","Hell"));
printf("Ends with Test ( Code,ode ) : %d\n", endsWith("Code","ode"));
printf("Contains Test ( Google,msn ) : %d\n", doesContain("Google","msn"));
 
return 0;
}

Output :

Starts with Test ( Hello,Hell ) : 1
Ends with Test ( Code,ode ) : 1
Contains Test ( Google,msn ) : 0

Code without using string library to demonstrate how char strings are just pointers:

#include <stdio.h>
 
/* returns 0 if no match, 1 if matched, -1 if matched and at end */
int s_cmp(const char *a, const char *b)
{
char c1 = 0, c2 = 0;
while (c1 == c2) {
c1 = *(a++);
if ('\0' == (c2 = *(b++)))
return c1 == '\0' ? -1 : 1;
}
return 0;
}
 
/* returns times matched */
int s_match(const char *a, const char *b)
{
int i = 0, count = 0;
printf("matching `%s' with `%s':\n", a, b);
 
while (a[i] != '\0') {
switch (s_cmp(a + i, b)) {
case -1:
printf("matched: pos %d (at end)\n\n", i);
return ++count;
case 1:
printf("matched: pos %d\n", i);
++count;
break;
}
i++;
}
printf("end match\n\n");
return count;
}
 
int main()
{
s_match("A Short String", "ort S");
s_match("aBaBaBaBa", "aBa");
s_match("something random", "Rand");
 
return 0;
}
Output:
matching `A Short String' with `ort S':
matched: pos 4
end match

matching `aBaBaBaBa' with `aBa':
matched: pos 0
matched: pos 2
matched: pos 4
matched: pos 6 (at end)

matching `something random' with `Rand':
end match

[edit] C++

#include <string>
using namespace std;
 
string s1="abcd";
string s2="abab";
string s3="ab";
//Beginning
s1.compare(0,s3.size(),s3)==0;
//End
s1.compare(s1.size()-s3.size(),s3.size(),s3)==0;
//Anywhere
s1.find(s2)//returns string::npos
int loc=s2.find(s3)//returns 0
loc=s2.find(s3,loc+1)//returns 2

[edit] C#

Works with: Mono version 2.6
 
class Program
{
public static void Main (string[] args)
{
var value = "abcd".StartsWith("ab");
value = "abcd".EndsWith("zn"); //returns false
value = "abab".Contains("bb"); //returns false
value = "abab".Contains("ab"); //returns true
int loc = "abab".IndexOf("bb"); //returns -1
loc = "abab".IndexOf("ab"); //returns 0
loc = "abab".IndexOf("ab",loc+1); //returns 2
}
}
 

[edit] Clojure

Translation of: Java
(def evals '((. "abcd" startsWith "ab")
(. "abcd" endsWith "zn")
(. "abab" contains "bb")
(. "abab" contains "ab")
(. "abab" indexOf "bb")
(let [loc (. "abab" indexOf "ab")]
(. "abab" indexOf "ab" (dec loc)))))
 
user> (for [i evals] [i (eval i)])
([(. "abcd" startsWith "ab") true] [(. "abcd" endsWith "zn") false] [(. "abab" contains "bb") false] [(. "abab" contains "ab") true] [(. "abab" indexOf "bb") -1] [(let [loc (. "abab" indexOf "ab")] (. "abab" indexOf "ab" (dec loc))) 0])

[edit] CoffeeScript

This example uses string slices, but a better implementation might use indexOf for slightly better performance.

 
matchAt = (s, frag, i) ->
s[i...i+frag.length] == frag
 
startsWith = (s, frag) ->
matchAt s, frag, 0
 
endsWith = (s, frag) ->
matchAt s, frag, s.length - frag.length
 
matchLocations = (s, frag) ->
(i for i in [0..s.length - frag.length] when matchAt s, frag, i)
 
console.log startsWith "tacoloco", "taco" # true
console.log startsWith "taco", "tacoloco" # false
console.log startsWith "tacoloco", "talk" # false
console.log endsWith "tacoloco", "loco" # true
console.log endsWith "loco", "tacoloco" # false
console.log endsWith "tacoloco", "yoco" # false
console.log matchLocations "bababab", "bab" # [0,2,4]
console.log matchLocations "xxx", "x" # [0,1,2]
 

[edit] Common Lisp

 
(defun starts-with-p (str1 str2)
"Determine whether `str1` starts with `str2`"
(let ((p (search str2 str1)))
(and p (= 0 p))))
 
(print (starts-with-p "foobar" "foo")) ; T
(print (starts-with-p "foobar" "bar")) ; NIL
 
(defun ends-with-p (str1 str2)
"Determine whether `str1` ends with `str2`"
(let ((p (mismatch str2 str1 :from-end T)))
(or (not p) (= 0 p))))
 
(print (ends-with-p "foobar" "foo")) ; NIL
(print (ends-with-p "foobar" "bar")) ; T
 
(defun containsp (str1 str2)
"Determine whether `str1` contains `str2`.
Instead of just returning T, return a list of starting locations
for every occurence of `str2` in `str1`"

(unless (string-equal str2 "")
(loop for p = (search str2 str1) then (search str2 str1 :start2 (1+ p))
while p
collect p)))
 
(print (containsp "foobar" "oba")) ; (2)
(print (containsp "ababaBa" "ba")) ; (1 3)
(print (containsp "foobar" "x")) ; NIL
 

[edit] Component Pascal

BlackBox Component Builder

 
MODULE StringMatch;
IMPORT StdLog,Strings;
CONST
strSize = 1024;
patSize = 256;
 
TYPE
Matcher* = POINTER TO LIMITED RECORD
str: ARRAY strSize OF CHAR;
pat: ARRAY patSize OF CHAR;
pos: INTEGER
END;
 
PROCEDURE NewMatcher*(IN str: ARRAY OF CHAR): Matcher;
VAR
m: Matcher;
BEGIN
NEW(m);m.str := str$;m.pos:= 0;
RETURN m
END NewMatcher;
 
PROCEDURE (m: Matcher) Match*(IN pat: ARRAY OF CHAR): INTEGER,NEW;
VAR
pos: INTEGER;
BEGIN
m.pat := pat$;
pos := m.pos;
Strings.Find(m.str,m.pat,pos,m.pos);
RETURN m.pos
END Match;
 
PROCEDURE (m: Matcher) Next*(): INTEGER, NEW;
VAR
pos: INTEGER;
BEGIN
pos := m.pos + LEN(m.pat$);
Strings.Find(m.str,m.pat,pos,m.pos);
RETURN m.pos;
END Next;
 
(* Some Helper functions based on Strings module *)
PROCEDURE StartsWith(IN str: ARRAY OF CHAR;IN pat: ARRAY OF CHAR): BOOLEAN;
VAR
pos: INTEGER;
BEGIN
Strings.Find(str,pat,0,pos);
RETURN pos = 0
END StartsWith;
 
PROCEDURE Contains(IN str: ARRAY OF CHAR;IN pat: ARRAY OF CHAR; OUT pos: INTEGER): BOOLEAN;
BEGIN
Strings.Find(str,pat,0,pos);
RETURN pos >= 0
END Contains;
 
PROCEDURE EndsWith(IN str: ARRAY OF CHAR;IN pat: ARRAY OF CHAR): BOOLEAN;
VAR
pos: INTEGER;
BEGIN
Strings.Find(str,pat,0,pos);
RETURN pos + LEN(pat$) = LEN(str$)
END EndsWith;
 
PROCEDURE Do*;
CONST
aStr = "abcdefghijklmnopqrstuvwxyz";
VAR
pat: ARRAY 128 OF CHAR;
res: BOOLEAN;
at: INTEGER;
m: Matcher;
BEGIN
(* StartsWith *)
pat := "abc";
StdLog.String(aStr + " startsWith " + pat + " :>");StdLog.Bool(StartsWith(aStr,pat));StdLog.Ln;
pat := "cba";
StdLog.String(aStr + " startsWith " + pat + " :>");StdLog.Bool(StartsWith(aStr,pat));StdLog.Ln;
pat := "def";
StdLog.String(aStr + " startsWith " + pat + " :>");StdLog.Bool(StartsWith(aStr,pat));StdLog.Ln;
StdLog.Ln;
(* Contains *)
pat := 'def';
StdLog.String(aStr + " contains " + pat + " :>");StdLog.Bool(Contains(aStr,pat,at));
StdLog.String(" at: ");StdLog.Int(at);StdLog.Ln;
pat := 'efd';
StdLog.String(aStr + " contains " + pat + " :>");StdLog.Bool(Contains(aStr,pat,at));
StdLog.String(" at: ");StdLog.Int(at);StdLog.Ln;
pat := 'abc';
StdLog.String(aStr + " contains " + pat + " :>");StdLog.Bool(Contains(aStr,pat,at));
StdLog.String(" at: ");StdLog.Int(at);StdLog.Ln;
pat := 'xyz';
StdLog.String(aStr + " contains " + pat + " :>");StdLog.Bool(Contains(aStr,pat,at));
StdLog.String(" at: ");StdLog.Int(at);StdLog.Ln;
StdLog.Ln;
(* EndsWith *)
pat := 'xyz';
StdLog.String(aStr + " endsWith " + pat + " :>");StdLog.Bool(EndsWith(aStr,pat));StdLog.Ln;
pat := 'zyx';
StdLog.String(aStr + " endsWith " + pat + " :>");StdLog.Bool(EndsWith(aStr,pat));StdLog.Ln;
pat := 'abc';
StdLog.String(aStr + " endsWith " + pat + " :>");StdLog.Bool(EndsWith(aStr,pat));StdLog.Ln;
pat:= 'def';
StdLog.String(aStr + " endsWith " + pat + " :>");StdLog.Bool(EndsWith(aStr,pat));StdLog.Ln;
StdLog.Ln;
 
m := NewMatcher("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
StdLog.String("Matching 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' against 'abc':> ");
StdLog.Ln;
StdLog.String("Match at: ");StdLog.Int(m.Match("abc"));StdLog.Ln;
StdLog.String("Match at: ");StdLog.Int(m.Next());StdLog.Ln;
StdLog.String("Match at: ");StdLog.Int(m.Next());StdLog.Ln
END Do;
END StringMatch.
 

Execute: ^Q StringMatching.Do
Output:

abcdefghijklmnopqrstuvwxyz startsWith abc :> $TRUE
abcdefghijklmnopqrstuvwxyz startsWith cba :> $FALSE
abcdefghijklmnopqrstuvwxyz startsWith def :> $FALSE

abcdefghijklmnopqrstuvwxyz contains def :> $TRUE at:  3
abcdefghijklmnopqrstuvwxyz contains efd :> $FALSE at:  -1
abcdefghijklmnopqrstuvwxyz contains abc :> $TRUE at:  0
abcdefghijklmnopqrstuvwxyz contains xyz :> $TRUE at:  23

abcdefghijklmnopqrstuvwxyz endsWith xyz :> $TRUE
abcdefghijklmnopqrstuvwxyz endsWith zyx :> $FALSE
abcdefghijklmnopqrstuvwxyz endsWith abc :> $FALSE
abcdefghijklmnopqrstuvwxyz endsWith def :> $FALSE

Matching 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' against 'abc':> 
Match at:  0
Match at:  26
Match at:  -1

[edit] D

void main() {
import std.stdio;
import std.algorithm: startsWith, endsWith, find, countUntil;
 
"abcd".startsWith("ab").writeln; // true
"abcd".endsWith("zn").writeln; // false
"abab".find("bb").writeln; // empty array (no match)
"abcd".find("bc").writeln; // "bcd" (substring start
// at match)
"abab".countUntil("bb").writeln; // -1 (no match)
"abab".countUntil("ba").writeln; // 1 (index of 1st match)
 
// std.algorithm.startsWith also works on arrays and ranges:
[1, 2, 3].countUntil(3).writeln; // 2
[1, 2, 3].countUntil([2, 3]).writeln; // 1
}
Output:
true
false

bcd
-1
1
2
1

[edit] Delphi

program CharacterMatching;
 
{$APPTYPE CONSOLE}
 
uses StrUtils;
 
begin
WriteLn(AnsiStartsText('ab', 'abcd')); // True
WriteLn(AnsiEndsText('zn', 'abcd')); // False
WriteLn(AnsiContainsText('abcd', 'bb')); // False
Writeln(AnsiContainsText('abcd', 'ab')); // True
WriteLn(Pos('ab', 'abcd')); // 1
end.

[edit] E

def f(string1, string2) {
println(string1.startsWith(string2))
 
var index := 0
while ((index := string1.startOf(string2, index)) != -1) {
println(`at $index`)
index += 1
}
 
println(string1.endsWith(string2))
}

[edit] Elena

#define system'routines.
#define extensions.
 
// --- Program ---
 
#symbol program =
[
literalControl starting:"hello" &with:"hel" ?
[
consoleEx writeLine:"hello starts with hel".
].
 
literalControl ending:"hello" &with:"llo" ?
[
consoleEx writeLine:"hello ends with llo".
].
 
literalControl contain:"el" &in:"hello" ?
[
consoleEx writeLine:"hello contains el".
].
].

[edit] Elixir

The String module has functions that cover the base requirements.

 
s1 = "abcd"
s2 = "adab"
s3 = "ab"
 
String.starts_with?(s1, s3)
# => true
String.starts_with?(s2, s3)
# => false
 
String.ends_with?(s1, s3)
# => false
String.ends_with?(s2, s3)
# => true
 
String.contains?(s1, s3)
# => true
String.contains?(s2, s3)
# => true
 

[edit] Erlang

 
-module(character_matching).
-export([starts_with/2,ends_with/2,contains/2]).
 
%% Both starts_with and ends_with are mappings to 'lists:prefix/2' and
%% 'lists:suffix/2', respectively.
 
starts_with(S1,S2) ->
lists:prefix(S2,S1).
 
ends_with(S1,S2) ->
lists:suffix(S2,S1).
 
contains(S1,S2) ->
contains(S1,S2,1,[]).
 
%% While S1 is at least as long as S2 we check if S2 is its prefix,
%% storing the result if it is. When S1 is shorter than S2, we return
%% the result. NB: this will work on any arbitrary list in erlang
%% since it makes no distinction between strings and lists.
contains([_|T]=S1,S2,N,Acc) when length(S2) =< length(S1) ->
case starts_with(S1,S2) of
true ->
contains(T,S2,N+1,[N|Acc]);
false ->
contains(T,S2,N+1,Acc)
end;
contains(_S1,_S2,_N,Acc) ->
Acc.
 

[edit] Euphoria

sequence first, second
integer x
 
first = "qwertyuiop"
 
-- Determining if the first string starts with second string
second = "qwerty"
if match(second, first) = 1 then
printf(1, "'%s' starts with '%s'\n", {first, second})
else
printf(1, "'%s' does not start with '%s'\n", {first, second})
end if
 
-- Determining if the first string contains the second string at any location
-- Print the location of the match for part 2
second = "wert"
x = match(second, first)
if x then
printf(1, "'%s' contains '%s' at position %d\n", {first, second, x})
else
printf(1, "'%s' does not contain '%s'\n", {first, second})
end if
 
-- Determining if the first string ends with the second string
second = "uio"
if length(second)<=length(first) and match_from(second, first, length(first)-length(second)+1) then
printf(1, "'%s' ends with '%s'\n", {first, second})
else
printf(1, "'%s' does not end with '%s'\n", {first, second})
end if

Output:

'qwertyuiop' starts with 'qwerty'
'qwertyuiop' contains 'wert' at position 2
'qwertyuiop' does not end with 'uio'


[edit] F#

[<EntryPoint>]
let main args =
 
let text = "一二三四五六七八九十"
let starts = "一二"
let ends = "九十"
let contains = "五六"
let notContains = "百"
 
printfn "text = %A" text
printfn "starts with %A: %A" starts (text.StartsWith(starts))
printfn "starts with %A: %A" ends (text.StartsWith(ends))
printfn "ends with %A: %A" ends (text.EndsWith(ends))
printfn "ends with %A: %A" starts (text.EndsWith(starts))
printfn "contains %A: %A" contains (text.Contains(contains))
printfn "contains %A: %A" notContains (text.Contains(notContains))
printfn "substring %A begins at position %d (zero-based)" contains (text.IndexOf(contains))
let text2 = text + text
printfn "text = %A" text2
Seq.unfold (fun (n : int) ->
let idx = text2.IndexOf(contains, n)
if idx < 0 then None else Some (idx, idx+1)) 0
|> Seq.iter (printfn "substring %A begins at position %d (zero-based)" contains)
0

Output

text = "一二三四五六七八九十"
starts with "一二": true
starts with "九十": false
ends with "九十": true
ends with "一二": false
contains "五六": true
contains "百": false
substring "五六" begins at position 4 (zero-based)
text = "一二三四五六七八九十一二三四五六七八九十"
substring "五六" begins at position 4 (zero-based)
substring "五六" begins at position 14 (zero-based)

[edit] Fantom

Fantom provides several self-explanatory string-matching methods:

  • startsWith
  • endsWith
  • contains
  • index (takes an optional index, for the start position)
  • indexIgnoreCase (like above, ignoring case for ASCII characters)
  • indexr (start search from end of string, with an optional index)
  • indexrIgnoreCase (like above, ignoring case for ASCII characters)
 
class Main
{
public static Void main ()
{
string := "Fantom Language"
echo ("String is: " + string)
echo ("does string start with 'Fantom'? " + string.startsWith("Fantom"))
echo ("does string start with 'Language'? " + string.startsWith("Language"))
echo ("does string contain 'age'? " + string.contains("age"))
echo ("does string contain 'page'? " + string.contains("page"))
echo ("does string end with 'Fantom'? " + string.endsWith("Fantom"))
echo ("does string end with 'Language'? " + string.endsWith("Language"))
 
echo ("Location of 'age' is: " + string.index("age"))
posn := string.index ("an")
echo ("First location of 'an' is: " + posn)
posn = string.index ("an", posn+1)
echo ("Second location of 'an' is: " + posn)
posn = string.index ("an", posn+1)
if (posn == null) echo ("No third location of 'an'")
}
}
 

Output:

String is: Fantom Language
does string start with 'Fantom'? true
does string start with 'Language'? false
does string contain 'age'? true
does string contain 'page'? false
does string end with 'Fantom'? false
does string end with 'Language'? true
Location of 'age' is: 12
First location of 'an' is: 1
Second location of 'an' is: 8
No third location of 'an'

[edit] FBSL

#APPTYPE CONSOLE
 
DIM s = "roko, mat jane do"
 
IF LEFT(s, 4) = "roko" THEN PRINT STRENC(s), " starts with ", STRENC("roko")
IF INSTR(s, "mat") THEN PRINT STRENC(s), " contains ", STRENC("mat"), " at ", INSTR
IF RIGHT(s, 2) = "do" THEN PRINT STRENC(s), " ends with ", STRENC("do")
PRINT STRENC(s), " contains ", STRENC("o"), " at the following locations:", InstrEx(s, "o")
 
PAUSE
 
SUB InstrEx(mane, match)
INSTR = 0
WHILE INSTR(mane, match, INSTR + 1): PRINT " ", INSTR;: WEND
END SUB
 

Output

"roko, mat jane do" starts with "roko"
"roko, mat jane do" contains "mat" at 7
"roko, mat jane do" ends with "do"
"roko, mat jane do" contains "o" at the following locations: 2 4 17

Press any key to continue...

[edit] Forth

: starts-with ( a l a2 l2 -- ? )
tuck 2>r min 2r> compare 0= ;
: ends-with ( a l a2 l2 -- ? )
tuck 2>r negate over + 0 max /string 2r> compare 0= ;
\ use SEARCH ( a l a2 l2 -- a3 l3 ? ) for contains

[edit] GML

Translation of: BASIC
#define charMatch
{
first = "qwertyuiop";
 
// Determining if the first string starts with second string
second = "qwerty";
if (string_pos(second, first) > 0) {
show_message("'" + first + "' starts with '" + second + "'");
} else {
show_message("'" + first + "' does not start with '" + second + "'");
}
 
second = "wert"
// Determining if the first string contains the second string at any location
// Print the location of the match for part 2
if (string_pos(second, first) > 0) {
show_message("'" + first + "' contains '" + second + "' at position " + string(x));
} else {
show_message("'" + first + "' does not contain '" + second + "'");
}
// Handle multiple occurrences of a string for part 2.
x = string_count(second, first);
show_message("'" + first + "' contains " + string(x) + " instances of '" + second + "'");
 
// Determining if the first string ends with the second string
second = "random garbage"
temp = string_copy(first,
(string_length(first) - string_length(second)) + 1,
string_length(second));
if (temp == second) {
show_message("'" + first + "' ends with '" + second + "'");
} else {
show_message("'" + first + "' does not end with '" + second + "'");
}
}

Output (in message boxes, 1 per line):

'qwertyuiop' starts with 'qwerty'
'qwertyuiop' contains 'wert' at position 0
'qwertyuiop' contains 1 instances of 'wert'
'qwertyuiop' does not end with 'random garbage'

[edit] Go

package main
 
import (
"fmt"
"strings"
)
 
func match(first, second string) {
fmt.Printf("1. %s starts with %s: %t\n",
first, second, strings.HasPrefix(first, second))
i := strings.Index(first, second)
fmt.Printf("2. %s contains %s: %t,\n", first, second, i >= 0)
if i >= 0 {
fmt.Printf("2.1. at location %d,\n", i)
for start := i+1;; {
if i = strings.Index(first[start:], second); i < 0 {
break
}
fmt.Printf("2.2. at location %d,\n", start+i)
start += i+1
}
fmt.Println("2.2. and that's all")
}
fmt.Printf("3. %s ends with %s: %t\n",
first, second, strings.HasSuffix(first, second))
}
 
func main() {
match("abracadabra", "abr")
}

Output:

1. abracadabra starts with abr: true
2. abracadabra contains abr: true,
2.1. at location 0,
2.2. at location 7,
2.2. and that's all
3. abracadabra ends with abr: false

[edit] Groovy

Examples:

assert "abcd".startsWith("ab")
assert ! "abcd".startsWith("zn")
assert "abcd".endsWith("cd")
assert ! "abcd".endsWith("zn")
assert "abab".contains("ba")
assert ! "abab".contains("bb")
 
 
assert "abab".indexOf("bb") == -1 // not found flag
assert "abab".indexOf("ab") == 0
 
def indicesOf = { string, substring ->
if (!string) { return [] }
def indices = [-1]
while (true) {
indices << string.indexOf(substring, indices.last()+1)
if (indices.last() == -1) break
}
indices[1..<(indices.size()-1)]
}
assert indicesOf("abab", "ab") == [0, 2]
assert indicesOf("abab", "ba") == [1]
assert indicesOf("abab", "xy") == []

All assertions pass, so there is no output.

[edit] Haskell

> import Data.List
> "abc" `isPrefixOf` "abcdefg"
True
> "efg" `isSuffixOf` "abcdefg"
True
> "bcd" `isInfixOf` "abcdefg"
True
> "abc" `isInfixOf` "abcdefg" -- Prefixes and suffixes are also infixes
True
> let infixes a b = findIndices (isPrefixOf a) $ tails b
> infixes "ab" "abcdefabqqab"
[0,6,10]

[edit] Icon and Unicon

procedure main()
 
write("Matching s2 :=",image(s2 := "ab")," within s1:= ",image(s1 := "abcdabab"))
 
write("Test #1 beginning ",if match(s2,s1) then "matches " else "failed")
writes("Test #2 all matches at positions [")
every writes(" ",find(s2,s1)|"]\n")
write("Test #3 ending ", if s1[0-:*s2] == s2 then "matches" else "fails")
 
end
Sample output:
Matching s2 :="ab" within s1:= "abcdabab"
Test #1 beginning matches
Test #2 all matches at positions [ 1 5 7 ]
Test #3 ending matches

[edit] J

startswith=: ] -: ({.~ #)
contains=: +./@:E.~
endswith=: ] -: ({.~ -@#)

Example use:

   'abcd' startswith 'ab'
1
'abcd' startswith 'cd'
0
'abcd' endswith 'ab'
0
'abcd' endswith 'cd'
1
'abcd' contains 'bb'
0
'abcd' contains 'ab'
1
'abcd' contains 'bc'
1
'abab' contains 'ab'
1
'abab' I.@E.~ 'ab' NB. find starting indicies
0 2

Note that these verbs contain no constraints restricting them to sequences of characters and so also apply to arrays of type other than character:

   0 1 2 3 startswith 0 1               NB. integer
1
4.2 5.1 1.3 9 3 contains 1.3 4.2 NB. floating point
0
4.2 5.1 1.3 4.2 9 3 contains 1.3 4.2
1

[edit] Java

"abcd".startsWith("ab") //returns true
"abcd".endsWith("zn") //returns false
"abab".contains("bb") //returns false
"abab".contains("ab") //returns true
int loc = "abab".indexOf("bb") //returns -1
loc = "abab".indexOf("ab") //returns 0
loc = "abab".indexOf("ab",loc+1) //returns 2

[edit] JavaScript

var stringA = "tacoloco"
, stringB = "co"
, q1, q2, q2multi, m
, q2matches = []
 
// stringA starts with stringB
q1 = stringA.substring(0, stringB.length) == stringB
 
// stringA contains stringB
q2 = stringA.indexOf(stringB)
 
// multiple matches
q2multi = new RegExp(stringB,'g')
 
while(m = q2multi.exec(stringA)){
q2matches.push(m.index)
}
 
// stringA ends with stringB
q3 = stringA.substr(-stringB.length) == stringB
 
console.log("1: Does '"+stringA+"' start with '"+stringB+"'? " + ( q1 ? "Yes." : "No."))
console.log("2: Is '"+stringB+"' contained in '"+stringA+"'? " + (~q2 ? "Yes, at index "+q2+"." : "No."))
if (~q2 && q2matches.length > 1){
console.log(" In fact, it happens "+q2matches.length+" times within '"+stringA+"', at index"+(q2matches.length > 1 ? "es" : "")+" "+q2matches.join(', ')+".")
}
console.log("3: Does '"+stringA+"' end with '"+stringB+"'? " + ( q3 ? "Yes." : "No."))

Output:

1: Does 'tacoloco' start with 'co'? No.
2: Is 'co' contained in 'tacoloco'? Yes, at index 2.
   In fact, it happens 2 times within 'tacoloco', at indexes 2, 6.
3: Does 'tacoloco' end with 'co'? Yes.

[edit] Lasso

local(
a = 'a quick brown peanut jumped over a quick brown fox',
b = 'a quick brown'
)
 
//Determining if the first string starts with second string
#a->beginswith(#b) // true
 
//Determining if the first string contains the second string at any location
#a >> #b // true
#a->contains(#b) // true
 
//Determining if the first string ends with the second string
#a->endswith(#b) // false

[edit] Julia

begins_with("abcd","ab") #returns true
search("abcd","ab") #returns 1:2, indices range where string was found
ends_with("abcd","zn") #returns false
ismatch(r"ab","abcd") #returns true where 1st arg is regex string
julia>for r in each_match(r"ab","abab")
println(r.offset)
end
1
3

[edit] K

startswith: {:[0<#p:_ss[x;y];~*p;0]}
endswith: {0=(-#y)+(#x)-*_ss[x;y]}
contains: {0<#_ss[x;y]}

Example:

  startswith["abcd";"ab"]
1
startswith["abcd";"bc"]
0
endswith["abcd";"cd"]
1
endswith["abcd";"bc"]
0
contains["abcdef";"cde"]
1
contains["abcdef";"bdef"]
0
_ss["abcdabceabc";"abc"] / location of matches
0 4 8

[edit] LabVIEW

These images solve the task's requirements in order.
This image is a VI Snippet, an executable image of LabVIEW code. The LabVIEW version is shown on the top-right hand corner. You can download it, then drag-and-drop it onto the LabVIEW block diagram from a file browser, and it will appear as runnable, editable code.
LabVIEW Character matching 1.png
LabVIEW Character matching 2.png
LabVIEW Character matching 3.png

[edit] Lang5

: 2array  2 compress ; : bi*  '_ set dip _ execute ;  : bi@  dup bi* ;
: comb "" split ;  : concat "" join ;  : dip swap '_ set execute _ ;
: first 0 extract swap drop ; : flip comb reverse concat ;
 
: contains
swap 'comb bi@ length do # create a matrix.
1 - "dup 1 1 compress rotate" dip dup 0 == if break then
loop drop length compress swap drop
"length 1 -" bi@ rot 0 0 "'2array dip" '2array bi* swap 2array slice reverse
 : concat.(*) concat ;
'concat "'concat. apply" bi* eq 1 1 compress index collapse
length if expand drop else drop 0 then ; # r: position.
: end-with 'flip bi@ start-with ;
: start-with 'comb bi@ length rot swap iota subscript 'concat bi@ eq ;
 
"rosettacode" "rosetta" start-with . # 1
"rosettacode" "taco" contains . # 5
"rosettacode" "ocat" contains . # 0
"rosettacode" "edoc" end-with . # 0
"rosettacode" "code" contains . # 7

[edit] Liberty BASIC

'1---Determining if the first string starts with second string
st1$="first string"
st2$="first"
if left$(st1$,len(st2$))=st2$ then
print "First string starts with second string."
end if
 
'2---Determining if the first string contains the second string at any location
'2.1---Print the location of the match for part 2
st1$="Mississippi"
st2$="i"
if instr(st1$,st2$) then
print "First string contains second string."
print "Second string is at location ";instr(st1$,st2$)
end if
 
'2.2---Handle multiple occurrences of a string for part 2.
pos=instr(st1$,st2$)
while pos
count=count+1
pos=instr(st1$,st2$,pos+len(st2$))
wend
print "Number of times second string appears in first string is ";count
 
'3---Determining if the first string ends with the second string
st1$="first string"
st2$="string"
if right$(st1$,len(st2$))=st2$ then
print "First string ends with second string."
end if
 

[edit]

to starts.with? :sub :thing
if empty? :sub [output "true]
if empty? :thing [output "false]
if not equal? first :sub first :thing [output "false]
output starts.with? butfirst :sub butfirst :thing
end
 
to ends.with? :sub :thing
if empty? :sub [output "true]
if empty? :thing [output "false]
if not equal? last :sub last :thing [output "false]
output ends.with? butlast :sub butlast :thing
end
 
show starts.with? "dog "doghouse  ; true
show ends.with? "house "doghouse  ; true
show substring? "gho "doghouse  ; true (built-in)

[edit] Lua

s1 = "string"
s2 = "str"
s3 = "ing"
s4 = "xyz"
 
print( "s1 starts with s2: ", string.find( s1, s2 ) == 1 )
print( "s1 starts with s3: ", string.find( s1, s3 ) == 1, "\n" )
 
print( "s1 contains s3: ", string.find( s1, s3 ) ~= nil )
print( "s1 contains s3: ", string.find( s1, s4 ) ~= nil, "\n" )
 
print( "s1 ends with s2: ", select( 2, string.find( s1, s2 ) ) == string.len( s1 ) )
print( "s1 ends with s3: ", select( 2, string.find( s1, s3 ) ) == string.len( s1 ) )

[edit] Maple

These facilities are all to be found in the StringTools package in Maple.

 
> with( StringTools ): # bind package exports at the top-level
> s := "dzrIemaWWIMidXYZwGiqkOOn":
> s[1..4]; # pick a prefix
"dzrI"
 
> IsPrefix( s[ 1 .. 4 ], s ); # check it
true
 
> s[ -4 .. -1 ]; # pick a suffix
"kOOn"
 
> IsSuffix( s[ -4 .. -1 ], s ); # check it
true
 
> p := Search( "XYZ", s ); # find a substring
p := 14
 
> s[ p .. p + 2 ]; # check
"XYZ"
 
> SearchAll( [ "WWI", "XYZ" ], s ); # search for multiple patterns
[8, 1], [14, 2]
 
> to 3 do s := cat( s, s ) end: length( s ); # build a longer string by repeated doubling
192
 
> p := SearchAll( "XYZ", s ); # find all occurrences
p := 14, 38, 62, 86, 110, 134, 158, 182
 
> {seq}( s[ i .. i + 2 ], i = p ); # check them
{"XYZ"}
 

The StringTools package also contains facilities for regular expression matching, but for fixed string patterns, the Search and SearchAll tools are much faster.

[edit] Mathematica

StartWith[x_, y_] := MemberQ[Flatten[StringPosition[x, y]], 1]
EndWith[x_, y_] := MemberQ[Flatten[StringPosition[x, y]], StringLength[x]]
StartWith["XYZaaabXYZaaaaXYZXYZ", "XYZ"]
EndWith["XYZaaabXYZaaaaXYZXYZ", "XYZ"]
StringPosition["XYZaaabXYZaaaaXYZXYZ", "XYZ"]
Output
True
True
{{1,3},{8,10},{15,17},{18,20}}


[edit] MATLAB / Octave

 
% 1. Determining if the first string starts with second string
strcmp(str1,str2,length(str2))
% 2. Determining if the first string contains the second string at any location
~isempty(strfind(s1,s2))
% 3. Determining if the first string ends with the second string
( (length(str1)>=length(str2)) && strcmp(str1(end+[1-length(str2):0]),str2) )
 
% 1. Print the location of the match for part 2
disp(strfind(s1,s2))
% 2. Handle multiple occurrences of a string for part 2.
ix = strfind(s1,s2); % ix is a vector containing the starting positions of s2 within s1
 


[edit] NetRexx

/* NetRexx */
options replace format comments java crossref savelog symbols
 
lipsum = ''
x_ = 0
x_ = x_ + 1; lipsum[0] = x_; lipsum[x_] = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
x_ = x_ + 1; lipsum[0] = x_; lipsum[x_] = lipsum[1].reverse
 
srch = ''
srch[1] = 'Lorem ipsum dolor sit amet'
srch[2] = 'consectetur adipisicing elit'
srch[3] = 'dolore magna aliqua.'
 
loop j_ = 1 to lipsum[0]
x1 = lipsum[j_].pos(srch[1])
x2 = lipsum[j_].pos(srch[2])
x3 = lipsum[j_].lastpos(srch[3])
 
report(x1 = 1, lipsum[j_], srch[1], 'Test string starts with search string:', 'Test string does not start with search string:')
report(x2 > 0, lipsum[j_], srch[2], 'Search string located in test string at position:' x2, 'Search string not found within test string:')
report(x3 \= srch[3].length, lipsum[j_], srch[3], 'Test string ends with search string:', 'Test string does not start with search string:')
end j_
 
many = ''
x_ = 0
x_ = x_ + 1; many[0] = x_; many[x_] = 'How many times does "many times" occur in this string?'
x_ = x_ + 1; many[0] = x_; many[x_] = 'How often does "many times" occur in this string?'
x_ = x_ + 1; many[0] = x_; many[x_] = 'How often does it occur in this string?'
srch[4] = 'many times'
 
loop j_ = 1 to many[0]
o_ = 0
k_ = 0
loop label dups until o_ = 0
o_ = many[j_].pos(srch[4], o_ + 1)
if o_ \= 0 then k_ = k_ + 1
end dups
report(k_ > 0, many[j_], srch[4], 'Number of times search string occurs:' k_, 'Search string not found')
end j_
 
method report(state = boolean, ts, ss, testSuccess, testFailure) public static
if state then say testSuccess
else say testFailure
say ' Test string:' ts
say ' Search string:' ss
say
 
return
 

[edit] Nimrod

import strutils
 
var s: string = "The quick brown fox"
if startsWith(s, "The quick"):
echo("Starts with: The quick")
if endsWith(s, "brown Fox"):
echo("Ends with: brown fox")
var pos = find(s, " brown ") # -1 if not found
if contains(s, " brown "): # showing the contains() proc, but could use if pos!=-1:
echo('"' & " brown " & '"' & " is located at position: " & $pos)
Output:
Starts with: The quick
Ends with: brown fox
" brown " is located at position: 9

[edit] Objective-C

[@"abcd" hasPrefix:@"ab"] //returns true
[@"abcd" hasSuffix:@"zn"] //returns false
int loc = [@"abab" rangeOfString:@"bb"].location //returns -1
loc = [@"abab" rangeOfString:@"ab"].location //returns 0
loc = [@"abab" rangeOfString:@"ab" options:0 range:NSMakeRange(loc+1, [@"abab" length]-(loc+1))].location //returns 2

[edit] Objeck

 
bundle Default {
class Matching {
function : Main(args : System.String[]) ~ Nil {
"abcd"->StartsWith("ab")->PrintLine(); # returns true
"abcd"->EndsWith("zn")->PrintLine(); # returns false
("abab"->Find("bb") <> -1)->PrintLine(); # returns false
("abab"->Find("ab") <> -1)->PrintLine(); # returns true
loc := "abab"->Find("bb"); # returns -1
loc := "abab"->Find("ab"); # returns 0
loc := "abab"->Find("ab", loc + 1); # returns 2
}
}
}
 

[edit] OCaml

let match1 s1 s2 =
let len1 = String.length s1
and len2 = String.length s2 in
if len1 < len2 then false else
let sub = String.sub s1 0 len2 in
(sub = s2)

testing in the top-level:

# match1 "Hello" "Hello World!" ;;
- : bool = false
# match1 "Hello World!" "Hello" ;;
- : bool = true
let match2 s1 s2 =
let len1 = String.length s1
and len2 = String.length s2 in
if len1 < len2 then false else
let rec aux i =
if i < 0 then false else
let sub = String.sub s1 i len2 in
if (sub = s2) then true else aux (pred i)
in
aux (len1 - len2)
# match2 "It's raining, Hello World!" "umbrella" ;;
- : bool = false
# match2 "It's raining, Hello World!" "Hello" ;;
- : bool = true
let match3 s1 s2 =
let len1 = String.length s1
and len2 = String.length s2 in
if len1 < len2 then false else
let sub = String.sub s1 (len1 - len2) len2 in
(sub = s2)
# match3 "Hello World" "Hello" ;;
- : bool = false
# match3 "Hello World" "World" ;;
- : bool = true
let match2_loc s1 s2 =
let len1 = String.length s1
and len2 = String.length s2 in
if len1 < len2 then (false, -1) else
let rec aux i =
if i < 0 then (false, -1) else
let sub = String.sub s1 i len2 in
if (sub = s2) then (true, i) else aux (pred i)
in
aux (len1 - len2)
# match2_loc "The sun's shining, Hello World!" "raining" ;;
- : bool * int = (false, -1)
# match2_loc "The sun's shining, Hello World!" "shining" ;;
- : bool * int = (true, 10)
let match2_num s1 s2 =
let len1 = String.length s1
and len2 = String.length s2 in
if len1 < len2 then (false, 0) else
let rec aux i n =
if i < 0 then (n <> 0, n) else
let sub = String.sub s1 i len2 in
if (sub = s2)
then aux (pred i) (succ n)
else aux (pred i) (n)
in
aux (len1 - len2) 0
# match2_num "This cloud looks like a camel, \
    that other cloud looks like a llama" "stone" ;;
- : bool * int = (false, 0)
# match2_num "This cloud looks like a camel, \
    that other cloud looks like a llama" "cloud" ;;
- : bool * int = (true, 2)

[edit] OxygenBasic

 
string s="sdfkjhgsdfkdfgkbopefioqwurti487sdfkrglkjfs9wrtgjglsdfkdkjcnmmb.,msfjflkjsdfk"
 
string f="sdfk"
 
string cr=chr(13)+chr(10),tab=chr(9)
 
string pr="FIND STRING LOCATIONS" cr cr
 
sys a=0, b=1, count=0, ls=len(s), lf=len(f)
 
do
a=instr b,s,f
if a=0 then exit do
count++
if a=1 then pr+="Begins with keyword" cr
pr+=count tab a cr
if a=ls-lf+1 then pr+="Ends with keyword at " a cr
b=a+1
end do
 
pr+=cr "Total matches: " count cr
 
print pr
 
'FIND STRING LOCATIONS
'
'Begins with keyword
'1 1
'2 8
'3 32
'4 51
'5 73
'Ends with keyword at 73
'
'Total matches: 5
 

[edit] PARI/GP

This meets the first but not the second of the optional requirements. Note that GP treats any nonzero value as true so the location found by contains() can be ignore if not needed.

startsWith(string, prefix)={
string=Vec(string);
prefix=Vec(prefix);
if(#prefix > #string, return(0));
for(i=1,#prefix,if(prefix[i]!=string[i], return(0)));
1
};
contains(string, inner)={
my(good);
string=Vec(string);
inner=Vec(inner);
for(i=0,#string-#inner,
good=1;
for(j=1,#inner,
if(inner[j]!=string[i+j], good=0; break)
);
if(good, return(i+1))
);
0
};
endsWith(string, suffix)={
string=Vec(string);
suffix=Vec(suffix);
if(#suffix > #string, return(0));
for(i=1,#suffix,if(prefix[i]!=string[i+#string-#suffix], return(0)));
1
};

[edit] Perl

Using regexes:

$str1 =~ /^\Q$str2\E/  # true if $str1 starts with $str2
$str1 =~ /\Q$str2\E/ # true if $str1 contains $str2
$str1 =~ /\Q$str2\E$/ # true if $str1 ends with $str2

Using index:

index($str1, $str2) == 0                               # true if $str1 starts with $str2
index($str1, $str2) != -1 # true if $str1 contains $str2
rindex($str1, $str2) == length($str1) - length($str2) # true if $str1 ends with $str2

Using substr:

substr($str1, 0, length($str2)) eq $str2  # true if $str1 starts with $str2
substr($str1, - length($str2)) eq $str2 # true if $str1 ends with $str2

Bonus task (printing all positions where $str2 appears in $str1):

print $-[0], "\n" while $str1 =~ /\Q$str2\E/g;  # using a regex
my $i = -1; print $i, "\n" while ($i = index $str1, $str2, $i + 1) != -1;  # using index

[edit] Perl 6

my @subs = (
# Regex-based:
sub R_contains ( Str $_, Str $s2 ) { ? m/ $s2 / },
sub R_starts_with ( Str $_, Str $s2 ) { ? m/ ^ $s2 / },
sub R_ends_with ( Str $_, Str $s2 ) { ? m/ $s2 $ / },
 
# Index-based:
sub I_contains ( Str $_, Str $s2 ) { .index( $s2)\ .defined },
sub I_starts_with ( Str $_, Str $s2 ) { my $m = .index( $s2); $m.defined and $m == 0 },
sub I_ends_with ( Str $_, Str $s2 ) { my $m = .rindex($s2); $m.defined and $m == .chars - $s2.chars },
 
# Substr-based:
sub S_starts_with ( Str $_, Str $s2 ) { .substr(0, $s2.chars) eq $s2 },
sub S_ends_with ( Str $_, Str $s2 ) { .substr( -$s2.chars) eq $s2 },
 
# Optional tasks:
sub R_find ( Str $_, Str $s2 ) { $/.from if /$s2/ },
sub R_find_all ( Str $_, Str $s2 ) {
my @p = .match: /$s2/, :g;
@p».from if @p;
},
);
 
my $str1 = 'abcbcbcd';
my @str2s = < ab bc cd zz >;
 
say "'$str1' vs:".fmt('%15s '), @str2s.fmt('%-15s');
for [1, 4, 6], [2, 5, 7], [0, 3], [8, 9] {
say;
for @subs[.list] -> $sub {
say "{$sub.name}:".fmt('%15s '),
@str2s.map({ ~$sub.($str1, $_) }).fmt('%-15s');
}
}
Output:
 'abcbcbcd' vs: ab              bc              cd              zz             

 R_starts_with: Bool::True      Bool::False     Bool::False     Bool::False    
 I_starts_with: Bool::True      Bool::False     Bool::False     Bool::False    
 S_starts_with: Bool::True      Bool::False     Bool::False     Bool::False    

   R_ends_with: Bool::False     Bool::False     Bool::True      Bool::False    
   I_ends_with: Bool::False     Bool::False     Bool::True      Bool::False    
   S_ends_with: Bool::False     Bool::False     Bool::True      Bool::False    

    R_contains: Bool::True      Bool::True      Bool::True      Bool::False    
    I_contains: Bool::True      Bool::True      Bool::True      Bool::False    

        R_find: 0               1               6               Nil()          
    R_find_all: 0               1 3 5           6               Nil()          

[edit] PHP

<?php
/**********************************************************************************
* This program gets needle and haystack from the caller (chm.html) (see below)
* and checks for occurrences of the needle in the haystack
* 02.05.2013 Walter Pachl
* Comments or Suggestions welcome
**********************************************************************************/

$haystack = $_POST['haystack']; if ($haystack=='') {$haystack='no haystack given';}
$needle = $_POST['needle']; if ($needle=='') {$needle='no needle given';}
 
function rexxpos($h,$n) {
$pos = strpos($h,$n);
if ($pos === false) { $pos=-1; }
else { $pos=$pos+1; }
return ($pos);
}
 
$pos=rexxpos($haystack,$needle);
$tx1 = "";
if ($pos==-1){ $n=0; } // not found
else { $n=1; } // found once (so far)
// Special cases
if ($pos==1){ $tx1="needle found to be the start of the haystack"; }
if ($pos==strlen($haystack)-strlen($needle)+1)
{ $tx1="needle found at end of haystack"; }
 
if ($n>0) { // look for other occurrences
$pl=$pos; // list of positions
$p=$pos; //
$x="*************************************";
$h=$haystack;
while ($p>0) {
$h=substr($x,0,$p).substr($h,$p);
$p=rexxpos($h,$needle);
if ( $p>0 ) { $n=$n+1; $pl=$pl.",&nbsp;".$p; }
}
if ($n==1) { $txt="needle found once in haystack, position: $pl."; }
else if ($n==2) { $txt="needle found twice in haystack, position(s): $pl."; }
else { $txt="needle found $n times in haystack, position(s): $pl."; }
}
else { $txt="needle not found in haystack."; }
?>
<html>
<head>
<title>Character Matching</title>
<meta name="author" content="Walter Pachl">
<meta name="date" content="02.05.2013">
<style>
p { font: 120% courier; }
</style>
</head>
<body>
<p><strong>Haystack:&nbsp;'<?php echo "$haystack" ?>'</strong></p>
<p><strong>Needle:&nbsp;&nbsp;&nbsp;'<?php echo "$needle" ?>'</strong></p>
<p><strong><?php echo "$txt" ?></strong></p>
<!-- special message: -->
<p style="color: red";><strong><?php echo "$tx1" ?></strong></p>
</body>
</html>
<?php
<!DOCTYPE html>
<!--
/************************************************************************
* Here we prompt the user for a haystack and a needle
* We then invoke program chmx.php
* to check for occurrences of the needle in the haystack
* 02.05.2013 Walter Pachl
* Comments or Suggestions welcome
************************************************************************/

-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Character matching</title>
</head>
<body>
<form id="test" name="test" method="post" action="chmx.php">
<h1>Character matching</h1>
<p>Given two strings, demonstrate the following 3 types of matchings:
<ol style="margin-top:2; margin-bottom:2;">
<li>Determining if the first string starts with second string
<li>Determining if the first string contains the second string at any location
<li>Determining if the first string ends with the second string
</ol>
<p>Optional requirements:
<ol style="margin-top:2; margin-bottom:2;">
<li>Print the location of the match(es) for part 2
<li>Handle multiple occurrences of a string for part 2.
</ol>
<p style="margin-top:5; margin-bottom:3;">
<font face="Courier"><strong>Haystack:</strong>
<strong><input type="text" name="haystack" size="80"></strong></font></p>
<p style="margin-top:5; margin-bottom:3;">
<font face="Courier"><strong>Needle:&nbsp;&nbsp;</strong>
<strong><input type="text" name="needle" size="80"></strong></font></p>
<p>Press <input name="Submit" type="submit" class="erfolg" value="CHECK"/>
to invoke chmx.php.</p>
</form>
</body>
</html>

[edit] PicoLisp

: (pre? "ab" "abcd")
-> "abcd"
: (pre? "xy" "abcd")
-> NIL
 
: (sub? "bc" "abcd")
-> "abcd"
: (sub? "xy" "abcd")
-> NIL
 
: (tail (chop "cd") (chop "abcd"))
-> ("c" "d")
: (tail (chop "xy") (chop "abcd"))
-> NIL
 
 
(de positions (Pat Str)
(setq Pat (chop Pat))
(make
(for ((I . L) (chop Str) L (cdr L))
(and (head Pat L) (link I)) ) ) )
 
: (positions "bc" "abcdabcd")
-> (2 6)

[edit] PL/I

 
/* Let s be one string, t be the other that might exist within s. */
/* 8-1-2011 */
k = index(s, t);
if k = 0 then put skip edit (t, ' is nowhere in sight') (a);
else if k = 1 then
put skip edit (t, ' starts at the beginning of ', s) (a);
else if k+length(t)-1 = length(s) then
put skip edit (t, ' is at the end of ', s) (a);
else put skip edit (t, ' is within ', s) (a);
 
if k > 0 then put skip edit (t, ' starts at position ', k) (a);
 

Optional extra:

 
/* Handle multiple occurrences. */
n = 1;
do forever;
k = index(s, t, n);
if k = 0 then
do;
if n = 1 then put skip list (t, ' is nowhere in sight');
stop;
end;
else if k = 1 then
put skip edit ('<', t, '> starts at the beginning of ', s) (a);
else if k+length(t)-1 = length(s) then
put skip edit ('<', t, '> is at the end of ', s) (a);
else put skip edit ('<', t, '> is within ', s) (a);
n = k + length(t);
 
if k > 0 then
put skip edit ('<', t, '> starts at position ', trim(k)) (a);
else stop;
end;
 

[edit] PureBasic

Procedure StartsWith(String1$, String2$)
Protected Result
If FindString(String1$, String2$, 1) =1 ; E.g Found in possition 1
Result =CountString(String1$, String2$)
EndIf
ProcedureReturn Result
EndProcedure
 
Procedure EndsWith(String1$, String2$)
Protected Result, dl=Len(String1$)-Len(String2$)
If dl>=0 And Right(String1$, Len(String2$))=String2$
Result =CountString(String1$, String2$)
EndIf
ProcedureReturn Result
EndProcedure

And a verification

If OpenConsole()
PrintN(Str(StartsWith("Rosettacode", "Rosetta"))) ; = 1
PrintN(Str(StartsWith("Rosettacode", "code"))) ; = 0
PrintN(Str(StartsWith("eleutherodactylus cruralis", "e"))) ; = 3
PrintN(Str(EndsWith ("Rosettacode", "Rosetta"))) ; = 0
PrintN(Str(EndsWith ("Rosettacode", "code"))) ; = 1
PrintN(Str(EndsWith ("Rosettacode", "e"))) ; = 2
 
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf

An alternate and more complete solution:

Procedure startsWith(string1$, string2$)
;returns one if string1$ starts with string2$, otherwise returns zero
If FindString(string1$, string2$, 1) = 1
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
 
Procedure contains(string1$, string2$, location = 0)
;returns the location of the next occurrence of string2$ in string1$ starting from location,
;or zero if no remaining occurrences of string2$ are found in string1$
ProcedureReturn FindString(string1$, string2$, location + 1)
EndProcedure
 
Procedure endsWith(string1$, string2$)
;returns one if string1$ ends with string2$, otherwise returns zero
Protected ls = Len(string2$)
If Len(string1$) - ls >= 0 And Right(string1$, ls) = string2$
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
 
If OpenConsole()
PrintN(Str(startsWith("RosettaCode", "Rosetta"))) ; = 1, true
PrintN(Str(startsWith("RosettaCode", "Code"))) ; = 0, false
 
PrintN("")
PrintN(Str(contains("RosettaCode", "luck"))) ; = 0, no occurrences
Define location
Repeat
location = contains("eleutherodactylus cruralis", "e", location)
PrintN(Str(location)) ;display each occurrence: 1, 3, 7, & 0 (no more occurrences)
Until location = 0
 
PrintN("")
PrintN(Str(endsWith ("RosettaCode", "Rosetta"))) ; = 0, false
PrintN(Str(endsWith ("RosettaCode", "Code"))) ; = 1, true
 
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf

Sample output:

1
0

0
1
3
7
0

0
1

[edit] PowerShell

 
"spicywiener".StartsWith("spicy")
"spicywiener".Contains("icy")
"spicywiener".EndsWith("wiener")
"spicywiener".IndexOf("icy")
[regex]::Matches("spicywiener", "i").count
 

Output:

True
True
True
2
2

[edit] Python

"abcd".startswith("ab") #returns True
"abcd".endswith("zn") #returns False
"bb" in "abab" #returns False
"ab" in "abab" #returns True
loc = "abab".find("bb") #returns -1
loc = "abab".find("ab") #returns 0
loc = "abab".find("ab",loc+1) #returns 2

[edit] Racket

 
#lang racket
(require srfi/13)
(string-prefix? "ab" "abcd")
(string-suffix? "cd" "abcd")
(string-contains "abab" "bb")
(string-contains "abab" "ba")
 

Output:

#t
#t
#f
1


[edit] Retro

: startsWith? ( $1 $2 - f )
withLength &swap dip 0 swap ^strings'getSubset compare ;
 
"abcdefghijkl" "abcde" startsWith?
"abcdefghijkl" "bcd" startsWith?
 
"abcdefghijkl" "bcd" ^strings'search
"abcdefghijkl" "zmq" ^strings'search
 
: endsWith? ( $1 $2 - f )
swap withLength + over getLength - compare ;
 
"abcdefghijkl" "ijkl" endsWith?
"abcdefghijkl" "abc" endsWith?

[edit] REXX

Extra coding was added to take care of using plurals in the output messages.

/*REXX program  demonstrates  some  basic   character string   testing. */
parse arg a b /*obtain A and B from the C.L. */
say 'string A = ' a /*display string A to terminal.*/
say 'string B = ' b /* " " B " " */
say
if left(A,length(b))==b then say 'string A starts with string B'
else say "string A doesn't start with string B"
say
/*another method, however a wee bit obtuse. */
/*¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬
if compare(a,b)==length(b) then say 'string A starts with string B'
else say "string A doesn't start with string B"
¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬*/

/* [↑] above is a big comment. */
p=pos(b,a)
if p==0 then say "string A doesn't contain string B"
else say 'string A contains string B (starting in position' p")"
say
if right(A,length(b))==b then say 'string A ends with string B'
else say "string A doesn't end with string B"
say
Ps=''; p=0; do until p==0
p=pos(b, a, p+1)
if p\==0 then Ps = Ps',' p
end /*until ···*/
Ps=space(strip(Ps, 'L', ","))
times=words(Ps)
if times==0 then say "string A doesn't contain string B"
else say 'string A contains string B ',
times 'time'left('s',times>1),
"(at position"left('s', times>1) Ps')'
 
/*stick a fork in it, we're done.*/

output when the following is specified (five Marx brothers):   Chico_Harpo_Groucho_Zeppo_Gummo p

string  A  =  Chico_Harpo_Groucho_Zeppo_Gummo
string  B  =  p

string  A  doesn't start with string B

string  A  contains string  B  (starting in position 10)

string  A  doesn't end with string B

string  A  contains string  B  3 times (at positions 10, 23, 24)

output when the following is specified:   Chico_Harpo_Groucho_Zeppo_Gummo Z

string  A  =  Chico_Harpo_Groucho_Zeppo_Gummo
string  B  =  Z

string  A  doesn't start with string  B

string  A  contains string  B  (starting in position 21)

string  A  doesn't end with string  B

string  A  contains string  B  1 time (at position 21)

output when the following is specified:   Chico_Harpo_Groucho_Zeppo_Gummo Chi

string  A  =  Chico_Harpo_Groucho_Zeppo_Gummo
string  B  =  Chi

string  A  starts with string  B

string  A  contains string B  (starting in position 1)
 
string  A  doesn't end with string  B

string  A  contains string  B  1 time (at position 1)

output when the following is specified:   Chico_Harpo_Groucho_Zeppo_Gummo mmo

string  A  =  Chico_Harpo_Groucho_Zeppo_Gummo
string  B  =  mmo

string  A  doesn't start with string  B

string  A  contains string  B  (starting in position 29)

string  A  ends with string  B

string  A  contains string  B  1 time (at position 29)

[edit] Ruby

Works with: Ruby version 1.8.7
p 'abcd'.start_with?('ab') #returns true
p 'abcd'.end_with?('ab') #returns false
p 'abab'.include?('bb') #returns false
p 'abab'.include?('ab') #returns true
p 'abab'.index('bb') #returns nil
p 'abab'.index('ab') #returns 0
p 'abab'.index('ab', 1) #returns 2
p 'abab'.rindex('ab') #returns 2
 

[edit] Run BASIC

s1$ = "abc def ghi klmnop"
s2$ = "abc" ' begins with
s3$ = "ef" ' is in the string
s4$ = "nop" ' ends with
 
sn2$ = "abcx" ' not begins with
sn3$ = "efx" ' not in the string
sn4$ = "nopx" ' not ends with
 
if left$(s1$,len(s2$)) <> s2$ then a$ = "Not "
print "String:";s1$;" does ";a$;"begin with:";s2$
 
if instr(s1$,s3$) = 0 then a$ = "Not "
print "String:";s1$;" does ";a$;"contain:";s3$
 
if mid$(s1$,len(s1$) + 1 - len(s4$),len(s4$)) <> s4$ then a$ = "Not "
print "String:";s1$;" does ";a$;"end with:";s4$
 
' ----------- not -----------------------------
print
if left$(s1$,len(sn2$)) <> sn2$ then a$ = "Not "
print "String:";s1$;" does ";a$;"begin with:";sn2$
 
if instr(s1$,sn3$) = 0 then a$ = "Not "
print "String:";s1$;" does ";a$;"contain:";sn3$
 
if mid$(s1$,len(s1$) + 1 - len(sn4$),len(sn4$)) <> sn4$ then a$ = "Not "
print "String:";s1$;" does ";a$;"end with:";sn4$
Output:
String:abc def ghi klmnop does begin with:abc
String:abc def ghi klmnop does contain:ef
String:abc def ghi klmnop does end with:nop

String:abc def ghi klmnop does Not begin with:abcx
String:abc def ghi klmnop does Not contain:efx
String:abc def ghi klmnop does Not end with:nopx

[edit] Scala

"abcd".startsWith("ab") //returns true
"abcd".endsWith("zn") //returns false
"abab".contains("bb") //returns false
"abab".contains("ab") //returns true
 
var loc="abab".indexOf("bb") //returns -1
loc = "abab".indexOf("ab") //returns 0
loc = "abab".indexOf("ab", loc+1) //returns 2

[edit] Seed7

$ include "seed7_05.s7i";
 
const proc: main is func
local
var integer: position is 0;
begin
writeln(startsWith("abcd", "ab")); # write TRUE
writeln(endsWith("abcd", "zn")); # write FALSE
writeln(pos("abab", "bb") <> 0); # write FALSE
writeln(pos("abab", "ab") <> 0); # write TRUE
writeln(pos("abab", "bb")); # write 0
position := pos("abab", "ab");
writeln(position); # position is 1
position := pos("abab", "ab", succ(position));
writeln(position); # position is 3
end func;

Output:

TRUE
FALSE
FALSE
TRUE
0
1
3

[edit] Smalltalk

a startsWith: b
a includesSubCollection: b
a endsWith: b
a indexOfSubCollection: b
a indexOfSubCollection: b startingAt: pos

[edit] Standard ML

String.isPrefix "ab" "abcd"; (* returns true *)
String.isSuffix "zn" "abcd"; (* returns false *)
String.isSubstring "bb" "abab"; (* returns false *)
String.isSubstring "ab" "abab"; (* returns true *)
#2 (Substring.base (#2 (Substring.position "bb" (Substring.full "abab")))); (* returns 4 *)
val loc = #2 (Substring.base (#2 (Substring.position "ab" (Substring.full "abab")))); (* returns 0 *)
val loc' = #2 (Substring.base (#2 (Substring.position "ab" (Substring.extract ("abab", loc+1, NONE))))); (* returns 2 *)

[edit] Tcl

In this code, we are looking in various ways for the string in the variable needle in the string in the variable haystack.

set isPrefix    [string equal -length [string length $needle] $haystack $needle]
set isContained [expr {[string first $needle $haystack] >= 0}]
set isSuffix [string equal $needle [string range $haystack end-[expr {[string length $needle]-1}] end]]

Of course, in the cases where the needle is a glob-safe string (i.e., doesn't have any of the characters “*?[\” in), this can be written far more conveniently:

set isPrefix    [string match  $needle* $haystack]
set isContained [string match *$needle* $haystack]
set isSuffix [string match *$needle $haystack]

Another powerful technique is to use the regular expression engine in literal string mode:

set isContained [regexp ***=$needle $haystack]

This can be extended by getting the regexp to return the locations of the matches, enabling the other forms of match to be done:

set matchLocations [regexp -indices -all -inline ***=$needle $haystack]
# Each match location is a pair, being the index into the string where the needle started
# to match and the index where the needle finished matching
 
set isContained [expr {[llength $matchLocations] > 0}]
set isPrefix [expr {[lindex $matchLocations 0 0] == 0}]
set isSuffix [expr {[lindex $matchLocations end 1] == [string length $haystack]-1}]
set firstMatchStart [lindex $matchLocations 0 0]
puts "Found \"$needle\" in \"$haystack\" at $firstMatchStart"
foreach location $matchLocations {
puts "needle matched at index [lindex $location 0]"
}

[edit] TUSCRIPT

 
$$ MODE TUSCRIPT
ASK "string1", string1=""
ASK "string2", string2=""
 
IF (string1.sw.string2) THEN
PRINT string1," starts with ",string2
ELSE
PRINT string1," not starts with ",string2
ENDIF
SET beg=STRING (string1,string2,0,0,0,end)
IF (beg!=0) THEN
PRINT string1," contains ",string2
PRINT " starting in position ",beg
PRINT " ending in position ",end
ELSE
PRINT string1," not contains ",string2
ENDIF
 
IF (string1.ew.string2) THEN
PRINT string1," ends with ",string2
ELSE
PRINT string1," not ends with ",string2
ENDIF
 

Output:

string1 >Rosetta Code
string2 >Code
Rosetta Code not starts with Code
Rosetta Code contains        Code
  starting in position 9
  ending   in position 13
Rosetta Code ends with       Code 

[edit] TXR

[edit] TXR Lisp

@(do
(tree-case *args*
((big small)
(cond
((< (length big) (length small))
(put-line `@big is shorter than @small`))
((str= big small)
(put-line `@big and @small are equal`))
((match-str big small)
(put-line `@small is a prefix of @big`))
((match-str big small -1)
(put-line `@small is a suffix of @big`))
(t (let ((pos (search-str big small)))
(if pos
(put-line `@small occurs in @big at position @pos`)
(put-line `@small does not occur in @big`))))))
(otherwise
(put-line `usage: @(ldiff *full-args* *args*) <bigstring> <smallstring>`))))
Output:
$ txr cmatch2.txr x
usage: txr cmatch2.txr <bigstring> <smallstring>
$ txr cmatch2.txr x y z
usage: txr cmatch2.txr <bigstring> <smallstring>
$ txr cmatch2.txr catalog cat
cat is a prefix of catalog
$ txr cmatch2.txr catalog log
log is a suffix of catalog
$ txr cmatch2.txr catalog at
at occurs in catalog at position 1
$ txr cmatch2.txr catalog catalogue
catalog is shorter than catalogue
$ txr cmatch2.txr catalog catalog
catalog and catalog are equal
$ txr cmatch2.txr catalog dog
dog does not occur in catalog

[edit] Pattern Language

@line
@(cases)
@ line
@ (output)
second line is the same as first line
@ (end)
@(or)
@ (skip)@line
@ (output)
first line is a suffix of the second line
@ (end)
@(or)
@ line@(skip)
@ (output)
first line is a suffix of the second line
@ (end)
@(or)
@ prefix@line@(skip)
@ (output)
first line is embedded in the second line at position @(length prefix)
@ (end)
@(or)
@ (output)
first line is not found in the second line
@ (end)
@(end)
Output:
$ txr cmatch.txr -
123
01234
first line is embedded in the second line at position 1
$ txr cmatch.txr -
123
0123
first line is a suffix of the second line

[edit] XPL0

include c:\cxpl\codes;  \intrinsic 'code' declarations
string 0; \use zero-terminated strings
 
func StrLen(A); \Return number of characters in a string
char A;
int I;
for I:= 0 to -1>>1-1 do
if A(I) = 0 then return I;
 
func StrFind(A, B); \Search for string B in string A
\Returns index of first occurrence of string B in A, or -1 if B is not found
char A, B; \strings to be compared
int LA, LB, I, J;
[LA:= StrLen(A);
LB:= StrLen(B);
for I:= 0 to LA-LB do
[for J:= 0 to LB-1 do
if B(J) # A(J+I) then J:= LB+1;
if J = LB then return I; \found
];
return -1;
];
 
char Str; int I, J;
[Str:= "pack my box with";
\ 0123456789012345
Text(0, if StrFind(Str, "pack") = 0 then "yes" else "no"); CrLf(0); \1.
Text(0, if StrFind(Str, "ack") = 0 then "yes" else "no"); CrLf(0);
I:= StrFind(Str, "x w");
Text(0, if I >= 0 then "yes" else "no"); \2.
Text(0, ", at offset "); IntOut(0, I); CrLf(0);
I:= 0; J:= 0; \offsets of space characters
loop [I:= StrFind(Str+J, " ");
if I < 0 then quit;
IntOut(0, I+J); ChOut(0, ^ );
J:= J+I+1;
];
CrLf(0);
Text(0, if StrFind(Str, "X w") >= 0 then "yes" else "no"); CrLf(0);
Text(0, if StrFind(Str, "with") = StrLen(Str)-StrLen("with") then "yes" else "no"); CrLf(0); \3.
Text(0, if StrFind(Str, "x w" ) = StrLen(Str)-StrLen("x w" ) then "yes" else "no"); CrLf(0);
]
Output:
yes
no
yes, at offset 10
4 7 11 
no
yes
no

[edit] zkl

fcn f(text,p){if(text.find(p)==0)println("Yep") else println("Nope")}
f("foobar","foo") //--> Yep
f("foobar","bar") //--> Nope
fcn f(text,p){if(Void!=(n:=text.find(p)))println("Contained @",n) else println("Nope")}
f("foobar","ob") //--> Contained @2
f("foobar","food") //--> Nope
fcn f(text,p){if(Void!=(n:=text.rfind(p)) and n+p.len() == text.len())
println("tail gunner") else println("Nope")}
f("foobar","r"); f("foobar","ar"); //--> tail gunners
f("foobar","ob"); //--> Nope
f("foobarfoobar","bar"); //--> tail gunner
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox