1

I', learning C and I'm getting no output for some reason, probably I don't return as I should but how I should? (described the problem in the comments below :D) Any help is appreciated!

#include <stdio.h>
#include <ctype.h>
#include <string.h>

char *makeUpperCase (char *string);

int main()
{
    printf(makeUpperCase("hello")); //Here there is no output, and when I'm trying with the format %s it returns null
    return 0;
}

char *makeUpperCase(char *string)
{
    char str_out[strlen(string) + 1];
    for (int i = 0; i < strlen(string); ++i)
        str_out[i] = toupper(string[i]);

    printf(str_out); //Here I get the output.
    return str_out;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Patton13
  • 27
  • 5
  • `str_out` is a **local** variable inside the function. Once the function returns there is no more `str_out`. The function returns the address of the array's first element (`return str_out;`) and immediately afterwards deletes the array so the `printf()` in your `main()` uses the address of something that does no longer exist (a string that does not exist). – pmg Jan 16 '22 at 11:51
  • Read this: [Returning an array in C](https://stackoverflow.com/questions/11656532/returning-an-array-using-c). There are hundreds of similar/duplicate instances of this mistake on this site, but alas the vernacular used by the people who post them (who are nearly always beginners) are so unbelievably diverse they're often hard to find. – WhozCraig Jan 16 '22 at 11:54

2 Answers2

1

You declared within the function a local variable length array that will not be alive after exiting the function

char str_out[strlen(string) + 1];

So your program has undefined behavior.

If the function parameter declared without the qualifier const then it means that the function changes the passed string in place. Such a function can be defined the following way

char * makeUpperCase( char *string )
{
    for ( char *p = string; *p != '\0'; ++p )
    {
        *p = toupper( ( unsigned char )*p );
    }

    return string;
}

Otherwise you need to allocate dynamically a new string. For example

char * makeUpperCase( const char *string )
{
    char *str_out = malloc( strlen( string ) + 1 );

    if ( str_out != NULL )
    { 
        char *p = str_out;

        for ( ; *string != '\0'; ++string )
        {
            *p++ = toupper( ( unsigned char )*string );
        }

        *p = '\0';
    }

    return str_out;
}

Here is a demonstration program.

#include <stdop.h>
#include <stdlib.h>
#include <string.h>

char *makeUpperCase( const char *string )
{
    char *str_out = malloc( strlen( string ) + 1 );

    if (str_out != NULL)
    {
        char *p = str_out;

        for (; *string != '\0'; ++string)
        {
            *p++ = toupper( ( unsigned char )*string );
        }

        *p = '\0';
    }

    return str_out;
}

int main( void )
{
    char *p = makeUpperCase( "hello" );

    puts( p );

    free( p );
}

The program output is

HELLO
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I tried your solution but still it does not printing the output in the main function. :( I'm getting Segmentation fault here `*p = toupper( ( unsigned char )*p );` – Patton13 Jan 16 '22 at 12:03
  • @Patton13 You may not change a string literal. Use the second function from mu answer. – Vlad from Moscow Jan 16 '22 at 12:05
0

The problem is that printf() is buffering output based on a bit complex mechanism. When you are outputting to a terminal, printf() just buffers everything until the buffer fills (which is not going to happen with just the string "hello", or until it receives a '\n' character (which you have not used in your statement)

So, to force a buffer flush, just add the following statement

    fflush(stdout);

after your printf() call.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31