tags:

views:

328

answers:

8

Is there anything like this in Standard C++ / STL? Ideally it should be constructed like

fstring s = fstring(10);

I need to sometimes construct or have a string of fixed size. Sometimes to be able to read / write only that many characters into a stream.

Edit:

Note that the size is only known at runtime, and is different from one to the other. But all of the fstrings should know how to work together and have all the fancy string behavior.

A: 

C style character array?

char label[10] = "a string";
Joel
That misses all of the member functions of an STL container - even the subset that could apply to a fixed-length container.
sbi
+1  A: 

Why not use std::basic_string from STL as a fixed string class?

You can use the constructor

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

as initializer.

Later edit: Example:

std::string my10CharStringInitializedWithSpace( 10, ' ');
Cătălin Pitiș
How can that be put in code? I'm relatively new to C++ syntax.
Ayman
See my latest edit
Cătălin Pitiș
Problem is, the created string does not do any trimming / padding, or ensuring its 10 char limit.
Ayman
For that, you need to define your own class, if you want an encapsulated solution, or to use what exists on the market. See boost string algorithms for trimming: http://www.boost.org/doc/libs/1_40_0/doc/html/string_algo.html
Cătălin Pitiș
A: 

If I understand you correctly, you don't want to use std::string because you're worried it might silently expand on you. I see a couple of options:

  1. Use a raw C-style string and the functions from cstdio that take a length argument (e.g., fgets).

  2. Use a std::vector<char>.

Kristo
But `std::vector<char>` will silently expand, too! Take http://stackoverflow.com/questions/1571901/1571978#1571978
sbi
Only if you ask it to. `operator>>` on a string will automagically expand the string to accomodate whatever you're reading. With a vector you'd have to explicitly insert or push_back past your imposed limit.
Kristo
Ah, you're referring to `operator>>`. This wasn't clear from your posting.
sbi
A: 

There's probably something in boost that provides this (the closest I've personally seen is Boost.Array, which is insufficient). However, if you're just looking to model the "important subset" of std::string, it's not very difficult to make a fixed-length equivalent:

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

For anyone asking about why bothering to do this at all, the main benefit is to avoid memory allocation without losing most of the useful std::string API. If there's another way to do this with std::allocator, I'd be curious to know.

Tom
I tried, but I don't see how this can work. The problem is, the string may (will) request more memory from the allocator than it needs currently. E.g, when I set the limit of my allocator on 32 characters, I only managed to push back 16 characters out of 25.
UncleBens
+4  A: 

The closest approximation today is boost::array<char, 10>

MSalters
+2  A: 

Use e.g.

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

Stuart
+2  A: 

How about inheriting std::string privately then exposing a smaller interface with using, and writing your own << and >> functions?

Marcus Lindblom
A: 

I've been using something like this for strings allocated on stack or as a part of another object. Which in release becomes a char*

#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];
};
baltic