Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用循环从另一个字符串创建没有空格的新字符串_C++_String_Loops - Fatal编程技术网

C++ 如何使用循环从另一个字符串创建没有空格的新字符串

C++ 如何使用循环从另一个字符串创建没有空格的新字符串,c++,string,loops,C++,String,Loops,我开始尝试编写一个函数来删除字符串中的空格,但现在我已经了解了许多其他人对这个问题的解决方案,我更想了解我的代码中到底出了什么问题/为什么std::cout 这不是那样的。使用此选项可以更改字符串的现有字符。但由于字符串为空,这会导致未定义的行为。若要附加到字符串,请将该行改为: t += s[i]; 它将打印所需的hereissometext输出。您可以找到字符串的+=运算符的文档。当您使用运算符[]插入std::string时,循环中有未定义的行为,但不确保其大小正确。您可以使用 t.pu

我开始尝试编写一个函数来删除字符串中的空格,但现在我已经了解了许多其他人对这个问题的解决方案,我更想了解我的代码中到底出了什么问题/为什么
std::cout
这不是那样的。使用此选项可以更改字符串的现有字符。但由于字符串为空,这会导致未定义的行为。若要附加到字符串,请将该行改为:

t += s[i];

它将打印所需的
hereissometext
输出。您可以找到字符串的
+=
运算符的文档。

当您使用
运算符[]
插入
std::string
时,循环中有未定义的行为,但不确保其大小正确。您可以使用

t.push_back(s[i]);
它不仅插入一个
字符
,而且还确保在内部缓冲区对于新字符串来说太小时(重新)分配它

进一步注意,实际上并不需要
count
变量
std::string
始终跟踪其长度,因此
t.size()
将始终生成当前
计数的值(当然,一旦修复UB)

另一方面,复制序列中符合特定条件的部分是一项常见任务,并且存在一个特定的库模板,它可以完全做到这一点,并将您从手工制作的循环中解放出来:

#include <algorithm>

std::copy_if(s.cbegin(), s.cend(), std::back_inserter(t),
     [](char c){ return std::isalpha(c); });
#包括
std::copy_if(s.cbegin()、s.cend()、std::back_inserter(t),
[](字符c){return std::isalpha(c);});

最后,还要注意@MatthieurFoltzer对
std::isalpha
行为的评论,这可能值得考虑。

我建议不要使用手工制作的循环。如果
与lambda表达式结合使用,则可以使用
std::copy_来表示条件。这将比您的实现更稳定(如果字符串
s
的长度超过
int
的容量会发生什么情况?)。我认为这也提高了可读性

#include <algorithm>
#include <iostream>
#include <string>

int main() {
    std::string s = "here is some text";
    std::string t = "";
    auto comp = [&](const char c) { return std::isalpha(c); };
    std::copy_if(s.begin(), s.end(), std::back_inserter(t), comp);

    std::cout << t << std::endl;
}
#包括
#包括
#包括
int main(){
std::string s=“这里有一些文本”;
std::string t=“”;
自动编译=[&](常量字符c){return std::isalpha(c);};
std::copy_if(s.begin()、s.end()、std::back_inserter(t)、comp);

std::cout您的答案很好。您已经指出了一些改进,因此您还可以解释std::isalpha不仅会丢弃空格,而且会丢弃所有非字母字符。如果有与空格不同的特殊字符,它将不起作用。在您旁边,不需要定义lambda。只需将
::isalpha
作为的谓词即可de>std::copy_if
(您可以使用C版本,因为
std::isalpha
具有重载)@GiovanniCerretani是真的,但请注意,通常不可能在标准库中获取函数的地址-除非另有说明,否则是禁止的。虽然允许使用
::isalpha
,但我认为通常最好不要接近此类非法构造。你绝对需要副本吗?你不能在plac中这样做吗e?我这样问是因为这样可以避免无数次的
push_back()
操作的重复重新分配,从而将运行时间缩短约一百万倍。对于上面这样的18个字符的字符串来说,这不是什么问题,但是对于18000或18000000个字符,或者在多次执行此操作时……比如说,
std::erase(std::remove_if(s.begin()、s.end()、::isspace)、s.end());
或类似?即使您确实需要副本,也最好先制作副本,然后在适当的位置进行剥离。。。
#include <algorithm>

std::copy_if(s.cbegin(), s.cend(), std::back_inserter(t),
     [](char c){ return std::isalpha(c); });
#include <algorithm>
#include <iostream>
#include <string>

int main() {
    std::string s = "here is some text";
    std::string t = "";
    auto comp = [&](const char c) { return std::isalpha(c); };
    std::copy_if(s.begin(), s.end(), std::back_inserter(t), comp);

    std::cout << t << std::endl;
}