我使用以下内容从变量中删除空格
for (i=0, ptr=lpsz;ptr[i];ptr++)
{
if (*ptr == ' ')
i++;
*ptr = ptr[i];
}
*ptr=0;
当有多个空间时似乎有问题而且我不确定我做错了什么。有人可以帮帮我吗?
答案 0 :(得分:6)
我建议您使用std::isspace
而不是做指针魔术。
如果您将std::string
与std::isspace
结合使用,则可以执行以下操作:
std::string str = "Hello World Today";
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
字符串实际上只是一个字符容器,因此您可以将删除/删除惯用法应用于它。
答案 1 :(得分:2)
这应该有效。考虑通过字符串移动的两个指针比一个指针加上一个偏移量要容易得多。
auto sptr = lpsz;
auto dptr = lpsz;
while (*dptr = *sptr) { // copy up to and including terminating NUL
if (*dptr != ' ') dptr++; // but spaces take no slots in the destination
sptr++;
}
甚至
auto sptr = lpsz;
auto dptr = lpsz;
while (auto c = *dptr = *sptr) {
dptr += (c != ' ');
sptr++;
}
这与原始代码之间的本质区别在于,当我们看到除了空格之外的其他内容时,我和原始代码都将读取和写入位置向前移动一个。但是当我们看到一个空格时,我将读取位置向前移动1并且不移动写入位置,而原始位置将读取位置向前移动2并将写入位置向前移动一个,这会跳过一个字符。此外,原始版本在写入位置测试空间,而不是在读取位置(我测试写入位置,但是在从读取位置复制字符后,>,因此结果是对的。)
答案 2 :(得分:1)
你应该使用算法,因为它们经过了很好的测试。但是,如果您想分析代码并了解故障,请考虑对代码运行情况的高级描述(参见Tony的答案)。
您在缓冲区中维护两个索引,一个用于读取,一个用于写入。每当读数头检测到一个空间时,你就会移动它但跳过写入。如果字符不是空格,则使用读头获取值并通过写头写入。
在你的实现中,读头是ptr+i
,作为写头的偏移拼写有点奇怪(如ptr[i]
中所示)。写头是ptr
(*ptr =
)。但是你在循环中的测试是使用 write 头而不是 read head:if (*ptr==' ')
。
即使您解决了这个问题,实现还有其他问题,例如,如果有两个连续的空格,那么因为您在循环中进行了一次测试。重写您的算法可能是:
char* remove_spaces(char* buffer) {
char *read = buffer;
for (char *read = buffer; (*read), ++read) {
if (*read != ' ') { // copy element
*buffer = *read;
++buffer; // and increment write head
}
}
*buffer = 0; // ensure null termination
return read;
}
现在,如果您对第一个空间进行初始搜索并将其用作上面循环的起点,则可以通过删除对内存的写入次数来进一步改进(性能)算法。这将减少操作次数和标记为脏的缓存行数。
答案 3 :(得分:0)
仔细地循环你的循环。
循环开始时 i
设置为0。
对于遇到的第一个空格,i
会递增(因此i==1
)。 ptr
处的字符将替换为prt+i
处的字符,即下一个字符。这是第一次使用,因为i
是1。
但是对于第二个空格,i
设置为2(因为它递增),所以空格被ptr+2
作为字符串副本的一部分,而不是就地更改,这样做会容易得多。
dest
是我们更改副本的目标缓冲区。
for(ptr = lpsz; *ptr; ptr++){
if(' ' == *ptr) {continue;}
*dest = *ptr;
dest++;
}
*dest = 0;