-1

How can I make a function in C that just returns the value of the string passed to it, for instance in the example given in main(), I would like to "normalize" the string "wACkY!" to just "Wacky!". I have managed to do this with a void function that directly modifies the string at its memory location, but what I want to do is not modify the string itself, but just return a modified version of it.

How can I do this?

printf("%s\n", normalize(string));

My normalize function

char *normalize(char *a) {
printf("%s\n", a);
int i = 0;
a[i] = toupper(a[i]);
for (i = 1; a[i] != '\0'; ++i) {
    a[i] = tolower(a[i]);
}
return a;
}

In main()

char *string = "wACkY!";
printf("%s\n", string);
printf("%s\n", normalize(string));
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Filip Markoski
  • 333
  • 3
  • 19
  • 1
    C doesn't have a string type; C only has character arrays. –  Feb 11 '17 at 10:00
  • 1
    And your invoke from `main` to the existing function shouldn't work anyway unless your implementation is being particularly generous. That's a read-only string-literal addressed by a non-const pointer, and passed to a function attempting to modify it in-place. [**Don't do that**](https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-string-initialized-with-cha), regardless of the answer to this question. – WhozCraig Feb 11 '17 at 10:14

4 Answers4

1
  1. Create a new heap memory with the size of the string that you have passed, please consider addition +1 for '\0' character. Use malloc, or calloc.
  2. Use memcpy or strncpy to write on the new heap memory.

  3. Make changes to the new memory using whatever you have done with the normalize function.

  4. And return the new char *

Ehsan
  • 1,338
  • 14
  • 13
  • I did it. It worked. But what happen to the new string that I made using malloc. Is there a way to free that memory after it has been returned using the function return? – Filip Markoski Feb 11 '17 at 10:22
  • Yes. save the return dynamically allocated and modified char * (which is a string!) to a variable. And you can free the variable. However, if you use printf("%s\n", normalize(string)); in such case the memory location will be orphaned, meaning, not freed for reuse. so better, do the following: char * modifiedString = normalize(string); printf("%s\n", modifiedString); free(modifiedString); All the best – Ehsan Feb 11 '17 at 13:43
  • sorry about the indentation! In comments they do not allow such things. – Ehsan Feb 11 '17 at 13:46
1

You can do this without using malloc(), and thus avoiding potential memory leaks, by employing VLAs, and changing the function prototype of normalize() to accept an additional argument that is an array for the new string.

In the program below, a character array, newstring[], is declared in main() after finding its size by finding the length of string using strlen() and adding space for the '\0' terminator. Note that the function normalize() modifies the character array newstring[] through the pointer to, so that after the function call the effects can be seen in newstring[] within main(). But newstring[] also returns a pointer to the first character in newstring[], allowing the string resulting from calling normalize() to be printed directly by printf().

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

char * normalize(char *to, char *from)
{
    strcpy(to, from);

    for (size_t i = 0; from[i] != '\0'; i++) {
        to[i] = tolower(from[i]);
    }

    to[0] = toupper(to[0]);

    return to;
}

int main(void)
{
    char *string = "wACkY!";
    size_t newstring_sz = strlen(string) + 1;
    char newstring[newstring_sz];

    printf("%s\n", string);    
    normalize(newstring, string);
    printf("%s\n", newstring);

    /* Alternatively */
    string = "wACkY!";
    printf("%s\n", string);    
    printf("%s\n", normalize(newstring, string));

    return 0;
}

Program output:

wACkY!
Wacky!
wACkY!
Wacky!
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • There is no point returning a char * (my opinion) for the normalize free-function. Because you are already returning by updating the char *to. So a better software engineering would be to use void type return. – Ehsan Feb 11 '17 at 13:48
  • @Ehsan-- I disagree. 1) Returning a pointer allows the return value to be used directly, in `printf()` for example. 2) Returning a pointer allows the function to return `NULL` if function input is deemed incorrect for some reason or in case of error within the function. Consider that many library functions, e.g., `fgets()`, return a pointer to the modified buffer. In general, I find returning such a pointer to be a useful feature. – ad absurdum Feb 11 '17 at 13:56
  • Yes! You are right! Under such circumstance, I do agree with you. – Ehsan Feb 11 '17 at 13:58
0

You need to write a function that either receives a buffer from the caller to place the modified string in, or allocates new memory for the modified string that it returns.

Although it wouldn't be difficult to provide you with this function, I feel you should do it yourself as a learning excercise. To allocate new memory for the string to return, look at malloc().

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
-1

I think that a more flexible approach is when the function gets the target string as a parameter and performs copying of the source string.

Here is shown how it can look

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

char * copy_normalized( char *s1, const char *s2 )
{
    char *p = s1;

    while ( isspace( ( unsigned char )*s2 ) ) *p++ = *s2++;

    *p = toupper( ( unsigned char )*s2 );

    while ( *s2 ) *++p = tolower( ( unsigned char )*++s2 );

    return s1;
}   

int main( void ) 
{
    char s[] = "wACkY!";
    char t[sizeof( s )];

    puts( s );
    puts( copy_normalized( t, s ) );

    printf( "\n" );

    char *p = malloc( sizeof( s ) );

    puts( s );
    puts( copy_normalized( p, s ) );

    free( p );

    return 0;
}

The program output is

wACkY!
Wacky!

wACkY!
Wacky!

You can add a check that the character that should be converted to upper case is an alpha character.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • There is no point returning a char * (my opinion) for the normalize free-function. Because you are already returning by updating the char *to. So a better software engineering would be to use void type return. Just my view! – Ehsan Feb 11 '17 at 13:49
  • 1
    @Ehsan All C standard string functions confirm this convention. This allows to chain in one statement several calls of string functions. So user-defined functions also should follow this convention. – Vlad from Moscow Feb 11 '17 at 14:34