• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] GetWord

This function GetWord allows you to split a string up by whitespace separated groups of characters. It starts looking for words from the starting position S.

Primary use of this function for me is parsing chat commands (ie: "-give gold 100 Zeatherann").

JASS:
// Returns the end of the word starting at S. It ignores leading whitespace. Whitespace characters are spaces, tabs, and newlines.
// To make use of the return value, use SubString(String,Index,GetWord(String,Index)).

// Notes: You'll receive the leading spaces ignored by this function.
function GetWord takes string str,integer S returns integer
    local integer Len=StringLength(str)
    local boolean Beg=false
    local boolean Spc
    local string C=""
    loop
        set C=SubString(str,S,S+1)
        set Spc=(C==" ")or(C=="\t")or(C=="\n")
        if Beg and Spc then
            return S
        elseif Spc==false then
            set Beg=true
        endif
        set S=S+1
        if S>=Len then
            return Len
        endif
    endloop
endfunction

Example Use:

JASS:
function Chat takes nothing returns nothing
    // ***** Local variables *****
    local string Txt=GetEventPlayerChatString()
    local integer Len=StringLength(Txt)
    local integer Pos=GetWord(Txt,0)
    local string Str=SubString(Txt,0,Pos)
    local integer Old
    call DisplayTextToPlayer(Player(0),0,0,"\""+Str+"\"")
    loop
        exitwhen Pos==Len
        set Old=Pos+1
        set Pos=GetWord(Txt,Pos)
        set Str=SubString(Txt,Old,Pos)
        call DisplayTextToPlayer(Player(0),0,0,"\""+Str+"\"")
    endloop
endfunction

function InitTrig_Chat takes nothing returns nothing
    set gg_trg_Chat=CreateTrigger()
    call TriggerRegisterPlayerChatEvent(gg_trg_Chat,Player(0),"",false)
    call TriggerAddCondition(gg_trg_Chat,Filter(function Chat))
endfunction

JASS:
// String.Find
//   string Str: The source string to find the position of the wanted string.
//   string Txt: The string you want to find within the source string.
//   integer S: The starting position you want to look for the string.
//
//   returns integer: Returns the position of the found text, or -1 if no string is found.
//
//   Notes: This function can and will create a ton of unique strings for the string table, which makes it eat up more RAM.
function StringFind takes string Str,string Txt,integer S returns integer
    local integer Len=StringLength(Str)
    local integer L2=StringLength(Txt)
    loop
        if SubString(Str,S,S+L2)==Txt then
            return S
        endif
        set S=S+1
        if S+L2>Len then
            return -1
        endif
    endloop
endfunction
Edit: Will craft this into a string library, well, minus the vJASS library/endlibrary words which yall can add if ya like.
 
Last edited:
Not bad. It is an interesting implementation, but I don't like the usage too much. I think it would be much better to fill up some string array and give the size, similar to this:
http://www.thehelper.net/threads/explode-string.106468/
Although, I suppose that it is a bit ugly implementation-wise without global blocks. To each his own.

Also, you should include some documentation in the script itself, IMO, so that users will be able to quickly refer to it when they need to use it.
 
Lol @ Jasshelper. It doesn't need to return anything because it returns nothing, besides if you change it to returns boolean then you should you make it return false.

Edit: Chat is just a demo trigger anyways, so if you used it then you'd remove that trigger. As for documentation, I haven't been able to come up with a suitable wording that'd make sense and remain clear. Sometimes I just don't know how to explain things, hence the [hopefully] useful demo trigger.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
A few things are required if you want your snippet be approved.

- Put your function into a library, give it an adequate name.
- Add a small description into your script about it's purpose
- List your public API, in your case one function and add at least 1 sentence, which
explains the purpose of that function.

Towards your code:
1.) You don't need local integer I, as you could also just use passed in argument S
2.) Spc == false should be not spc
3.) Bribe established JPAG to make resource follow an uniform format. This ensures readability for public code.
Locally generated variables should start with a small letter.
--> beg, len, spc, c

I think GetWord is not the best function name, because it doesn't return a word ( string )
it returns a position ( integer ). What about TriggerHappys idea to name it StringExplode or StringSplit?

EDIT: I correct myself, when saying you should put your code into a library.
I always forget about good old plain JASS. :p
 
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
rules said:
Any submitted script must be written in either plain JASS, vJass, Zinc or LUA. cJass will not be accepted until it is working 100%.

so yeah...if it is plain Jass, which this apparently is, it cant use library.

GetWord, as you noted is not good name, but neither are these two, because it doesnt explode nor split the string, it just says where the next word is, so imo the best name would GetWordPosition or NextWordPosition
 
Yea, I could probably add a bit of documentation. Thanks for spotting the unneeded local variable, I bet an earlier version used both. The usual casing for identifier names is something I don't follow. Mine's real simple; "DEFINES" and "OtherIndetifiers". As a C++ programmer this makes 0% of my code conflict with the standard library. A user of this code is expected to adjust it to fit their map's needs as best as possible. Give me a few minutes to update it.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
The philosophy of this is a bit strange, especially the execution and the unfortunate function name.

Instead if this, I can see the benefit of getting the remainder of a string via tokens.

API:

function GetWordFromString take string source, string toScan, integer whichWord returns string

And then call it like this:
JASS:
local string source = "-give % gold to %"
local string chat = GetEventPlayerChatString()
local integer goldAmount = S2I(GetWordFromString(source, chat, 1))
local string destPlayer = GetWordFromString(source, chat, 2)
 
Last edited:
Top