Просто был интересный аргумент в комментарии к одному из моих вопросов. Мой оппонент утверждает, что заявление ""
делает не содержать ""
неправильно.
Я считаю, что если ""
содержал другой ""
, что один также будет содержать ""
и так далее.
Кто не прав?
Постскриптум
Я говорю о std::string
Постскриптум P.S
Я не говорил о подстроках, но даже если я добавлю к своему вопросу «как подстроку», это все равно не имеет смысла. Пустая подстрока ерунда. Если вы разрешаете содержать пустые подстроки в строках, это означает, что у вас есть бесконечность пустых подстрок. Какой смысл в этом?
Я единственный, кто считает, что с функцией что-то не так? std::string::find
?
Ссылка на C ++ ясно говорит
Возвращаемое значение: позиция первого символа первого совпадения.
Хорошо, давайте предположим, что это имеет смысл на минуту и запустим этот код:
string empty1 = "";
string empty2 = "";
int postition = empty1.find(empty2);
cout << "found \"\" at index " << position << endl;
Выход: found "" at index 0
Бессмысленная часть: как может быть индекс 0 в строке длины 0? Это ерунда.
Чтобы быть в состоянии даже иметь 0-я позиция, строка должна быть длиной не менее 1 символа.
И C ++ дает исключение в этом случае, что подтверждает мою точку зрения:
cout << empty2.at( empty1.find(empty2) ) << endl;
Если бы он действительно содержал пустую строку, у него не было бы проблем распечатать его.
Это зависит от того, что вы подразумеваете под «содержит».
Пустая строка подстрока пустой строки, и поэтому содержится в этом смысле.
С другой стороны, если вы рассматриваете строку как набор символов, пустая строка не может содержать пустую строку, поскольку ее элементы являются символами, а не строками.
Относительно наборов, набор
{2}
это подмножество из набора
A = {1, 2, 3}
но {2}
это не член из A
— все A
Членами являются числа, а не множества.
Точно так же, {}
это подмножество {}
, но {}
не является элементом в {}
(это не может быть, потому что это пусто).
Так что вы оба правы.
C ++ согласен с вашим «оппонентом»:
#include <iostream>
#include <string>
using namespace std;
int main()
{
bool contains = string("").find(string("")) != string::npos;
cout << "\"\" contains \"\": "<< boolalpha << contains;
}
Выход: "" contains "": true
Это просто. Строка A содержит подстроку B, если есть аргумент offset
такой, что A.substr(offset, B.size()) == B
, Никаких особых случаев для пустых строк не требуется.
Итак, посмотрим. std::string("").substr(0,0)
оказывается std::string("")
, И мы можем даже проверить ваш «контрпример». std::string("").substr(0,0).substr(0,0)
также четко определен и пуст. Черепахи все время вниз.
Первое, что неясно, говорите ли вы о std::string
или строки C с нулевым символом в конце, второе почему это должно иметь значение?. Я приду std::string
,
Требования к std::string
определить, как должен вести себя компонент, а не каким должно быть его внутреннее представление (хотя некоторые требования влияют на внутреннее представление). Если требования к компоненту соблюдены, то, содержит ли он что-то внутри, является деталью реализации, которую вы, возможно, даже не сможете проверить.
В частном случае пустой строки нет ничего, что требовало бы, чтобы она содержала что-либо. Он может содержать элемент размера, установленный в 0, и указатель (для динамически выделяемой памяти, если / когда он не пустой) также установлен в 0. Требование в operator[]
требует, чтобы он возвращал ссылку на символ со значением 0, но поскольку этот символ нельзя изменить, не вызывая неопределенного поведения, и поскольку строгие правила псевдонимов позволяют читать из lvalue типа char, реализация может просто вернуть ссылку на один из байты в size
член (все установлено в 0) в случае пустой строки.
Некоторые реализации std::string
использовать оптимизацию небольших объектов, в этих реализациях будет зарезервирована память для небольших строк, включая пустой строка. В то время как std::string
явно не будет содержать std::string
внутренне он может содержать последовательность символов, составляющих пустую строку (то есть завершающий нулевой символ)
пустая строка ничего не содержит — это ПУСТО. 🙂
Конечно, пустая строка не содержать пустая строка. Это будут черепахи, если так и будет.
принимать String empty = "";
который объявляет строковый литерал, который является пустым, если вы хотите, чтобы строковый литерал представлять пустой строковый литерал, который вам понадобится String representsEMpty = """";
но, конечно, вы должны избежать этого, давая вам string actuallyRepresentsEmpty = "\"\"";
PS Я принимаю прагматичный подход к этому. Оставьте математическую ерунду у двери.
Думая о вашей поправке, вполне возможно, что ваш «оппонент» имел в виду, что «пустая» строка std :: string по-прежнему имеет внутреннюю память для символов, которая сама по себе не содержит символов. Я уверен, что это было бы деталью реализации, возможно, он мог бы просто сохранить массив символов определенного размера (скажем, 10) «просто упаковывать», так что технически он не будет пустым.
Конечно, есть вопрос с подвохом, что «ничто» не вписывается во что-то бесконечное время, что-то вроде ситуации «делим на ноль».
Сегодня у меня возник тот же вопрос, поскольку в настоящее время я связан с паршивой реализацией STL (восходящей к эпохе, предшествовавшей C ++ 98), которая отличается от C ++ 98 и всех следующих стандартов:
TEST_ASSERT(std::string().find(std::string()) == string::npos); // WRONG!!! (non-standard)
Это особенно плохо, если вы пытаетесь написать переносимый код, потому что так трудно доказать, что ни одна функция не зависит от этого поведения. К сожалению, в моем случае это действительно так: он выполняет обработку строк, чтобы сократить ввод телефонных номеров в зависимости от спецификации абонентской линии.
На Cppreference я вижу в станд :: basic_string :: найти Явное описание пустых строк, которое, я думаю, точно соответствует рассматриваемому случаю:
пустая подстрока находится в pos, если и только если pos <= размер ()
Упомянутый pos
определяет позицию, с которой начинается поиск, по умолчанию 0
(начало).
Соответствующий стандарту Стандартная библиотека C ++ пройдут следующие тесты:
TEST_ASSERT(std::string().find(std::string()) == 0);
TEST_ASSERT(std::string().substr(0, 0).empty());
TEST_ASSERT(std::string().substr().empty());
Такое толкование «содержать» отвечает на вопрос «да».