Thread: Some help for a newbie.

  1. #1
    Registered User
    Join Date
    Aug 2017
    Posts
    3

    Some help for a newbie.

    Hello, guys.
    I really need some help. To say that programming is akin to magic to me would be an understatement, so forgive this (probably) stupid question of mine.
    I wanted to try out the "toupper" function in C and my plan was to write a simple program that would change the case of my input from lowercase to uppercase.
    Everything seemed to be ok. But I have run into problem that I cannot solve: the program I wrote stops working when facing a space character in my input. I don't know what I can do about it. Really. I've tried "isspace" fuction, but the result is the same. The only word that gets transformed is the one before the first space. The rest of the input is lost.
    I would appreciate very much if you could point out where my mistake is and what I am supposed to do to fix it.
    This is my code:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    
    int main(void)
    {
        char message[25];
        printf("What is your message to the world?\n");
        scanf("%s", message);
        
        for(int i = 0, n = strlen(message); i < n; i++)
        {
            if(isalpha(message[i]))
            {
                if(islower(message[i]))
                {
                    printf("%c", toupper(message[i]));
                }
                else
                {
                    printf("%c", message[i]);
                }
            }
            else
            {
                printf("%c", message[i]);
            }
        }
        return 0;
    }
    I really can't understand why the very first space terminates the program. If I replace them with some random characters, then everything seems to be working just fine.
    Thanks!

  2. #2
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by Abactor View Post
    I really can't understand why the very first space terminates the program. If I replace them with some random characters, then everything seems to be working just fine.
    Thanks!
    The %s scanf format stops reading on a space. If you want to continue reading after the space, you have a few options:

    1. Simple workaround is to replace %s with the %[...] syntax to coax scanf to continue reading any non-newline character:

    Code:
    scanf("%[^\n]", message);
    2. A safer option is to use fgets to read an entire line of input. This option is safer because you can avoid buffer overflows. With scanf there's not an easy, general way to avoid them.

    Code:
    char message[25];    
    printf("What is your message to the world?\n");
    fgets(message, sizeof(message), stdin);
    message[sizeof(message)-1] = '\0'; // Ensure '\0' termination.
    
    /* ... rest of code */

  3. #3
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by c99tutorial View Post
    Code:
    char message[25];    
    printf("What is your message to the world?\n");
    fgets(message, sizeof(message), stdin);
    message[sizeof(message)-1] = '\0'; // Ensure '\0' termination.
    You've accidentaly used sizeof instead of strlen in removing the newline. Should be:
    Code:
    message[strlen(message)-1] = '\0'; // Ensure '\0' termination.
    There are, of course, some problems with this approach, but it's good enough for now.

    As for the loop in the code, it could be written like this:
    Code:
        for(int i = 0, n = strlen(message); i < n; i++)
            printf("%c", toupper(message[i]));
    toupper passes a character through unchanged if it can't be converted to upper case.

    You can avoid the strlen call, too:
    Code:
        for(int i = 0; message[i] != '\0'; i++)
            printf("%c", toupper(message[i]));
    And you should print a final newline afterwards since if you don't the prompt appears on the same line as the output (on linux, at least).

    Now that I think about it, there's no reason to use the expensive printf function when the cheap putchar will do:
    Code:
        for(int i = 0; message[i] != '\0'; i++)
            putchar(toupper(message[i]));
        putchar('\n');
    Defintion of the day:
    abactor: one who steals cattle
    Last edited by algorism; 08-02-2017 at 03:07 PM.

  4. #4
    Registered User
    Join Date
    Aug 2017
    Posts
    3
    Ooooooooh, now I see.
    Thank you, guys, really appreciate it!!!!!

  5. #5
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by algorism View Post
    You've accidentaly used sizeof instead of strlen in removing the newline. Should be:
    Code:
    message[strlen(message)-1] = '\0'; // Ensure '\0' termination.
    fgets is not guaranteed to write a '\0' byte to the buffer, so strlen is not guaranteed to work. Hence this line:

    Code:
    message[sizeof(message)-1] = '\0'; // Ensure '\0' termination.
    After that, you can safely use strlen on message, but unfortunately not before.

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    fgets is not guaranteed to write a '\0' byte to the buffer,
    The fgets() function will always* write the end of string character ('\0') to the string. What is not guaranteed to be written to the string is the end of line character ('\n'), which is only written to the string if there is enough room.

    And remember that the sizeof operator will only work when the array definition is in the same scope.

    Edit: * Unless eof() is encountered before any character is received.


    Jim
    Last edited by jimblumberg; 08-03-2017 at 02:08 PM.

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by c99tutorial View Post
    fgets is not guaranteed to write a '\0' byte to the buffer, so strlen is not guaranteed to work. Hence this line:
    Code:
    message[sizeof(message)-1] = '\0'; // Ensure '\0' termination.
    After that, you can safely use strlen on message, but unfortunately not before.
    Then it's even more of a half-assed solution than I originally thought. The only way fgets won't 0-terminate the string is if it returns NULL, so the obviously superior solution is to test its return value. Your "solution" simply "ensures" the 0-termination of a string of garbage. Useless.
    Code:
    if (fgets(message, sizeof message, stdin) == NULL)
        ; // handle eof or other problem
    else
        message[strcspn(message, "\n")] = 0; // remove newline

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Hello, I am a newbie and so I have a newbie question;)
    By piratemonkey247 in forum C Programming
    Replies: 4
    Last Post: 12-20-2012, 10:59 AM
  2. Newbie with Very Newbie Question
    By Jedi_Mediator in forum C++ Programming
    Replies: 18
    Last Post: 07-01-2008, 08:00 AM
  3. C++ newbie / linux not so newbie question
    By goldmonkey in forum C++ Programming
    Replies: 7
    Last Post: 12-13-2003, 12:27 PM
  4. Newbie but not really
    By atanpoco in forum C++ Programming
    Replies: 10
    Last Post: 05-13-2003, 09:22 AM
  5. Newbie needs help
    By Getintothegame in forum Windows Programming
    Replies: 4
    Last Post: 05-04-2003, 02:07 AM

Tags for this Thread