Удаление символа из массива с использованием strchr, не возвращает правильное значение в простой C - PullRequest
0 голосов
/ 08 декабря 2011

Я пытаюсь удалить первую точку с запятой из набора символов, значение которого:

Ввод:
; Тест: 876033074, 808989746, 825766962; Test1: 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; Тест1: 825766962;

Ответы [ 3 ]

4 голосов
/ 08 декабря 2011

Относительно 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
}
3 голосов
/ 08 декабря 2011

Вы используете strcpy с перекрывающимся буфером ввода / вывода, что приводит к неопределенному поведению.

0 голосов
/ 08 декабря 2011

Вы ищете последовательность из трех символов (точка с запятой), а затем удаляете первые два (запятая и пробел).Если вы также хотите удалить точку с запятой, вам нужно удалить все три символа (используйте toRemove+3 вместо toRemove+2).Вам также нужно добавить 1 к результату strlen для учета байта NUL, завершающего строку.

Если, как вы говорите, вы просто хотите удалить первую точку с запятой и ничего больше, вам нужно искатьточка с запятой (которую вы можете сделать с strchr):

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