'Adding elements to C++ vector

I want to learn more about C++ coding, especially to design and create a desktop application.

To begin, I want to create a notification app where I can make a task by giving the task a name and content. For this, I use 2 vectors (name and content).

I initialize the vectors like this:

std::vector <LPWSTR> NameTask; 
std::vector <LPWSTR> ContentTask; 

After, I simply create a button to add the name and content into the vectors:

if (wmId == ID_BUTTON) {
    //local variables (only for the Button event)
    int len_name = GetWindowTextLength(TextBox_Name) + 1; //give the lenght value of the text in the textbox
    int len_content = GetWindowTextLength(TextBox_content) + 1; //give the lenght value of the text in the textbox
    wchar_t Text_name[100] = L""; //Wchar is compatible with LPWSTR
    wchar_t Text_content[100] = L""; //Wchar is compatible with LPWSTR
            
    // get the text of the Text edit and put it in local variable name and content
    GetWindowText(TextBox_Name, Text_name, len_name);
    GetWindowText(TextBox_content, Text_content, len_content);
    //verify if the texts are empty
    if (wcslen(Text_name) == 0 || wcslen(Text_content) == 0) {
        MessageBox(hWnd, L"name and content can't be empty", L"MessageBox", MB_OK);
    }
    else {
        NameTask.push_back(Text_name); // set name of task in vector of NameTask
        ContentTask.push_back (Text_name); // set content of task in vector of ContentTask
        //ComboBox_AddString(Combobox, Text_name); // add the title of the task in the combotext
        //SetWindowText(TextBox_Name, L""); //empty the textbox
        SetWindowText(TextBox_content, NameTask.at(0)); // visualize first element of vector name
    }           
}

The problem that I have is that, when I add a new element to the vector, and then I go to visualize it, it always shows me the last element added. Even when I use SetWindowText(TextBox_content, NameTask.at(0));

And when I use another button to visualize the name and content, it gives a strange output:

left name and right content



Solution 1:[1]

The problem is that you are storing dangling pointers in your vectors. Your if block is allocating local arrays, then storing pointers to those arrays into the vectors. When the if block exits, the arrays are destroyed, but the vectors are still pointing at them.

You need to make a copy of the text data you are retrieving from your UI. You can use std::wstring to handle that.

Try something more like this:

struct Task
{
    std::wstring Name; 
    std::wstring Content; 
};

std::vector<Task> Tasks;

...

if (wmId == ID_BUTTON) {
    int len_name = GetWindowTextLength(TextBox_Name);
    int len_content = GetWindowTextLength(TextBox_content);

    if (len_name == 0 || len_content == 0) {
        MessageBox(hWnd, L"name and content can't be empty", L"MessageBox", MB_OK);
    }
    else {
        ++len_name;
        ++len_content;

        std::wstring Text_name(L'\0', len_name);
        std::wstring Text_content(L'\0', len_content);
            
        len_name = GetWindowText(TextBox_Name, &Text_name[0], len_name);
        Text_name.resize(len_name);

        len_content = GetWindowText(TextBox_content, &Text_content[0], len_content);
        Text_content.resize(len_content);

        Task task;
        task.Name = Text_name;
        task.Content = Text_content;
        Tasks.push_back(task);

        //ComboBox_AddString(Combobox, Text_name.c_str());
        //SetWindowText(TextBox_Name, L"");
        SetWindowText(TextBox_content, Text_name.c_str());
    }
}

...

// use Tasks[index].Name(.c_str()) and Tasks[index].Content(.c_str()) as needed...

Solution 2:[2]

I don't know what you really want to do. At first, i would change the wchar_t to std::wstring. This way you don't need to specify the size. But, here I have a sugestion

if (wmId == ID_BUTTON) {
        //local variables (only for the Button event)
        int len_name = GetWindowTextLength(TextBox_Name) + 1; //give the lenght value of the text in the textbox
        int len_content = GetWindowTextLength(TextBox_content) + 1; //give the lenght value of the text in the textbox
        std::wstring Text_name = L""; //Wchar is compatible with LPWSTR
        std::wstring Text_content = L""; //Wchar is compatible with LPWSTR
        
        // get the text of the Text edit and put it in local variable name and content
        GetWindowText(TextBox_Name, Text_name, len_name);
        GetWindowText(TextBox_content, Text_content, len_content);
        //verify if the texts are empty
        if (wcslen(Text_name) == 0 || wcslen(Text_content) == 0) {
            MessageBox(hWnd, L"name and content can't be empty", L"MessageBox", MB_OK);
        }
        else {
            NameTask.push_back(Text_name); // set name of task in vector of NameTask
            ContentTask.push_back (Text_name); // set content of task in vector of ContentTask
            //ComboBox_AddString(Combobox, Text_name); // add the title of the task in the combotext
            //SetWindowText(TextBox_Name, L""); //empty the textbox
            SetWindowText(TextBox_content, NameTask.at(0)); // visualize first element of vector name
        }           
    }

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 Remy Lebeau
Solution 2 George Victor