#c #c 11 #c 14 #c 17
#c #c 11 #c 14 #c 17
Вопрос:
Я пишу функцию, которая возвращает строку. Но произошло что-то странное. Вывод result
строки был напечатан как неожиданная вещь с консоли.
Он становится китайским или чем-то другим или ПУСТОЙ строкой в зависимости от машины (ПРОТЕСТИРОВАНО). Но это происходит только тогда, когда входная строка очень длинная. Это работает нормально для строк с меньшим размером.
Есть ли лучший способ добавить char
к строке? Это потому, что я подозреваю, что проблема была вызвана тем, как я добавил символы в конец строки.
Из консоли
Из отладчика
main.cpp
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool checkPalindrome(string s)
{
return (s == std::string(s.rbegin(), s.rend()));
}
string longestPalindrome(string s)
{
if (s.size() > 1000 || s.empty())
return "";
string result = "";
string sub = "";
char* ptr = amp;sub[0];
for (int i = 0; i < s.length(); i) {
sub = s[i];
while (true) {
string temp = ptr;
if (checkPalindrome(temp)) {
ptr = amp;sub[0];
if (temp.length() > result.length()) {
result = temp;
break;
}
break;
}
else {
ptr ;
}
if (ptr == amp;sub[sub.length()-1]) {
ptr = amp;sub[0];
break;
}
}
}
std::cout << "end of function" << std::endl;
return resu<
}
int main()
{
string output = longestPalindrome("babaddtattarrattatddetartrateedredividerb");
std::cout << output << std::endl;
return 0;
}
Комментарии:
1. Это не компилируется, потому что
output
является локальной переменной вmain
, но вы каким-то образом получаете к ней доступlongestPalindrome
. Пожалуйста, опубликуйте фактический, компилируемый код.2. почему бы и нет
for (auto character : s)
3. @Blaze извините за это. Я просто хотел, чтобы aovid использовал то же имя vairbale, а затем изменил локальную переменную
output
наresult
в функцииlongestPalindrome
. Я обновил сообщение4.
string sub = ""; char* ptr = amp;sub[0];
Не приведет ли это к UB?5.
amp;sub[0]
в пустой строке нет UB: eel.is/c draft/strings#string.access-1
Ответ №1:
Выражение char* ptr = amp;sub[0];
дает вам указатель на char
. Однако при выполнении sub = s[i];
вам может потребоваться, чтобы внутренняя память string
увеличилась, чтобы вместить новый символ. Если вы продолжаете добавлять к нему, в конечном итоге это произойдет. Это сделает его недействительным ptr
и сделает его непригодным для использования до тех пор, пока он не будет переназначен.
Когда такое перераспределение действительно происходит, выделяется буфер большего размера, предыдущее значение перемещается из более короткого буфера в буфер большего размера, затем более короткий буфер уничтожается для замены на больший. Но ptr
все еще указывает на то, где раньше находились данные предыдущего более короткого буфера. Теперь он указывает на элемент уничтоженного объекта. Когда вы затем это сделаете, string temp = ptr;
вы рискуете инициализировать string
из недействительного указателя, поведение которого не определено.
Одним из относительно простых решений было бы придерживаться индексов вместо указателей. Индексы по своей природе не становятся недействительными, пока они находятся в пределах размера string
. Другим возможным решением может быть использование reserve
для предварительного выделения достаточно большой емкости, чтобы ее никогда не приходилось перераспределять.