2009-10-15 3 views
10

Есть ли что-нибудь подобное в стандартном C++/STL? В идеале он должен быть построен какC++ фиксированная длина строки?

fstring s = fstring(10); 

Мне нужно иногда построить или иметь строку фиксированного размера. Иногда, чтобы иметь возможность читать/писать только много символов в поток.

Edit:

Обратите внимание, что размер известно лишь во время выполнения, и отличается от одного к другому. Но все fstring s должны знать, как работать вместе и иметь все причудливое поведение string.

+1

Я немного ржавый, но как это отличается от char []? – Lazarus

+1

@Lazarus - класс std :: string-esque с фиксированной строкой мог бы предложить гораздо больше функциональности, включая переопределение <>, чем базовый тип char []. Также AFAIK не может иметь std :: vector , но будет возможно иметь std :: vector >. – Tom

+0

Какое «причудливое» поведение строк вы хотите использовать? Это помогло бы нам дать лучший ответ, если бы мы знали подмножество функций-членов строки, которые вы использовали. –

ответ

0

C стиль массив символов?

char label[10] = "a string"; 
+0

Это пропускает все функции-члены контейнера STL - даже подмножество, которое может применяться к контейнеру с фиксированной длиной. – sbi

1

Почему бы не использовать std :: basic_string из STL как фиксированный класс строк?

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

basic_string(
    size_type _Count, 
    value_type _Ch, 
    const allocator_type& _Al = Allocator () 
); 

в инициализаторе.

Позже изменения: Пример:

std::string my10CharStringInitializedWithSpace(10, ' '); 
+0

Проблема заключается в том, что созданная строка не выполняет обрезку/отступы или не обеспечивает ограничение на 10 символов. – Ayman

+0

Для этого вам нужно определить свой собственный класс, если вы хотите инкапсулированное решение, или использовать то, что существует на рынке. См. Алгоритмы форматирования строки для обрезки: http://www.boost.org/doc/libs/1_40_0/doc/html/string_algo.html –

0

Если я вас правильно понимаю, вы не хотите использовать std::string, потому что вы беспокоитесь, что может тихо расширить на вас. Я вижу несколько вариантов:

  1. Используйте необработанную строку C-стиль и функции от cstdio, которые принимают длину аргумент (например, fgets).

  2. Использовать std::vector<char>.

+0

Но 'std :: vector ' также будет бесшумно расширяться! Возьмите http://stackoverflow.com/questions/1571901/1571978#1571978 – sbi

+0

Только если вы его попросите. 'operator >>' в строке будет автоматически расширять строку, чтобы разместить все, что вы читаете. С помощью вектора вы должны явно вставить или push_back мимо введенного ограничения. –

+0

Ах, вы имеете в виду 'operator >>'. Это было непонятно из вашего сообщения. – sbi

1

Возможно, что-то в boost, которое обеспечивает это (ближайший, которого я лично видел, является Boost.Array, которого недостаточно). Тем не менее, если вы просто хотите, чтобы смоделировать «важное подмножество» из std::string, это не очень сложно сделать фиксированную длину эквивалент:

template <size_t N> 
class fixed_string 
{ 
    // ... interface looks like std::string 
}; 

Для тех, кто с просьбой о том, почему потрудившись сделать это на всех, Основное преимущество заключается в том, чтобы избежать выделения памяти, не теряя большую часть полезного API std::string. Если есть еще один способ сделать это с std::allocator, мне было бы интересно узнать.

+0

Я пробовал, но я не вижу, как это может работать. Проблема в том, что строка может (будет) запрашивать больше памяти из распределителя, чем это требуется в настоящее время. Например, когда я устанавливаю лимит моего распределителя на 32 символа, мне удалось отбросить только 16 символов из 25. – UncleBens

5

использования, например,

std::tr1::array<char, 10> 
+5

Теперь, когда C++ 11 уже здесь, можно использовать std :: array по адресу http://en.cppreference.com/w/cpp/container/array. –

2

Как насчет наследования std::string приватно затем подвергая меньший интерфейс с using, и писать свои собственные < < и >> функции?

1

Я использовал что-то вроде этого для строк, выделенных в стеке или как часть другого объекта. Что в выпуске становится символ *

#ifdef DEBUG 
#define STR_DEBUG 
#endif 

#define FIXED_STRING(maxSize) ReservedString<maxSize> _Tmp##__LINE__; 

class FixedString{ 
public: 
    FixedString& operator =(char const * const pStr); 
    //FixedString& operator =(FixedString const &pStr); 
    operator const char*() const { return mStr; } 
    const char* cStr() const { return mStr; } 
    FixedString& operator +=(const char *pStr); 
    bool equals(const char *pStr); 
    bool beginsWith(const char *pStr); 
    /// rises ASSERT if not enough 
    void ensureEnoughForNMore(int NMoreSymbols); 
protected: 
    char *mStr; 
    #ifdef STR_DEBUG 
     ui16 mMaxLength; 
    #endif 

private: 
    #ifdef STR_DEBUG 
     FixedString(char *str, ui16 maxLength): mStr(str), mMaxLength(maxLength) {} 
    #else 
     FixedString(char *str): mStr(str) {} 
    #endif 
    template<int> 
    friend class ReservedString; 
}; 

template <int MAX_LENGTH> class ReservedString{ 
public: 
    operator FixedString() { 
     #ifdef STR_DEBUG 
      return FixedString(mBuf, MAX_LENGTH); 
     #else 
      return FixedString(mBuf); 
     #endif 
    } 
private: 
    char mBuf[MAX_LENGTH+1]; 
}; 
1

С C++ 11, можно пойти на

std::array<char,10> s; 

Также станд :: строка эквивалентна всегда может быть построен, когда требуется

std::string s2(std::begin(s), std::end(s)); 
Смежные вопросы