Thread: Character conversion

  1. #1
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72

    Character conversion

    I am currently teaching myself how to program in C ( only about a month of experience as of yet) and have taken on an assignment from someone here on the forums.

    I was to write a program that accepts a string then passes that string through functions that had to be written by me to do the following:

    1) convert the entire string to uppercase and send it to the standard output
    2) convert the entire string to lowercase and send it to the standard output
    3) convert the first letter of each word to uppercase and send it to the standard output

    I was successful in #1 and #2. I have been having difficulties with the last. I seem to consistently produce all uppercase or all lowercase for some reason.

    I don't want an answer. If someone could just give me a hint or tip as to the logic behind this. I have found it helps me more to try and work most of these out, without being shown as it helps me to start thinking like a programmer.

    I can't use the string.h library for this exercise either.
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You've got #2 right? So everything's lowercase. (And you know how to uppercase things, because you can do #1.) Do you know how to tell when a word starts? (Hint: how do you know when a word ends?)

  3. #3
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    I was trying something along those lines. I was trying to check with isspace, but maybe my logic was wrong. I erased my function to start anew, but maybe I could rewrite what I had to show you.

    Should I set a variable that will be checked with boolean logic? In other words, if whitespace is found, the variable will be set to YES and so when it reaches a printable character it will toupper that character ( since this would obviously be the first character in the word ) and then set the variable to NO ( which means, as long as we keep finding characters through each incrementation of the string it will skip the conversion and then will reset to YES upon finding whitespace again, ie the end of the current word).

    Somehow I failed to even convert the first letter of the first word in my string, so I think my program structure had errors in the handling of walking through the string.

    I think I could figure out the actual conversion, but I am new to pointers and strings and believe ( as I just said ) that I am having trouble manipulating the string.

    Sorry if the above sounds convoluted...I'm trying to straighten the logic out in my head and this kind of logic is all new to me.
    Last edited by Dogmasur; 09-01-2008 at 05:45 PM. Reason: Typos fixed
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  4. #4
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    Okay, so I figured it out and got it working. Like every other program that I have put together, I like to throw it out here so you all can chew me apart...hehe. Actually, I like to hear how I could have done something simpler or more efficient. So here it is ( and please remember, I am a novice, so please be kind ):

    Code:
    /* Take in a string from the user and then produce three distinct outputs:*/
    /* 1)  convert and print as all uppercase*/
    /* 2)  convert and print as all lowercase*/
    /* 3)  convert first letter of each word to uppercase and print*/
    /* Create functions to determine if a character is upper, lower, or neither*/
    /* Create a function to change the case of a character*/
    /* Do this without the use of string.h*/
    
    #include <stdio.h>
    #include <ctype.h>
    
    
    char firstLetUpper ( char string[] );
    char upperCase ( char string[] );
    char lowerCase (  char string[] );      
    int main ( void )
    {
        char string[101];
        int c;
        
        printf("Please enter a string of 100 characters or less:\n");
        fgets ( string, 101, stdin );  /*gets a string from the user*/
        
        for ( c = 0; c <= 101; c++)  /* this removes the newline and replaces it with a null terminator*/
        {
            if ( string[c] == '\n' )
            {
                 string[c] = '\0';
                 break;
            } 
        }        
        
        upperCase ( string );  /*my function to convert all to uppercase*/
            printf("%s\n", string);
        lowerCase ( string );  /*my function to convert all to lowercase*/
            printf("%s\n", string);
        firstLetUpper ( string );  /*my function to convert the first letter of each word to uppercase*/
            printf("%s\n", string);
        
        getchar ();
        
        return 0;
        
    }              
    
    char upperCase ( char string[] ) 
    {
         char *p;
         
         for ( p = string; *p != '\0'; ++p)
         {
             *p = toupper ( *p );
         }
         
         return 0;
    }         
    
    char lowerCase ( char string[] )
    {
         char *p;
         
         for ( p = string; *p != '\0'; ++p)
         {
             *p = tolower ( *p );
         }    
    
         return 0;
    }   
    
    char firstLetUpper ( char string[] )
    {
         char *p;
         int ws = 0; /* used to check if the program is in or out of a word*/
         
         for ( p = string; *p != '\0'; ++p){
             if ( ws == 0 ){
                 *p = toupper ( *p );
                 ws = 1;
             }    
             else{
                  if ( isspace ( *p )){
                       ws = 0;
                  }
             }
         }
                 
         return 0;
    }
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    1. It's a bit of a shame that fgets doesn't return the number of characters read. Just be aware that normally, you would use strlen to find the position where the \n must be and not do the whole for-loop thing.
    2. Why are you returning 0 from your functions? Even more so, why are you returning 0 from your functions as a character?
    3. Your firstLetUpper function is brittle in the sense that it won't handle "odd strings like this with two spaces" correctly.

  6. #6
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    I understand the strlen function, but as I said, I can't use it here. I never really looked into return. What should I be returning? I'll have to read up in the FAQ so I know exactly what it does. Right now, it's just a habit. I didn't think about what would happen if I received two white spaces together. I'll check it out and see what happens when it runs and see how I can firm up the function some more.

    Thanks for the input.
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Why return anything? You're not using the result of the function in any way, and there's no error conditions that you could be signaling (you can't really go wrong with toupper or tolower).

  8. #8
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Code:
    char string[101];
    for (c = 0; c <= 101; c++) /* work with string[c] */ ;
    This will possibly access beyond the bounds of your array. If the loop runs to the end, it will try to manipulate string[101], which is invalid; the last member of the array is string[100].

    You really want to use less-than, not less-than-or-equal-to, so that the loop will run from 0 to 100.

  9. #9
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    Quote Originally Posted by tabstop View Post
    Why return anything? You're not using the result of the function in any way, and there's no error conditions that you could be signaling (you can't really go wrong with toupper or tolower).
    I think I've got you. Does this mean I can omit the return statement altogether? The return-type in the function prototype still needs to remain char though, correct? Or can I go with void?

    The moral of the story is ( as far as inside the body of the function ) if you are going to return something...return something valuable or useful or you don't really need to return at all then correct?
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  10. #10
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    Quote Originally Posted by cas View Post
    This will possibly access beyond the bounds of your array. If the loop runs to the end, it will try to manipulate string[101], which is invalid; the last member of the array is string[100].

    You really want to use less-than, not less-than-or-equal-to, so that the loop will run from 0 to 100.
    Thanks. I was thinking of the extra character to hold the NULL terminator, but forgot that the first index of the string is actually 0 and not one.
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Dogmasur View Post
    I think I've got you. Does this mean I can omit the return statement altogether? The return-type in the function prototype still needs to remain char though, correct? Or can I go with void?
    If you do not return anything then you should use void. If you do return something, you obviously need a non-void return type.
    The moral of the story is ( as far as inside the body of the function ) if you are going to return something...return something valuable or useful or you don't really need to return at all then correct?
    The function can use return to "return early" [that is, you have done the work already, so no need to continue], but a void function will have an implicit return at the final brace.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    So a void function can be used to protect your program from falling off the end of the program? I have also heard that a function without a return-type is interpreted as being an int. Is this ALWAYS true or compiler-specific?
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Dogmasur View Post
    So a void function can be used to protect your program from falling off the end of the program? I have also heard that a function without a return-type is interpreted as being an int. Is this ALWAYS true or compiler-specific?
    In C, a function without a return-type is int. A function that returns void is not a function without a return-type. I have no idea what you mean about falling off the end of the program.

  14. #14
    Registered User Dogmasur's Avatar
    Join Date
    Jul 2008
    Posts
    72
    Quote Originally Posted by tabstop View Post
    1. It's a bit of a shame that fgets doesn't return the number of characters read. Just be aware that normally, you would use strlen to find the position where the \n must be and not do the whole for-loop thing.
    2. Why are you returning 0 from your functions? Even more so, why are you returning 0 from your functions as a character?
    3. Your firstLetUpper function is brittle in the sense that it won't handle "odd strings like this with two spaces" correctly.
    1. Replied to earlier.

    2. I have fixed that issue, by not returning anything and changing my functions to void return-types.

    3. Is this better:
    Code:
    void firstLetUpper ( char string[] )
    {
         char *p;
         int ws = 0; /* used to check if the program is in or out of a word*/
         
         for ( p = string; *p != '\0'; ++p){
             if ( ws == 0 && isalpha ( *p) ){
                 *p = toupper ( *p );
                 ws = 1;
             }    
             else{
                  if ( isspace ( *p )){
                       ws = 0;
                  }
             }
         }
    }
    "The art of living is more like wrestling than dancing." - Marcus Aurelius

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Incidentally, I believe that with respect to C99, functions must explicitly have a return type.
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  2. about wide character and multiple byte character
    By George2 in forum C Programming
    Replies: 3
    Last Post: 05-22-2006, 08:11 PM
  3. pipe
    By smart girl in forum C Programming
    Replies: 4
    Last Post: 04-30-2006, 09:17 AM
  4. Conversion of character string to integer
    By supaben34 in forum C++ Programming
    Replies: 3
    Last Post: 10-30-2003, 04:34 AM
  5. UNICODE and GET_STATE
    By Registered in forum C++ Programming
    Replies: 1
    Last Post: 07-15-2002, 03:23 PM