Adding elements to C++ vector

560 Views Asked by At

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

3

There are 3 best solutions below

1
On BEST ANSWER

I change it and it work. it may not be the ideal and correct way but i will let it how it is.

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[len] = L""; //Wchar is compatible with LPWSTR
            wchar_t Text_content[len] = 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,  (LPWSTR) Text_name, len_name);
            GetWindowText(TextBox_content, (LPWSTR)Text_content, len_content);
            //verify if the texts are empty
            if (len_name == 1 || len_content == 1) {
                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_content); // set content of task in vector of ContentTask
                ComboBox_AddString(Combobox,Text_name); //set name in combobox
                SetWindowText(TextBox_Name, L""); //empty the textbox
                SetWindowText(TextBox_content, L""); //empty the textbox
                
                
                
            }

        }
5
On

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
        }           
    }
0
On

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...