使用strchr从数组中删除字符,不会在普通C中返回正确的值

时间:2011-12-07 21:22:27

标签: c string char return-value strstr

我正在尝试从值为的字符arrary中删除第一个分号:

  

输入:
;测试:876033074,808989746,825766962,;测试1:   825766962,

代码:

 char *cleaned = cleanResult(result);
            printf("Returned BY CLEAN: %s\n",cleaned);



    char *cleanResult(char *in)
    {   
        printf("Cleaning this: %s\n",in);

        char *firstOccur = strchr(in,';');
        printf("CLEAN To Remove: %s\n",firstOccur);
        char *restOfArray = firstOccur + 2;
        printf("CLEAN To Remove: %s\n",restOfArray); //Correct Value Printed here

        char *toRemove;
        while ((toRemove = strstr(restOfArray + 2,", ;"))!=NULL) 
        {
            printf("To Remove: %s\n",toRemove);
            memmove (toRemove, toRemove + 2, strlen(toRemove + 2));
            printf("Removed: %s\n",toRemove); //Correct Value Printed
        }

        return in;
    }
  

输出(第一个分号仍在那里):
;测试:876033074,   808989746,825766962; Test1:825766962;

3 个答案:

答案 0 :(得分:4)

关于sizeof(cleaned):使用sizeof来获取数组的容量只有在参数是数组而不是指针时才有效:

char buffer[100];
const char *pointer = "something something dark side";

// Prints 100
printf("%zu\n", sizeof(buffer));

// Prints size of pointer itself, usually 4 or 8
printf("%zu\n", sizeof(pointer));

虽然本地数组和指针都可以下标,但它们在sizeof时的行为却不同。因此,只有指向它的指针才能确定数组的容量。

另外,请记住:

void foo(char not_really_an_array[100])
{
    // Prints size of pointer!
    printf("%zu\n", sizeof(not_really_an_array));

    // Compiles, since not_really_an_array is a regular pointer
    not_really_an_array++;
}

虽然not_really_an_array被声明为数组,但它是一个函数参数,所以实际上是一个指针。它完全相同:

void foo(char *not_really_an_array)
{
...

不太合乎逻辑,但我们坚持不懈。


关于你的问题。我不清楚你要做什么。只需删除字符串的第一个字符(就地)即可通过memmove完成:

memmove( buffer             // destination
       , buffer + 1         // source
       , strlen(buffer) - 1 // number of bytes to copy
       );

这需要线性时间,并假设buffer不包含空字符串。

strcpy(buffer, buffer + 1)不会这样做的原因是因为字符串重叠,所以这会产生未定义的行为。但是,memmove明确允许源和目标重叠。

对于更复杂的字符过滤,您应该考虑使用“读取”指针和“写入”指针手动遍历字符串。只要确保写指针没有超出读指针,所以在读取时字符串不会被破坏。

void remove_semicolons(char *buffer)
{
    const char  *r = buffer;
    char        *w = buffer;

    for (; *r != '\0'; r++)
    {
        if (*r != ';')
            *w++ = *r;
    }

    *w = 0; // Terminate the string at its new length
}

答案 1 :(得分:3)

您正在使用带有重叠输入/输出缓冲区的strcpy,这会导致未定义的行为。

答案 2 :(得分:-1)

您正在搜索三个字符的序列(逗号空间分号),然后删除前两个字符(逗号和空格)。如果您也想删除分号,则需要删除所有三个字符(使用toRemove+3代替toRemove+2)。您还需要在strlen结果中添加1以说明终止字符串的NUL字节。

如果如你所说,你只想删除第一个分号而不是其他内容,则需要只搜索分号(可以使用strchr进行分号):

if ((toRemove = strchr(in, ';'))    // find a semicolon
    memmove(toRemove, toRemove+1, strlen(toRemove+1)+1);  // remove 1 char at that position