我开始尝试编写一个函数,该函数将从字符串中删除空格,但是现在,我已经研究了许多其他人针对该问题的解决方案,而我只是想确切地了解代码中出了什么问题/为什么std::cout << t << std::endl;
末尾什么都不输出。
当我std::cout << t[count];
在循环中包含该语句(在下面注释掉的语句)时,它将正确输出到控制台:hereissometext
无空格。当我std::cout << t[0] << std::endl;
结束时,它正确输出h
,t[1]
as e
,t[2]
as r
,依此类推。但是,当我尝试t
在最后输出时,它输出空格,并t.size()
输出0
。
我是编码的新手,如果这是一个完全明显的问题,请原谅我。
std::string s = "here is some text";
std::string t = "";
int count = 0;
for (int i = 0; i < s.size(); i++) {
if (std::isalpha(s[i])) {
t[count]+=s[i];
// std::cout << t[count];
count++;
}
}
std::cout << t << std::endl;
Run Code Online (Sandbox Code Playgroud)
lub*_*bgr 12
您在std::string
使用插入operator[]
而不确保其大小正确时,在循环中有未定义的行为。您可以改用
t.push_back(s[i]);
Run Code Online (Sandbox Code Playgroud)
这不仅会插入一个char
,而且还要确保当内部缓冲区对于新字符串而言太小时会重新分配内部缓冲区。
还要注意,您实际上并不需要该count
变量。std::string
始终跟踪其长度,因此t.size()
将始终产生当前值count
(当然,一旦修复了UB)。
顺便说一句,复制序列中符合特定条件的部分是一项常见的任务,并且存在一个特定的库模板可以完全做到这一点,并使您摆脱手工制作的循环:
#include <algorithm>
std::copy_if(s.cbegin(), s.cend(), std::back_inserter(t),
[](char c){ return std::isalpha(c); });
Run Code Online (Sandbox Code Playgroud)
最后,还要注意@MatthieurFoltzer对的行为的评论std::isalpha
,可能值得考虑。
t[count]+=s[i];
Run Code Online (Sandbox Code Playgroud)
这样不行。这样,您可以更改字符串的现有字符。但是,由于您的字符串为空,因此会导致未定义的行为。要附加到字符串,请将该行改为:
t += s[i];
Run Code Online (Sandbox Code Playgroud)
并输出所需的输出hereissometext
。您可以在此处找到+=
字符串操作员的文档。
我建议不要使用手工制作的循环。您可以将其std::copy_if
与lambda表达式结合使用以制定条件。这将比您的实现更稳定(如果字符串的长度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;
}
Run Code Online (Sandbox Code Playgroud)