使用remove_if与C以空结尾的字符串
Using remove_if with C null-terminated string
我有一种情况,我想有效地从一个以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 = ' ';
std::cout << test1 << std::endl;
return 0;
}
这个程序编译,然而,我在remove_if
的某个地方得到了一个Segmentation Fault
-这是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;
这是在RedHat 4.1.2-52上的gcc 4.1.2
。
我的理解是原始指针可以用作ForwardIterators
,但也许不是?有什么建议吗?
程序在试图修改字符串文字时有未定义的行为:
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 .
您的程序有未定义的行为,因为您试图修改const
字符的数组(字符串字面量是const
字符的数组)。c++ 11标准第7.1.6.1/4段:
除了可以修改任何声明为
mutable
(7.1.1)的类成员外,任何修改const
的尝试都可以被修改对象在其生命周期(3.8)内导致未定义的行为。
请注意,自c++ 11以来,从字符串文字到char*
的转换是非法的,并且在c++ 03中已被弃用(GCC 4.7.2为此给了我一个警告)。
要用最小的更改来修复程序,请将test1
声明为字符数组,并从字符串字面值初始化它:
char test1[] = "123a45";
下面是一个的实例