Thread: Convert to title case

  1. #1
    Registered User
    Join Date
    Jul 2008
    Posts
    3

    Convert to title case

    Hi, I need some help. I need to convert a series of words into title case without using the toupper or tolower and similar functions. Here;s my sample initial code.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char formatHere(char *firstword, char *secondword);
    {
    //I need some help here.
    
    return;
    }
    
    int main()
    {
    char string[16], string2[16];
    
    string='i nEed to ConvErt thiS';
    string2 = 'aLso tHis-onE';
    
    formatHere(*string, *string2);
    
    }
    
    
    Output should be.
    I Need To Convert This Also This-One
    Last edited by gertie; 07-06-2008 at 10:32 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What is formathere() supposed to do? If that is the function that will take a string and format it in "title case", then you should name the function something like toTitleCase().

    Also, note that main() returns an int, so you should declare it as such, and then return 0 at the end.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jul 2008
    Posts
    3
    Quote Originally Posted by laserlight View Post
    What is formathere() supposed to do? If that is the function that will take a string and format it in "title case", then you should name the function something like toTitleCase().

    Also, note that main() returns an int, so you should declare it as such, and then return 0 at the end.
    Thanks. It will not only convert but merge the strings together so I think that is OK. The problem is in the conversion itself like a loop for each character of the string maybe?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It will not only convert but merge the strings together so I think that is OK.
    Don't. Functions should do one thing and do it well. As such, you need to implement two functions: toTitleCase(), and another function which presumably would have the same functionality as strcat().
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >'i nEed to ConvErt thiS'
    1. You declared string1 to hold only 16 characters, so this string is too long to store in string1.
    2. A string literal is delimited with ""'s not '''s.
    3. You can either initialize the string at declaration, or use strcpy(). For example:
      Code:
      char string1[] = "i nEed to ConvErt thiS";
      Or with strcpy():
      Code:
      strcpy(string1, "i nEed to ConvErt thiS");

    Compile code as you write it, don't write the whole thing, and then try to compile. See the sticky post at the top of this forum for more ideas about this. And some ideas for converting to titlecase. Check for lowercase with tolower(). Check for uppercase with toupper(). Create an translation table (array) which will be used to look up the corresponding lowercase or uppercase character to translate from/to.
    Last edited by swoopy; 07-06-2008 at 10:54 AM.

  6. #6
    Registered User
    Join Date
    Oct 2007
    Posts
    242
    Well what you gotta do basically is to create a 2 loops: the first one will go over the characters in the string and the second one (inside the first one) will go over all the characters between A to Z and if str[i] equals to j (which holds the character between A to Z); if so, add to the new string which you created at the begging of the function, this: ((char) ((int)'A' + 32))
    You also have to add another loop (not inside the second one but inside the first one) that will go over all the characters between a to z and the same condition but just when you add this to the new string, you subtract 32 instead of adding.
    Code:
    If the function gets 1 parameter:
    
    char *newstr = malloc(strlen(str) + 1);
    for(;;)
    {
     for(;;)
     {
         // do stuff
     }
     for(;;)
     {
       // do stuff
     }
    }
    BTW,
    The function has to get only 1 parameters although you can create another loop which will loop twice and go over the other string too (and put both of the strings in an array of char *s: char *arr[2])
    Code:
    If the function gets 2 parameters:
    
    char *arr[2];
    arr[0] = str1;
    arr[1] = str2;
    int counter = 0;
    char *newstr = malloc(strlen(str) + 1);
    for(;;) // loop twice so we can go over 2 strings and not only one
    {
     for(;;) // loop on counter
     {
      for(;;)
      {
          // do stuff
      }
      for(;;)
      {
        // do stuff
      }
     }
     counter++; // increase counter so we can go over the second string
    }
    Good luck!
    Last edited by eXeCuTeR; 07-06-2008 at 10:59 AM.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    eXeCuTeR, pay attention to what I suggested. gertie should not be trying to combine the title case transformation and the string concatenation in one function. Consequently, there is no need to use malloc() in the function that performs title case transformation.

    I also suggest using islower(), isupper(), tolower() and toupper() for an initial implementation instead of using those loops. Once the transformation is known to work, one can then implement these functions to satisfy the requirement not to use them.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Jul 2008
    Posts
    3
    Quote Originally Posted by eXeCuTeR View Post
    Well what you gotta do basically is to create a 2 loops: the first one will go over the characters in the string and the second one (inside the first one) will go over all the characters between A to Z and if str[i] equals to j (which holds the character between A to Z); if so, add to the new string which you created at the begging of the function, this: ((char) ((int)'A' + 32))
    You also have to add another loop (not inside the second one but inside the first one) that will go over all the characters between a to z and the same condition but just when you add this to the new string, you subtract 32 instead of adding.

    Good luck!

    Thanks for this ((char) ((int)'A' + 32)). I will try to incorporate it into my own loops. Actually the strings are from a user input (not really given), and should be converted before being displayed for confirmation.

  9. #9
    Registered User
    Join Date
    Oct 2007
    Posts
    242
    Quote Originally Posted by laserlight View Post
    eXeCuTeR, pay attention to what I suggested. gertie should not be trying to combine the title case transformation and the string concatenation in one function. Consequently, there is no need to use malloc() in the function that performs title case transformation.

    I also suggest using islower(), isupper(), tolower() and toupper() for an initial implementation instead of using those loops. Once the transformation is known to work, one can then implement these functions to satisfy the requirement not to use them.
    Why not use malloc? although you could just make another array, not such a big deal.
    ---
    I thought he was forbidden to use library functions such as these.
    Anyways, it would be easier using isupper and islower (the functions he didn't mentioned he was forbidden to use); you could just skip the loops and automatically ((char) (int)str[i] + 32)) or -32 if it's big sensitive.

    Actually the strings are from a user input (not really given), and should be converted before being displayed for confirmation.
    It doesn't matter; just instead of calling it a const char *, call it a char *, no big difference.
    Last edited by eXeCuTeR; 07-06-2008 at 12:26 PM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why not use malloc? although you could just make another array, not such a big deal.
    Because having the function modify the string that is passed is a more flexible solution: the caller can pass the string to be transformed to title case, or can create a new string, copy over, and then have that new string be transformed into title case. This flexibility is a result of the idea of doing one thing and doing it well, since the function simply transforms what is given without creating something new.

    I thought he was forbidden to use library functions such as these.
    That's why I say that "Once the transformation is known to work, one can then implement these functions to satisfy the requirement not to use them."

    By the way, there is no need to explicitly cast the char to int.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Though malloc may be fine, you did forget to free the memory. If you use malloc, then you are also responsible to freeing it. It's the price you have to pay.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    you could just skip the loops and automatically ((char) (int)str[i] + 32)) or -32 if it's big sensitive.
    That would not work. For a start only the first letter in each word should be upper case; the rest is lower. Also, it would mangle non-alpha characters. I dont really see a need for the typecasting here either.

    In pseudo code it should be something like:
    Code:
    Convert the first character to upper case
    Loop through each following character
        If the character before it is whitespace or a hyphen 
            convert to uppercase
        else
            convert to lower case

  13. #13
    Registered User
    Join Date
    Oct 2007
    Posts
    242
    Quote Originally Posted by Elysia View Post
    Though malloc may be fine, you did forget to free the memory. If you use malloc, then you are also responsible to freeing it. It's the price you have to pay.
    I know that, I haven't typed the full code in there.

    That would not work.
    It would work (I mean, using the isupper and islower and +32 and -32)

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by eXeCuTeR View Post
    I know that, I haven't typed the full code in there.
    It's best you do when showing code
    No bad practices!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Jul 2008
    Posts
    26
    So you need a loop over the entire string (for, strlen), and you need a flag to detect when you have encountered white space and when you have not (fWhitespaceDetect). You can then capatilize the first character after a white space.

    Your main routine would then do something like this:

    printf ("Original: %s %s\n", string, string2);
    printf ("Converted: %s %s\n", Titlecase(string), Titlecase(string2));

    I don't like having a parameter as both a 'in' and an 'out' - I think they should be one or the other. So I wouldn't be modifying the original string, but rather returning the modified version. Then again, I don't like having to free data allocated in a previous function either, so I would typically either return a buffer to a local static variable, or request a secondary buffer in the function itself for the result (and returning the secondary buffer).

    One thing not described is how would a string such as "hEllO 23rd aveNue" be output? Since the '1' can't be uppercased, should the 'r' be converted to uppercase or not? Ie, do you search for the first letter before uppercasing?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reducing Code size from ridiculous length
    By DanFraser in forum C# Programming
    Replies: 10
    Last Post: 01-18-2005, 05:50 PM
  2. Converting Numbers to Words
    By denizengt in forum C Programming
    Replies: 20
    Last Post: 11-05-2003, 09:19 PM
  3. Basic Data types continue
    By viryonia in forum C Programming
    Replies: 6
    Last Post: 03-10-2003, 10:21 AM
  4. rand()
    By serious in forum C Programming
    Replies: 8
    Last Post: 02-15-2002, 02:07 AM