我已将文本文件内容加载到std :: string。我想从加载的字符串中删除空格。
方法1:
在循环语句中使用string.find()扫描字符串,并使用string.erase()删除空格;
方法2:
在循环语句中使用string.find()扫描字符串,并使用string.append()将非空白字符复制到新的string()变量;
方法3:
在循环语句中使用string.find()扫描字符串,并使用string.replace()将非空白字符复制到新字符串(size_t n,char c)变量;
方法4:
分配char *(使用malloc [源字符串的大小])
在循环语句中使用string.find()扫描字符串,并使用strcpy将非空格字符复制到char *变量,然后使用strcat();
最后将char *复制到一个新的字符串
免费char *
答案 0 :(得分:11)
编辑已升级为区域设置感知特征。谢谢用户657267!
标准算法很整洁!
s.erase(std::remove_if(
begin(s), end(s),
[l = std::locale{}](auto ch) { return std::isspace(ch, l); }
), end(s));
这是为了就地修改,但是如果你需要保留原始字符串:
std::string s2;
s2.reserve(s.size());
std::remove_copy_if(
begin(s), end(s),
std::back_inserter(s2),
[l = std::locale{}](auto ch) { return std::isspace(ch, l); }
);
答案 1 :(得分:3)
为了便于阅读,我会选择boost string algorithm library
#include <boost/algorithm/string.hpp>
std::string str1="Hello Dolly, Hello World!"
boost::erase_all(str1, " ");
编辑: 所有空白字符的示例:
std::string str1="Hello Dolly,\n Hello\t World!\t";
boost::find_format_all(str1, boost::token_finder(::isspace), boost::const_formatter(""));
EDIT2:
我运行了一些基准测试,看看这种方法与Quentin的答案相比如何。我使用区域设置感知版本和非区域设置感知版本的isspace
运行了100个样本。微秒的平均时间是:
| method | avg. time (μs) |
|-----------------------------------|----------------|
| boost::find_format_all w/locale | 2.02429 |
| boost::find_format_all w/o locale | 0.578105588 |
| std::remove_if w/locale | 1.197737742 |
| std::remove_if w/o locale | 0.190661227 |
答案 2 :(得分:3)
恕我直言,你可以通过方法2获得最佳性能,但在追加之前,你需要调用std::string::reserve
方法将新字符串的容量设置为初始字符串的大小。这需要在附加时防止不必要的重新分配。
答案 3 :(得分:1)
为了性能,最好一次读取字符串一个平台字(64位平台上的8个字节),然后从寄存器读取中提取每个字符,测试它是否为空白,如果它不是空格,将其添加到下一个要写入的平台字宽寄存器中。当要写入的寄存器已满(存储的字符数可以容纳在寄存器中)时,将其写入预先分配的输出缓冲区。对于单字节字符串,字符逐字符扫描速度要慢8倍。
最后,字符串的尾部可能包含的字符数少于占用完整平台字的字符数。然后需要一个计数器来知道最后处理的平台字中有多少个字符。
答案 4 :(得分:1)
方法5:使用库覆盖所有边缘情况(包括当前区域设置),并且当且仅当分析显示它是一个问题时进行调整。
#include <algorithm>
#include <functional>
#include <iostream>
#include <locale>
#include <string>
template<typename CharT, typename Traits, typename Allocator>
std::basic_string<CharT, Traits, Allocator>
strip_whitespace(std::basic_string<CharT, Traits, Allocator> str)
{
str.erase(
remove_if(str.begin(), str.end(), bind(
std::isspace<CharT>, std::placeholders::_1, std::locale{}
)),
str.end()
);
return str;
}
int main()
{
std::string str{"A string with \n whitespace"};
std::cout << str << '\n' << strip_whitespace(str) << '\n';
}
答案 5 :(得分:1)
目前尚不清楚“删除空格”究竟是什么意思 - 它是打算让文本不可读并破坏源代码,还是指“任何多余的空格”?
由于有一个答案提示第三方库,我将使用Qt的方法,它将仅删除“多余的空白”:
QString s("Test\n new line, multiple spacebars \t tab!");
qDebug() << s;
qDebug() << s.simplified();
输出:
"Test
new line, multiple spacebars tab!"
"Test new line, multiple spacebars tab!"
其他大部分答案都集中在删除所有空格键,但严格来说,还有其他字符可以分类为空格,例如制表符或换行符。
查看simplified()
方法的代码,我认为它非常有效:
QString QString::simplified() const
{
if (d->size == 0)
return *this;
QString result(d->size, Qt::Uninitialized);
const QChar *from = (const QChar*) d->data;
const QChar *fromend = (const QChar*) from+d->size;
int outc=0;
QChar *to = (QChar*) result.d->data;
for (;;) {
while (from!=fromend && from->isSpace())
from++;
while (from!=fromend && !from->isSpace())
to[outc++] = *from++;
if (from!=fromend)
to[outc++] = QLatin1Char(' ');
else
break;
}
if (outc > 0 && to[outc-1] == QLatin1Char(' '))
outc--;
result.truncate(outc);
return result;
}
新的字符串是在没有初始化的情况下预先分配的,因此避免了任何初始化和任何重新分配,然后类似于方法2(记住追加而不保留空间将导致许多和缓慢的重新分配),只有有用的数据被复制到结果字符串,最后,它被修剪得更短,以消除任何浪费的内存。
您可以按照此逻辑有效地为std::string
直接来自Qt source code。