Convert a string to title case

Share your advanced PureBasic knowledge/code with the community.
User avatar
Demivec
Addict
Addict
Posts: 4265
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Convert a string to title case

Post by Demivec »

Seymour Clufley wrote: Tue Apr 01, 2025 7:06 am My method uses FindString, not StringField.
@Seymour Clufley: Did you even read your code? Just do a search for 'StringField' in your code or even just search for 'String'.
Randy Walker
Addict
Addict
Posts: 1008
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: Convert a string to title case

Post by Randy Walker »

Demivec wrote: Tue Apr 01, 2025 10:41 am
Seymour Clufley wrote: Tue Apr 01, 2025 7:06 am My method uses FindString, not StringField.
@Seymour Clufley: Did you even read your code? Just do a search for 'StringField' in your code or even just search for 'String'.
I know I'm not the brighest cookie in the barrel here, but I swear i see the same exact line in borh sbippets"
Word$ = StringField(String$, I, " ")
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
Seymour Clufley
Addict
Addict
Posts: 1265
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Convert a string to title case

Post by Seymour Clufley »

Demivec wrote: Tue Apr 01, 2025 10:41 am
Seymour Clufley wrote: Tue Apr 01, 2025 7:06 am My method uses FindString, not StringField.
@Seymour Clufley: Did you even read your code? Just do a search for 'StringField' in your code or even just search for 'String'.
Of course it uses that earlier on, because I didn't change that bit. I was referring specifically to my method for checking words. It uses FindString.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
Randy Walker
Addict
Addict
Posts: 1008
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: Convert a string to title case

Post by Randy Walker »

Quin wrote: Mon Mar 31, 2025 12:54 pm Very nice! Only reason I didn't do it this way is because I don't like how slow StringField is, but a linked list is probably overkill, I could probably make it a static array.
I think what he meant to say was: don't like how slow FindString is,...
That way his comment makes sense, but yeah I have to agree, a linked list is a bit of an overkill considering FindString works fine.
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
Quin
Addict
Addict
Posts: 1132
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Convert a string to title case

Post by Quin »

Randy Walker wrote: Wed Apr 02, 2025 8:02 pm I think what he meant to say was: don't like how slow FindString is,...
That way his comment makes sense, but yeah I have to agree, a linked list is a bit of an overkill considering FindString works fine.
Yup Randy, you got it, my bad, I wrote that before having my coffee and know that both StringField and FindString are slow, so I got them confused in my state of uncaffeinated groggy morning blehness :D
The fastest, I think, would be to use a static array. That way you avoid the speed of FindString() but you don't get the complexities of a linked list that you frankly don't need.
It's also likely possible to replace StringField() with some clever Mid() magic. Maybe I'll do that this weekend.
User avatar
idle
Always Here
Always Here
Posts: 5855
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Convert a string to title case

Post by idle »

a slightly modified version using a map instead of list and an in place version

Code: Select all

EnableExplicit

Macro AddExcludedWord(_Word_) 
  AddMapElement(ExcludedWords$(),_Word_)
EndMacro

Procedure CapitalizeInplace(*inString)
  Protected *String.character 
  Protected *Start, *End, exit,do,len
  Protected *char.Unicode,tchar,bnext,word$ 
  
  Static NewMap ExcludedWords$()
  If MapSize(ExcludedWords$()) = 0 
    AddExcludedWord("a")
    AddExcludedWord("an")
    AddExcludedWord("the")
    AddExcludedWord("and")
    AddExcludedWord("but")
    AddExcludedWord("or")
    AddExcludedWord("for")
    AddExcludedWord("nor")
    AddExcludedWord("on")
    AddExcludedWord("at")
    AddExcludedWord("to")
    AddExcludedWord("by")
    AddExcludedWord("of")
    AddExcludedWord("in")
    AddExcludedWord("up")
    AddExcludedWord("with")
    AddExcludedWord("as")
  EndIf 
  
  *String = *inString
  *Start = *String
  *End = *String
  
  Repeat
    If *String\c = 0
      exit = #True
      do = #True
      *End = *String
    Else
      If *String\c = ' '
        do = #True
        *End = *String
      EndIf
    EndIf
    If do
      bnext=1
      len = (*End - *Start) >> 1 
      If Len > 0
        word$ = PeekS(*Start, len)
        If Not FindMapElement(ExcludedWords$(),word$) 
          *char = *Start 
          While *char\u  
            If *Char\u = ' ' 
              bnext= 1 
              *char+2  
              Break 
            ElseIf bnext     
              bnext = 0 
              If *char\u >=97 And *char\u <= 122 
                *char\u -32 
              EndIf   
            EndIf   
            *char+2 
          Wend 
        EndIf  
        
      EndIf
      *Start = *String + SizeOf(character)
      do = #False
    EndIf
    *String + SizeOf(character)
  Until exit
  
EndProcedure

Procedure.b ListContainsString(List List$(), String$)
String$ = LCase(String$)
ForEach List$()
If LCase(List$()) = String$ : ProcedureReturn #True : EndIf
Next
ProcedureReturn #False
EndProcedure

; Converts a string to title case, respecting all the semantic rules that come along with that. For example, the at the very beginning of the string is capitalized, but anywhere else it isn't.
Procedure$ Capitalize(String$)
	Protected.i i, Count
	Protected Res$, Word$, FirstCharacter$, WordTail$
	Static NewMap ExcludedWords$()
	AddExcludedWord("a")
	AddExcludedWord("an")
	AddExcludedWord("the")
	AddExcludedWord("and")
	AddExcludedWord("but")
	AddExcludedWord("or")
	AddExcludedWord("for")
	AddExcludedWord("nor")
	AddExcludedWord("on")
	AddExcludedWord("at")
	AddExcludedWord("to")
	AddExcludedWord("by")
	AddExcludedWord("of")
	AddExcludedWord("in")
	AddExcludedWord("up")
	AddExcludedWord("with")
	AddExcludedWord("as")
	Count = CountString(String$, " ") + 1
	For i = 1 To Count
		Word$ = StringField(String$, I, " ")
		FirstCharacter$ = Left(Word$, 1)
		WordTail$ = Right(Word$, Len(Word$) - 1)
		If i = 1 Or Not FindMapElement(ExcludedWords$(), Word$) : FirstCharacter$ = UCase(FirstCharacter$) : EndIf
		Word$ = FirstCharacter$ + WordTail$
		Res$ + Word$ + " "
	Next
	Res$ = RTrim(Res$, " ")
	ProcedureReturn Res$
EndProcedure

Global input.s = "this is a test of the function to see how it works with the two functions to see if they're the same or different" 

Debug Capitalize(input) 

CapitalizeInplace(@input) 
Debug input 



Randy Walker
Addict
Addict
Posts: 1008
Joined: Sun Jul 25, 2004 4:21 pm
Location: USoA

Re: Convert a string to title case

Post by Randy Walker »

idle wrote: Wed Apr 02, 2025 10:16 pm a slightly modified version using a map instead of list and an in place version
A rose by any other name. Isn't the map just another way to do a list? Looks the same to me, keeping in mind my middle name is Duhh".
- - - - - - - - - - - - - - - -
Randy
I *never* claimed to be a programmer.
User avatar
idle
Always Here
Always Here
Posts: 5855
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Convert a string to title case

Post by idle »

Randy Walker wrote: Thu Apr 03, 2025 12:41 am
idle wrote: Wed Apr 02, 2025 10:16 pm a slightly modified version using a map instead of list and an in place version
A rose by any other name. Isn't the map just another way to do a list? Looks the same to me, keeping in mind my middle name is Duhh".
A map only takes one look up, a list needs to lookup up more than one time until it finds the value or reaches the end of the list. Also if you do it in place by address of the string you don't need to take a copy of the string on the stack which means you have to walk the string to find its length to copy it. not a problem for short strings but long strings it becomes a problem.
Post Reply