'Declaring a string of fixed size

In C we do

char buffer[100];

Is there a way to declare a fixed size std::string?



Solution 1:[1]

You can use the string::reserve method like this

  std::string s;
  s.reserve(100);

But this isn't fixed size, because you can add more chars to the string with string::push_back for example.

Solution 2:[2]

In c++17, there will be std::string_view which offers the same (immutable) interface as std::string.

In the meantime, you can wrap a char array and add whatever services to it you choose, eg:

template<std::size_t N>
struct immutable_string
{
    using ref = const char (&)[N+1];
    constexpr immutable_string(ref s)
    : s(s)
    {}

    constexpr auto begin() const { return (const char*)s; }
    constexpr auto end() const { return begin() + size(); }
    constexpr std::size_t size() const { return N; }
    constexpr ref c_str() const { return s; }
    ref s;

    friend std::ostream& operator<<(std::ostream& os, immutable_string s)
    {
        return os.write(s.c_str(), s.size());
    }
};

template<std::size_t NL, std::size_t NR>
std::string operator+(immutable_string<NL> l, immutable_string<NR> r)
{
    std::string result;
    result.reserve(l.size() + r.size());
    result.assign(l.begin(), l.end());
    result.insert(result.end(), r.begin(), r.end());
    return result;
}

template<std::size_t N>
auto make_immutable_string(const char (&s) [N])
{
    return immutable_string<N-1>(s);
}

int main()
{
    auto x = make_immutable_string("hello, world");
    std::cout << x << std::endl;

    auto a = make_immutable_string("foo");
    auto b = make_immutable_string("bar");
    auto c = a + b;
    std::cout << c << std::endl;
}

Solution 3:[3]

As of Boost 1.66: A non-allocating string that emulates the interface of std::basic_string.

Solution 4:[4]

I don't know what you want to do, but with an std::array<char, 100> buffer; you should do fine.

You can then get a string like this:

std::string str(std::begin(buffer),std::end(buffer);

Solution 5:[5]

check this https://github.com/m3janitha/fixed_size_string. you can replace char buffer[n]; with fss::fixed_size_string<n> buffer;

Solution 6:[6]

You could use std::array, which is the C++ method of doing exactly what you did in C.

std::array<char, 100> buffer;

If you're worried about stack overflow due to large buffer sizes (like, for example, if that 100 is a stand-in for 1'000'000) you could dynamically allocate it instead.

std::unique_ptr<std::array<char, 100>> buffer = std::make_unique<std::array<char, 100>>();

Since your interface takes a char * as its operand, and this object allows you to query for its size at runtime, this ought to suffice.

Solution 7:[7]

Finally, I made the solution shown below. It will run on Excel 64 bit, but probably it can easily be changed to 32 bit (see suggestions in the code). I have tested it on Excel 2016.

' Helge V. Larsen (MSc, PhD)
' [email protected]
' HELA Consulting
' January 2022.

' Regarding Windows API: Very much inspired by the late Howard Kaikow:
' http://www.standards.com/Office/SetVBAProjectPassword.html
'
' Author: Howard Kaikow
' URL   : http://www.standards.com/
' Email : [email protected]
' Date  : April 2005

' This will run in Excel 64 bit.
' It will probably run in Excel 32 bit
' if you remove all "PtrSafe" and change all "LongPtr" to "Long".
' (I cannot test it since I do not have access to Exccel 32 bit.)
'
' Alternatively, you could use compiler directives
'     #If VBA7 Then
'     #Else
'     #End If
' to make it run in Excel 32 and 64 bit    .

Option Explicit

' API constants
Private Const BM_CLICK As Long = &HF5&
Private Const BM_SETCHECK As Long = &HF1&
Private Const BST_CHECKED As Long = &H1&
Private Const EM_REPLACESEL As Long = &HC2&
Private Const HWND_TOPMOST As Long = -1
Private Const SWP_NOACTIVATE As Long = &H10&
Private Const SWP_NOMOVE As Long = &H2&
Private Const SWP_NOSIZE As Long = &H1&
Private Const SWP_SHOWWINDOW As Long = &H40&
Private Const TCM_SETCURFOCUS As Long = &H1330&

' API functions and subs
Private Declare PtrSafe Function EnumChildWindows Lib "user32" _
    (ByVal hWndParent As LongPtr, ByVal lpEnumFunc As LongPtr, ByVal lParam As Long) As Long
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function GetDlgItem Lib "user32.dll" _
    (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long) As Long
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare PtrSafe Function SetFocusAPI Lib "user32" Alias "SetFocus" _
    (ByVal hWnd As Long) As Long
Private Declare PtrSafe Sub SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, _
    ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long)

Private hWndProjectProperties As LongPtr

Sub HVL_Lock_VBProject()
    
    ' Protect VBProject in workbook.
    ' The workbook is opened in another instance of Excel.
    
    Dim appExcel As Excel.Application
    Dim wbkExcel As Excel.Workbook
    
    Dim aFile As String
    Dim Pass  As String
    
    aFile = HVL_GetFile_Dialog("Browse for Excel workbook", ThisWorkbook.Path, "Excel files, *.xl*,")
    If aFile = vbNullString Then Exit Sub
    
    Set appExcel = New Excel.Application
    appExcel.Visible = False
    
    Set wbkExcel = appExcel.Workbooks.Open(aFile)
    
    If wbkExcel.VBProject.Protection = vbext_pp_none Then
       Pass = HVL_Get_PassWord
       If Pass = vbNullString Then GoTo Exit_Sub
       SetPassword wbkExcel.VBProject, Pass
    Else ' vbext_pp_locked
       MsgBox "The VBproject in" & vbCr & _
              aFile & vbCr & _
              "is protected." & vbCr & vbCr & _
              "Cannot change Project Password.", _
              vbInformation, _
              "Information"
       GoTo Exit_Sub
    End If
    
    wbkExcel.Save
    wbkExcel.Close False
    
    MsgBox "The VBproject in" & vbCr & _
           aFile & vbCr & _
           "has been locked.", _
           vbInformation, _
           "Information"
    
Exit_Sub:

    appExcel.Quit
    
    Set appExcel = Nothing
    Set wbkExcel = Nothing

End Sub

Sub SetPassword(ByRef aVBProject As VBProject, ByVal strPassword As String)

    ' Author: Howard Kaikow
    ' URL   : http://www.standards.com/
    ' Email : [email protected]
    ' Date  : April 2005
    ' spy++ was used to find the Control IDs in Project Properties dialog
    
    ' Changed by Helge V. Larsen.

    Const ControlIDConfirmPassword As Long = &H1556&
    Const ControlIDLockProject As Long = &H1557&
    Const ControlIDOK As Long = &H1&
    Const ControlIDPassword As Long = &H1555&
    Const ControlIDSysTabControl32 As Long = &H3020&
    
    Dim Ctrl As Office.CommandBarControl
    Dim hWnd As Long
    Dim hWndLockProject As Long
    Dim hWndPassword As Long
    Dim hWndConfirmPassword As Long
    Dim hWndOK As Long
    Dim hWndSysTabControl32 As Long
    Dim strCaption As String
    
    With aVBProject
        strCaption = .Name & " - Project Properties"
        With .VBE
            ' Find Project Properties dialog
            Set Ctrl = .CommandBars.FindControl(ID:=2578)
            ' Display Project Properties dialog
            Ctrl.Execute
            Set Ctrl = Nothing
        End With
    End With
    
    ' Get hWnd for Project Properties dialog
    hWndProjectProperties = FindWindow(vbNullString, strCaption)
    If hWndProjectProperties = 0 Then
        Exit Sub
    End If

    ' Get hWnd for OK button in Project Properties dialog
    hWndOK = GetDlgItem(hWndProjectProperties, ControlIDOK)
    
    ' Get hWnd for Tab Control in Project Properties dialog
    hWndSysTabControl32 = GetDlgItem(hWndProjectProperties, ControlIDSysTabControl32)

    'Move to Protection tab
    SendMessage hWndSysTabControl32, TCM_SETCURFOCUS, 1, ByVal 0&

    ' Must reset hWndProjectProperties probably because tab changed.
    EnumChildWindows ByVal hWndProjectProperties, AddressOf EnumChildProc, ByVal 0
    
    ' Get hWnd for Password Edit control in Project Properties dialog
    hWndPassword = GetDlgItem(hWndProjectProperties, ControlIDPassword)
    
    ' Get hWnd for Confirm Password Edit control in Project Properties dialog
    hWndConfirmPassword = GetDlgItem(hWndProjectProperties, ControlIDConfirmPassword)
    
    ' Get hWnd for Lock Project checkbox control in Project Properties dialog
    hWndLockProject = GetDlgItem(hWndProjectProperties, ControlIDLockProject)

    ' Lock project for &viewing
    SendMessage hWndLockProject, BM_SETCHECK, BST_CHECKED, 0

    ' &Password
    SendMessage hWndPassword, EM_REPLACESEL, vbTrue, ByVal strPassword

    ' &Confirm password
    SendMessage hWndConfirmPassword, EM_REPLACESEL, vbTrue, ByVal strPassword

    'OK button
    SetFocusAPI hWndOK
    SendMessage hWndOK, BM_CLICK, 0&, 0&
    
End Sub

Function EnumChildProc(ByVal hWnd As LongPtr, ByVal lParam As Long) As Long
    hWndProjectProperties = hWnd
    ' Do not recurse
    EnumChildProc = 0
End Function

Function HVL_GetFile_Dialog(Optional DialogTitle As String, _
                            Optional InitDirectory As String, _
                            Optional Filter As String, _
                            Optional InitView As Office.MsoFileDialogView = msoFileDialogViewDetails) As String

    ' Filter: e.g. "Data bases, *.mdb; *.accdb"

    Dim Filter_Arr As Variant
    Dim ViewType   As Office.MsoFileDialogView

    With Application.FileDialog(msoFileDialogFilePicker)
        .InitialView = InitView
        .AllowMultiSelect = False
         
         If DialogTitle <> vbNullString Then .Title = DialogTitle
         
         If Dir(InitDirectory, vbDirectory) <> vbNullString Then
           .InitialFileName = InitDirectory
         Else
           .InitialFileName = CurDir
         End If
         
         If Filter <> vbNullString Then
            Filter_Arr = Split(Filter, ",")
           .Filters.Add Trim(Filter_Arr(0)), Trim(Filter_Arr(1)), 1
         End If
         
         If .Show = True Then
             HVL_GetFile_Dialog = .SelectedItems(1)
         Else
             HVL_GetFile_Dialog = vbNullString
         End If
         
    End With

End Function

Function HVL_Get_PassWord()

    Dim Pass1 As String
    Dim Pass2 As String

    Pass1 = InputBox("Enter VBproject password:", "Lock VBroject")
    If Pass1 = vbNullString Then GoTo No_Password
    
    Pass2 = InputBox("Caution: If you loose or forget the password," & vbCr & _
                     "it cannot be recovered. It is advisable to keep" & vbCr & _
                     "a list of passwords and their corresponding" & vbCr & _
                     "workbook names in a safe place." & vbCr & _
                     "(Remember that passwords are case-sensitive.)" & vbCr & vbCr & _
                     "Confirm VBproject password:", _
                     "Lock VBproject")
    If Pass2 = vbNullString Then GoTo No_Password
    
    If Pass1 <> Pass2 Then
       MsgBox "Confirmation password is not identical!", vbCritical, "Error"
       GoTo No_Password
    End If
    
    HVL_Get_PassWord = Pass1
    
    Exit Function
    
No_Password:
    HVL_Get_PassWord = vbNullString
    
End Function

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 pospich0815
Solution 2 Richard Hodges
Solution 3 double-beep
Solution 4 phuclv
Solution 5 janitha M
Solution 6 Xirema
Solution 7 Helge