Использование remove_if с пустой строкой в ​​Си

У меня есть ситуация, когда я хочу эффективно удалить символ из символа NULL с символом *. Я могу предположить, что входящая строка является большой (то есть, было бы неэффективно копировать); но я также могу предположить, что мне не нужно выделять неиспользуемую память.

Я думал, что мог бы использовать std::remove_if для этой задачи (заменив символ в возвращаемом итераторе на NULL-терминатор) и настройте следующую тестовую программу, чтобы убедиться, что синтаксис правильный:

#include <algorithm>
#include <iostream>

bool is_bad (const char &c) {
return c == 'a';
}

int main (int argc, char *argv[]) {
char * test1 = "123a45";
int len = 6;
std::cout << test1 << std::endl;
char * new_end = std::remove_if(&test1[0], &test1[len], is_bad);
*new_end = '\0';
std::cout << test1 << std::endl;

return 0;
}

Эта программа компилируется, однако я получаю Segmentation Fault где-то в remove_if — вот вывод из gdb:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400914 in std::remove_copy_if<char*, char*, bool (*)(char const&)> (__first=0x400c2c "45", __last=0x400c2e "", __result=0x400c2b "a45",
__pred=0x4007d8 <is_bad(char const&)>) at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1218
1218                *__result = *__first;

Это с gcc 4.1.2 на RedHat 4.1.2-52.

Насколько я понимаю, необработанные указатели могут быть использованы как ForwardIteratorsа может и нет? Какие-либо предложения?

1

Решение

Программа имеет неопределенное поведение при попытке изменить строковый литерал:

char * test1 = "123a45";

Изменить на:

char test1[] = "123a45"; // 'test1' is a copy of the string literal.
char * new_end = std::remove_if(test1, test1 + sizeof(test1), is_bad);

Увидеть http://ideone.com/yzeo4k.

5

Другие решения

Ваша программа имеет неопределенное поведение, так как вы пытаетесь изменить массив const символы (строковые литералы являются массивами const персонажи). В соответствии с пунктом 7.1.6.1/4 стандарта C ++ 11:

За исключением того, что любой член класса объявлен mutable (7.1.1) могут быть изменены, любая попытка изменить const
объект в течение его жизни (3.8) приводит к неопределенному поведению.

Обратите внимание, что начиная с C ++ 11 преобразование из строкового литерала в char* является незаконным, и в C ++ 03 устарел (GCC 4.7.2 дает мне предупреждение за это).

Чтобы исправить вашу программу с минимальными изменениями, объявите test1 как массив символов и инициализировать его из строкового литерала:

char test1[] = "123a45";

Вот живой пример.

4

По вопросам рекламы [email protected]