简体   繁体   English

用C语言从字符数组中去除空格

[英]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.该函数需要从包含' ''\\t''\\n'的字符串中删除所有空格。该函数的输出应该是输入字符串的副本,但删除了所有空格。 The function prototype should stay the same and void .函数原型应该保持不变和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.现在strNoSpaceparamStrNoSpace的副本,它指向同一个内存,在本例中为 NULL。 Then inside your function you change strNoSpace to something, malloc() returns.然后在您的函数strNoSpace更改为某些内容, malloc()返回。 Now strNoSpace is something different to NULL, while paramStrNoSpace is still NULL, because strNoSpace was a copy of that pointer.现在strNoSpace与 NULL 不同,而paramStrNoSpace仍然是 NULL,因为strNoSpace是该指针的副本。

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.现在strNoSpace指向存储指针paramStrNoSpace的确切位置。 Whenever you modify *strNoSpace , you actually modify paramStrNoSpace now.每当您修改*strNoSpace ,您现在实际上是在修改paramStrNoSpace

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 .现在removeWS()永远不会改变strWithSpace Therefore we can pass it as a simple pointer again, but we have to tell removeWS() the size of the allocated memory block.因此我们可以再次将它作为一个简单的指针传递,但我们必须告诉removeWS()分配的内存块的大小。 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您在for条件中引用string ,而不是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.当您看到空格时,您只会放置NUL ( '\\0' ) 终止符(这实际上毫无意义,因为您将覆盖下一个非空格字符),但不会在您完成循环时放置,因此如果输入不以空格结尾,字符串不是以NUL结尾的。
  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.您在循环中正确推进(或不正确) j ,但也在for循环增量步骤中推进它,因此您将NUL分散在周围(过早终止字符串)并在此之前跳过非空格字符。

This can be done inplace as characters are being removed.这可以在删除字符时就地完成。 The pointers to and from advance through the string.指针tofrom提前通过字符串。 When a space is found only from is advanced.当找到一个空间时,只有from是先进的。

#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';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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