Я изучаю С++. У меня есть чип MacBook Pro M1PRO и Asus с i5 8-го поколения с Fedora 39.
Я немного знаю 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;
}
Итак, я ожидаю вывода [Hello, world], и это действительно происходит на моей машине с Linux. Но на Mac каждый раз, когда я выполняю свою программу вывода, я получаю либо правильное [Hello, world], либо неправильное [Hell, world].
Возможно, это адский мир, но мне бы очень хотелось понять, почему это происходит. Я думаю, что что-то не так с компилятором на моем Mac или ARM работает странно, но я в этом сомневаюсь.
Кроме того, пожалуйста, не стесняйтесь исправлять мой код и судить меня, это помогает мне учиться.
Спасибо!
Попробовал переключить процессор на Intel, все работает нормально. Пробовал гуглить, ничего конкретного не нашел. Пытался спросить
find_first_not_of и find_last_not_of нужен параметр массива символов, разделенный NUL. Вы предоставляете только один символ SPACE. Или, альтернативно, вы можете предоставить счет. См. en.cppreference.com/w/cpp/string/basic_string/find_first_not_ofТактическое примечание: из-за фундаментальных различий в идеологиях между C++ и Java Java (и наоборот) является плохим языком для использования в качестве основы для понимания C++. То, что вы узнаете о логике программы, останется в силе, но то, как лучше всего реализовать эту логику, часто радикально отличается.
Тактическое примечание. Chat GPT — это языковая модель, а язык, который она моделирует, НЕ является C++. Относитесь ко всему, что он говорит, с недоверием и тщательно проверяйте его результаты.
@Eljay, я использовал &SPACE, потому что думал, что если я использую адрес вместо самой строки, она не скопируется. Теперь я понял, что мне не нужно этого делать. Я просто пытался оптимизировать код.





Ваша проблема связана с
constexpr char SPACE = ' ';
const size_t first_index = input.find_first_not_of(&SPACE);
внутри функции trim. find_first_not_of ожидает в качестве входных данных строку c или std::string. &SPACE не является c-строкой, поскольку не заканчивается нулем. Это приводит к тому, что ваша программа имеет неопределенное поведение и почему вы получаете разные результаты от запуска к запуску.
Чтобы это исправить, просто поставьте лайк const std::string
const std::string SPACE = " ";
const size_t first_index = input.find_first_not_of(SPACE);
Вам также нужно будет исправить
const size_t last_index = input.find_last_not_of(&SPACE);
Используя приведенное выше предложение, которое превратит его в
const size_t last_index = input.find_last_not_of(SPACE);
Как указывает опустошение кучи в комментариях, существует также перегрузка, которая принимает всего один символ и которую можно использовать как
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);
Опереди меня на несколько секунд. Проголосуйте за :)
Другой вариант: оставить constexpr char SPACE = ' '; как есть, но использовать перегрузку с одним символом: find_first_not_of(SPACE).
@heapunderrun Хороший звонок, забыл об этой перегрузке. Я добавил это в ответ.
Передача &SPACE в find_first_of и подобные функции вызывают перегрузку, которая ожидает строку c, а не перегрузку, которая ожидает std::string.
Спасибо за ваши ответы, ребята, это сработало! Теперь у меня есть вопрос: мне не нужно использовать здесь &SPACE: input.find_first_not_of(SPACE), потому что сама функция примет его как адрес, верно? Это означает, что строка не будет воссоздаваться внутри функции.
Кроме того, я только что узнал, что есть эта функция strtok, я не знал о ней, поэтому попытался реализовать свое собственное разделение. Но эй, по крайней мере, мне нужно чему-то научиться.
@Kurisuchan strtok — это способ сделать это на языке C. Если вы хотите увидеть некоторые способы C++, см.: stackoverflow.com/questions/14265581/…
Почему вы используете
&SPACE?