NUL char в строках в С++

В приведенном ниже коде я пытаюсь заменить первый символ на '\0'.

Я ожидал, что он напечатает пустую строку, но на выходе она просто опускает это и отображает остальные символы.

int main()
{
    string str;
    cin >> str;

    str[0] = '\0';

    cout << str << "\n";
    return 0;
}

ВЫХОД:

   testing
   esting

Как завершить строку в С++?

PS: Я пытался использовать этот подход для завершения строки в другом вопросе, в котором мне нужно заключить промежуток между ними.

Ответ 1

std::string - не строка с нулевым завершением. Если вы хотите его очистить, используйте метод clear(). Если вы хотите удалить элемент строки, используйте метод erase().

Ответ 2

Существует два подхода к строкам.

В C строки имеют нулевое завершение, что означает, что "\ 0" указывает конец строки, что и ожидалось.

С++ (и большинство языков) использует подсчитанные строки, что означает, что конец строки индексируется, поэтому добавление нулевых терминаторов в строку не приведет к ее завершению. '\ 0' является непечатаемым символом, поэтому при печати вы получаете поведение, которое вы видите. Если вы хотите манипулировать длиной std::string, вам нужно использовать методы std::string (http://www.cplusplus.com/reference/string/string/).

С++ не заботится о нулевых терминаторах для строк. Они просто используются для совместимости с C.

Кстати, это должно иметь поведение, которое вы ожидали.

cout<<str.c_str()<<"\n";

См. также

Почему строки с нулевым завершением? Или: с нулевым завершением против символов + длина хранения

В чем обоснование строк с нулевым завершением?

Ответ 3

Вы просто думаете, что получили

testing
esting

в качестве вывода, но вы действительно получили

testing
 esting
^
|
+-- "empty" \0 char

поскольку std::string все еще имеет длину "тестирования", вы просто заменили первый символ "t" на "\ 0" . Когда std::cout получает строку, она смотрит на длину строки и выводит все ее символы, что делает "\ 0" причиной "пустого" слота на выходе.

Чтобы действительно очистить строку, предпочитайте называть std::string::clear(). Также допустимо std::string::reset(0), но это не так выразительно (вы даже можете назначить пустую строку... содрогаться). Реализация может или не может использовать "\ 0" вообще, поэтому не думайте об этом как о способе возиться с внешне наблюдаемым представлением.

Ответ 4

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;
}

Ответ 5

В соответствии с реализацией 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);
}

Ответ 6

Чтобы получить строку, которая заканчивается на первом символе, вам нужно сначала извлечь char const* из string, вызвав метод string::c_str(). Затем он будет обработан по вашему желанию (например, на C).

Ответ 7

Может быть, использовать старый добрый printf, например printf("%s", str.c_str());, это напечатает его стиль C и закончится нулевым символом. такие вещи, как strlen(str.c_str());, должны работать. Я подозреваю, что, поскольку строки С++ имеют функцию .size() где-то, у нее, вероятно, есть член int size;, они не тратят время на проверку нулевого символа каждый раз, когда они хотят печатать. Возможно, они просто скажу, чтобы печатать символы str.size().