我正在学习C++。我有一台 MacBook Pro M1PRO 芯片和一台配备 Fedora 39 的第 8 代 i5 的华硕。
我了解一点 Java,所以在我的 Hello World 项目中,我尝试重新创建分割和修剪函数,但在 C+ 中,我发现一些非常令人费解的东西。
我在两台机器上使用以下命令进行编译:
g++ -std=c++20 -o hello main.cpp
代码:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
string vector_to_string(const vector<string>& v, const string& separator = "") {
string result = "[";
for (size_t i = 0; i < v.size(); ++i) {
result += v[i];
if (i < v.size() - 1) {
result += separator;
}
}
result += "]";
return result;
}
string trim(const string& input) {
if (input.empty()) {
return "";
}
constexpr char SPACE = ' ';
const size_t first_index = input.find_first_not_of(&SPACE);
if (first_index == string::npos) {
return "";
}
const size_t last_index = input.find_last_not_of(&SPACE);
return input.substr(first_index, last_index - first_index + 1);
}
vector<string> split(const string& input, const char delimiter) {
vector<string> tokens;
size_t last_start = 0;
for(size_t i = 0; i < input.length(); i++) {
if (input[i] == delimiter) {
string token = trim(input.substr(last_start, i - last_start));
if (!token.empty()) {
tokens.push_back(token);
}
last_start = i + 1;
}
}
string lastToken = trim(input.substr(last_start));
if (!lastToken.empty()) {
tokens.push_back(lastToken);
}
return tokens;
}
int main() {
const string input = "Hello world";
const vector<string> tokens = split(input, ' ');
cout << vector_to_string(tokens, ", ") << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以我期待一个 [Hello, world] 输出,它确实在我的 Linux 机器上完美地发生。但在 Mac 上,每次执行输出程序时,我要么得到正确的 [Hello, world],要么得到不正确的 [Hell, world]。
这可能是一个地狱般的世界,但我非常想了解为什么会发生这种情况。我的想法是我的 Mac 上的编译器有问题,或者 ARM 工作得很奇怪,但我对此表示怀疑。
另外,请随时纠正我的代码并评判我,这有助于我学习。
谢谢!
尝试将CPU换成intel,效果很好。尝试谷歌搜索,找不到任何具体内容。尝试询问 ChatGPT 但它不知道如何回答。
你的问题是
constexpr char SPACE = ' ';
const size_t first_index = input.find_first_not_of(&SPACE);
Run Code Online (Sandbox Code Playgroud)
函数内部trim。 find_first_not_of需要一个 c 字符串或 astd::string作为输入。 &SPACE不是一个 C 字符串,因为它不是以 null 结尾的。这使得您的程序具有未定义的行为,以及为什么您每次运行都会得到不同的结果。
要解决这个问题,只需使用const std::string类似的
const std::string SPACE = " ";
const size_t first_index = input.find_first_not_of(SPACE);
Run Code Online (Sandbox Code Playgroud)
您还需要修复
const size_t last_index = input.find_last_not_of(&SPACE);
Run Code Online (Sandbox Code Playgroud)
使用上述建议将其变成
const size_t last_index = input.find_last_not_of(SPACE);
Run Code Online (Sandbox Code Playgroud)
正如评论中的heap underrun所指出的,还有一个只需要单个字符的重载,可以像这样使用
constexpr char SPACE = ' ';
const size_t first_index = input.find_first_not_of(SPACE);
...
const size_t last_index = input.find_last_not_of(SPACE);
Run Code Online (Sandbox Code Playgroud)