Ответ 1
std::string
- не строка с нулевым завершением. Если вы хотите его очистить, используйте метод clear()
. Если вы хотите удалить элемент строки, используйте метод erase()
.
В приведенном ниже коде я пытаюсь заменить первый символ на '\0'
.
Я ожидал, что он напечатает пустую строку, но на выходе она просто опускает это и отображает остальные символы.
int main()
{
string str;
cin >> str;
str[0] = '\0';
cout << str << "\n";
return 0;
}
ВЫХОД:
testing
esting
Как завершить строку в С++?
PS: Я пытался использовать этот подход для завершения строки в другом вопросе, в котором мне нужно заключить промежуток между ними.
std::string
- не строка с нулевым завершением. Если вы хотите его очистить, используйте метод clear()
. Если вы хотите удалить элемент строки, используйте метод erase()
.
Существует два подхода к строкам.
В C строки имеют нулевое завершение, что означает, что "\ 0" указывает конец строки, что и ожидалось.
С++ (и большинство языков) использует подсчитанные строки, что означает, что конец строки индексируется, поэтому добавление нулевых терминаторов в строку не приведет к ее завершению. '\ 0' является непечатаемым символом, поэтому при печати вы получаете поведение, которое вы видите. Если вы хотите манипулировать длиной std::string, вам нужно использовать методы std::string (http://www.cplusplus.com/reference/string/string/).
С++ не заботится о нулевых терминаторах для строк. Они просто используются для совместимости с C.
Кстати, это должно иметь поведение, которое вы ожидали.
cout<<str.c_str()<<"\n";
См. также
Почему строки с нулевым завершением? Или: с нулевым завершением против символов + длина хранения
Вы просто думаете, что получили
testing
esting
в качестве вывода, но вы действительно получили
testing
esting
^
|
+-- "empty" \0 char
поскольку std::string
все еще имеет длину "тестирования", вы просто заменили первый символ "t" на "\ 0" . Когда std::cout
получает строку, она смотрит на длину строки и выводит все ее символы, что делает "\ 0" причиной "пустого" слота на выходе.
Чтобы действительно очистить строку, предпочитайте называть std::string::clear()
. Также допустимо std::string::reset(0)
, но это не так выразительно (вы даже можете назначить пустую строку... содрогаться). Реализация может или не может использовать "\ 0" вообще, поэтому не думайте об этом как о способе возиться с внешне наблюдаемым представлением.
A std::string
похож на функциональность std::vector
. Если вы хотите удалить все элементы вашего std::string
, вы можете использовать std::string::clear
#include <iostream>
#include <string>
int main() {
std::string str("testing");
std::cout << str << std::endl;
str.clear();
std::cout << str << std::endl;
}
Если вы хотите удалить конкретный символ из своей строки (например, 1-й символ), вы можете использовать std::string::erase
:
#include <iostream>
#include <string>
int main() {
std::string str("testing");
std::cout << str << std::endl;
str.erase(str.begin());
std::cout << str << std::endl;
}
Если вы хотите удалить определенные символы из своей строки, вы могли бы, как в случае std::vector
, использовать стирание-удалить идиому:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string str("testing");
std::cout << str << std::endl;
str.erase(std::remove_if(str.begin(), str.end(), [](char const &c){ return c == 't'; }), str.end());
std::cout << str << std::endl;
}
В соответствии с реализацией std::string, [] возвращает ссылку для символа в заданной позиции во внутреннем массиве char. Когда вы устанавливаете str [8] = '\ 0, он устанавливает. Вы можете проверить это, вызвав функцию str.c_str(). Он возвращает внутренний массив.
Однако, Cout читает символы без нулевых символов посередине. Это причина выхода.
const_reference operator[](size_type __n) const
{
return *(_M_start + __n);
}
reference operator[](size_type __n)
{
return *(_M_start + __n);
}
Чтобы получить строку, которая заканчивается на первом символе, вам нужно сначала извлечь char const*
из string
, вызвав метод string::c_str()
. Затем он будет обработан по вашему желанию (например, на C).
Может быть, использовать старый добрый printf, например printf("%s", str.c_str());
, это напечатает его стиль C и закончится нулевым символом. такие вещи, как strlen(str.c_str());
, должны работать. Я подозреваю, что, поскольку строки С++ имеют функцию .size() где-то, у нее, вероятно, есть член int size;
, они не тратят время на проверку нулевого символа каждый раз, когда они хотят печатать. Возможно, они просто скажу, чтобы печатать символы str.size().