Можно ли построить «бесконечную» строку? - PullRequest
3 голосов
/ 15 июля 2010

Существует ли какая-либо реальная последовательность символов, которая всегда сравнивается больше, чем любая другая строка?

Моей первой мыслью было, что строка, сконструированная следующим образом:

std::basic_string<T>(std::string::max_size(), std::numeric_limits<T>::max())

Подойдет,при условии, что тот факт, что он почти наверняка не сработает, не такая уж большая проблема.Так что я предполагаю, что такого рода хакерство может быть осуществлено только в Юникоде, если оно вообще возможно.Я никогда не слышал ничего такого, что указывало бы на то, что это действительно возможно , но я также не слышал, чтобы сказать, что это не , и мне любопытно.

Есть мысли о том, как этого добиться без possibly_infinite<basic_string<T>>?

Ответы [ 8 ]

3 голосов
/ 15 июля 2010

Я предполагаю, что вы сравниваете строки, используя их символьное значение. То есть один символ действует как цифра, более длинная строка больше короткой и т. д.

s, есть ли какая-нибудь реальная последовательность символов, которая всегда сравнивается больше, чем любая другая строка?

Нет, потому что:

  1. Давайте предположим, что есть строка s , которая всегда больше, чем любая другая строка.
  2. Если вы сделаете копию s , копия будет равна s . Равное означает «не больше». Поэтому может быть строка, которая не превышает s .
  3. Если вы сделаете копию s и добавите один символ в конце, это будет больше, чем оригинал s . Поэтому может быть строка, которая больше s .
  4. Это означает, что невозможно сделать с .

т.е.

Строка s , которая всегда больше, чем любая другая строка, не может существовать. Копия s (copy == другая строка) будет равна s , а «равно» означает «не больше».
Строка s , которая всегда больше или равна любой другой строке, может существовать, если максимальный размер строки имеет разумный предел. Без ограничения размера можно будет взять копию s , добавить один символ в конце и получить строку, которая больше s .

На мой взгляд, правильным решением было бы ввести какой-то особый строковый объект, представляющий бесконечно «большую» строку, и написать оператор сравнения для этого объекта и стандартной строки. Кроме того, в этом случае вам может понадобиться пользовательский класс строки.

Можно создать строку, которая всегда меньше или равна любой другой строке. Строка нулевой длины будет именно такой - всегда меньше, чем что-либо еще, и будет равна другим строкам нулевой длины.

Или вы можете написать контр-интуитивную процедуру сравнения, где более короткая строка больше, чем более длинная строка, но в этом случае следующий сопровождающий кода будет вас ненавидеть, так что это не очень хорошая идея.

Не уверен, зачем тебе когда-нибудь нужно что-то подобное.

2 голосов
/ 15 июля 2010

Да .Как ты это делаешь, понятия не имею:)

2 голосов
/ 15 июля 2010

Unicode решает много проблем, но не эту.Unicode - это просто другая кодировка для символа, 1, 2 или 4 байта, они все еще хранятся в простом массиве.Вы можете использовать бесконечные строки, когда найдете машину с бесконечной памятью.

2 голосов
/ 15 июля 2010

Возможно, вам нужен собственный компаратор, для которого вы определяете магическое значение "бесконечная строка" и который всегда будет обрабатывать это значение как большее, чем любое другое.

1 голос
/ 15 июля 2010

Вы должны попытаться указать, что вы намерены достичь и каковы ваши требования. В частности, имеет ли значение в виде строки? есть ли какие-либо ограничения на домен? их нужно сравнивать с <?

Вы можете использовать не строковый тип:

struct infinite_string {};
bool operator<( std::string const & , infinite_string const & ) {
   return true;
}
bool operator<( infinite_string const &, std::string const & ) {
   return false;
}

Если вы можете использовать std::lexicographical_compare и вам не нужно хранить его как строку, то вы можете написать бесконечный итератор:

template <typename CharT>
struct infinite_iterator
{
   CharT operator*() { return std::numeric_limits<CharT>::max(); }
   infinite_iterator& operator++() { return *this; }
   bool operator<( const infinite_iterator& ) { return true; }
   // all other stuff to make it proper
};
assert( std::lexicographical_compare( str.begin(), str.end(), 
                              infinite_iterator, infinite_iterator ) );

Если вы можете использовать любой другой функтор сравнения, и в вашем домене есть недействительный код, вы можете использовать его в своих интересах:

namespace detail {
   // assume that "\0\0\0\0\0" is not valid in your domain
   std::string const infinite( 5, 0 ); 
}
bool compare( std::string const & lhs, std::string const & rhs ) {
   if ( lhs == detail::infinite ) return false;
   if ( rhs == detail::infinite ) return true;
   return lhs < rhs;
}
0 голосов
/ 15 июля 2010

Какой у тебя компаратор?

Исходя из этого, вы можете построить что-то, что является «вершиной» вашей решетки.

0 голосов
/ 15 июля 2010

Что ж, если бы вы динамически создавали строку равной длины, с которой сравнивались, и заполняли ее самым высоким из доступных ASCII-кода (7F для обычного ASCII или FF для расширенного), вы бы гарантировали, что эта строка будетсравните значение, равное или большее, чем у того, с которым вы сравниваете.

0 голосов
/ 15 июля 2010

, если вам нужна искусственная граница в пространстве объектов, которые не ограничены , стандартным приемом является добавление дополнительного элемента и определение нового оператора сравнения, который применяет ваше свойство.

Или реализовать ленивые струны.

...