简体   繁体   中英

Removing whitespace from a character array in C language

Can someone please let me know where the problem is and how to correct it.

The function is required to remove all whitespace from a string which includes ' ' , '\\t' and '\\n' The output of the function should be a copy of the input string but with all of whitespace removed. The function prototype should stay the same and void .

void removeWS(char *strNoSpace, const char *strWithSpace)
{
    int i, j;

    stringNoSpace = malloc(strlen(strWithSpace) + 1);

    for(i = 0, j = 0; stringWithSpace[i] != '\0'; i++, j++){

        if (isspace((char) strWithSpace[i]) != 0){

            strNoSpace[j++] = strWithSpace[i];

        }

    }

}

Stripped down to the actual issue:

void removeWS(char *strNoSpace, const char *strWithSpace)
{
    strNoSpace = malloc(strlen(strWithSpace) + 1);
    // ...
}

// ....
char* paramStrNoSpace = NULL;
char* paramStrWithSpace = "...";
removeWS(paramStrNoSpace, paramStrWithSpace);

Now strNoSpace is a copy of paramStrNoSpace It points to the same memory, which in this case is NULL. Then inside your function you change strNoSpace to something, malloc() returns. Now strNoSpace is something different to NULL, while paramStrNoSpace is still NULL, because strNoSpace was a copy of that pointer.

A simple soulution could be to pass a pointer to a pointer instead:

void removeWS(char **strNoSpace, const char *strWithSpace)
{
    *strNoSpace = malloc(strlen(strWithSpace) + 1);
    // ...
}

// ....
char* paramStrNoSpace = NULL;
char* paramStrWithSpace = "...";
removeWS(&paramStrNoSpace, paramStrWithSpace);

Now strNoSpace points to the exact position, where the pointer paramStrNoSpace is stored. Whenever you modify *strNoSpace , you actually modify paramStrNoSpace now.

The downside of that approach is, that you will loose track of your memory allocations sooner or later, when functions just allocate and return new memory. The rule of thumb is: whoever allocates memory, is also responsible to free it. Therefore I think a better interface would expect the caller to allocate enough memory for this function:

void removeWS(char *strNoSpace, ind strNoSpaceMaxSize, const char *strWithSpace)
{
    // ...
}

// ....
char* paramStrWithSpace = "...";
char* paramStrNoSpace = malloc(strlen(paramStrWithSpace) + 1);
removeWS(paramStrNoSpace, strlen(paramStrWithSpace), paramStrWithSpace);

Now removeWS() does never change strWithSpace . Therefore we can pass it as a simple pointer again, but we have to tell removeWS() the size of the allocated memory block. It has to check while running and stop in case, there is not enough memory.

I see three obvious issues:

  1. You refer to string in the for condition, not strWithSpace
  2. You're only placing NUL ( '\\0' ) terminators when you see a space (which is actually pointless, since you'll overwrite on the next non-space character), but not when you finish the loop, so if the input doesn't end with whitespace, the string isn't NUL -terminated.
  3. You're advancing (or not) j correctly within the loop, but also advancing it in the for loop increment step, so you'll leave NUL s scattered around (prematurely terminating the string) and skip non-space characters before then.

This can be done inplace as characters are being removed. The pointers to and from advance through the string. When a space is found only from is advanced.

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

void removeWS( char *strWithSpace)
{
    //declare two pointers and set them to first character of strWithSpace
    char *to = strWithSpace;
    char *from = strWithSpace;

    while ( *from) {//when from points to terminating '\0' while will exit
        if ( isspace ( *from)) {
            from++;//found space character, advance from
            continue;//back to top of while
        }
        *to = *from;//copy from character to to
        to++;//advance to
        from++;//advance from
    }
    *to = '\0';//set terminating '\0'
}

int main( int argc, char *argv[])
{
    char text[40] = {"text with spaces between the words"};

    printf("before   %s\n", text);
    removeWS( text);
    printf("after    %s\n", text);

    return 0;
}

try this

void removeWS(char *strNoSpace, const char *strWithSpace)
{
    int i, j;

    strNoSpace = malloc(strlen(strWithSpace) + 1);
    if ( strNoSpace == NULL ) {
            // error handle 
    }

    for(i = 0, j = 0; strWithSpace[i] != '\0'; i++ ) {    
        if ( isspace( strWithSpace[ i ] ) == 0 ) {
                strNoSpace[j++] = strWithSpace[i];    
        }    
    }
    strNoSpace[ j ] = '\0';
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM