Skip to main content
November 12, 2008
Question

Uppercase script help

  • November 12, 2008
  • 7 replies
  • 634 views
Hello I am trying to capitalize the first letter of address lines in my db also the first letter after a space. Here is the code I was using for it. but there seems to be a problem with a few strings that to me I can't see the problem with. Please Look at the code below and let me know if you see the problem.

<cffunction name="FirstUpperCase">
<cfargument name="string" required="Yes" type="string">
<cfset var returnString = ' '>
<cfloop from="1" to="#ListLen(ARGUMENTS.string, ' ')#" index="i">
<cfset listItem = ListGetAt(ARGUMENTS.string, i, ' ')>
<cfset returnString = returnString & UCase(Left(listItem, 1)) & LCase(Right(listItem, (Len(listItem) - 1)))> <cfif i LT ListLen(ARGUMENTS.string, ' ')>
<cfset returnString = returnString & ' '>
</cfif>
</cfloop>
<cfreturn returnString></cffunction>
<cfoutput>#FirstUpperCase(Recordset.address)#</cfoutput>

Here is the error:
Parameter 2 of function Right which is now 0 must be a positive integer


The error occurred in C:\CFusionMX7\wwwroot\WLWK\Members\members.cfm: line 21

19 : <cfset listItem = ListGetAt(ARGUMENTS.string, i, ' ')>
20 : <!--- this does all of the conversion to count characters and only make the first one cap. --->
21 : <cfset returnString = returnString & UCase(Left(listItem, 1)) & LCase(Right(listItem, (Len(listItem) - 1)))>
22 : <!--- This basically checks if the string is now less then the original string which it always will be.--->
23 : <cfif i LT ListLen(ARGUMENTS.string, ' ')>


Here is the string it bombs on:
1301 Jonesmont Rd Apt 7

Is it because the last character is only one character long? How would I fix this?

Thanks,
Andrew
    This topic has been closed for replies.

    7 replies

    Inspiring
    November 13, 2008
    You don't need to horse around with all that looping.

    You can do it in one line with a regex or with CSS:

    {code}
    <cfset s = "this is a test sentence,it has punctuation and it's also got a
    couple of apostrophe's (sic).the function should cap-first all words,i
    hope.plural numbers like 2s and 3s seem to work,too, for some reason. it,
    however,preserves wholly CAPITALISED word(s) <- note that last s is wrong
    using the regex.">
    <cfset sMatch = "(^\b|[^\w'])(\w)">
    <cfset sReplace = "\1\u\2">

    <cfoutput>
    <table>
    <tr><td>Original</td><td>#s#<br /><br /></td></tr>
    <tr><td>Regex</td><td>#reReplace(s, sMatch, sReplace, "ALL")#<br /><br
    /></td></tr>
    <tr><td>CSS</td><td><span
    style="text-transform:capitalize">#s#</span></td></tr>
    </table>
    </cfoutput>
    {code}

    Quite often when one finds one's self manipulating strings via looping over
    them and transforming sections of it, it's possible to do it a lot more
    expediently with a regex.

    --
    Adam
    Inspiring
    November 12, 2008
    You are welcome. But for the record, the removeChars method is more elegant. It does not require a cfif/cfelse. That in combination with listAppend would simplify the code.

    BTW: You might also check cflib.org for this kind of thing. They probably have functions that do this.

    <cffunction name="FirstUpperCase">
    <cfargument name="string" required="Yes" type="string">
    <!--- make all variables local --->
    <cfset var i = "">
    <cfset var listItem = "">
    <cfset var returnString = "">
    <cfset var delim = " ">

    <cfloop from="1" to="#ListLen(ARGUMENTS.string, delim)#" index="i">
    <cfset listItem = ListGetAt(ARGUMENTS.string, i, delim)>
    <!--- convert the case of the current element --->
    <cfset listItem = UCase(Left(listItem, 1)) & removeChars(listItem, 1, 1)>
    <!--- save the results --->
    <cfset returnString = listAppend(returnString, listItem, delim)>
    </cfloop>

    <cfreturn returnString>
    </cffunction>

    November 12, 2008
    Thanks for explaining cfSearching... that did it.

    <cfif len(listItem) gt 1>
    do something
    <cfelse>
    do something else
    </cfif>
    Inspiring
    November 12, 2008
    > How do I get to the last character of a string after the space
    > and determine if its length is 1 or not?

    Just use a cfif/cfelse to check the length of the current list item. Then do one thing if the length is > 1 and another if it is <= 1.

    <cfif len(listItem) gt 1>
    do something
    <cfelse>
    do something else
    </cfif>

    However, Dan's suggestion is more elegant. RemoveChars works as long as #listItem# contains one or more characters. If #listItem# is a single character it just returns an empty string. Otherwise, it returns the characters you specified.
    http://livedocs.adobe.com/coldfusion/8/functions_m-r_30.html

    <cfset listItem = "a">
    <cfset listItem = UCase(Left(listItem, 1)) & removeChars(listItem, 1, 1)>
    <cfoutput>
    |#listItem#|
    </cfoutput>

    November 12, 2008
    I'm sorry guys but can you give me examples of what your responses are?

    The problem I cant get my head around is the spaces? How do I get to the last character of a string after the space and determine if its length is 1 or not?
    Inspiring
    November 12, 2008
    try using removechars instead of right for your concatonation.
    Inspiring
    November 12, 2008
    > the last character is only one character long

    Check the length of each item. If it is more than one character, use your current logic. Otherwise, use ucase on the entire item. Not that it makes much sense for numbers, but ...

    > <cfloop from="1" to="#ListLen(ARGUMENTS.string, ' ')#" index="i">
    > <cfset listItem = ListGetAt(ARGUMENTS.string, i, ' ')>

    Do not forget to var scope all of the local variables, including the loop index and the listItem variable.

    > <cfset returnString = returnString & ....
    > <cfif i LT ListLen(ARGUMENTS.string, ' ')>
    > <cfset returnString = returnString & ' '>
    > </cfif>

    An alternative to the concatenation code is listAppend, with a space " " delimiter.