1

Тема: how to create char* text List from vector <string>

Доброго дня

#include <iostream>
#include <vector>
#include <string>
using namespace std;
CreateTextList(LPSTR* texts, vector<string> strings, int col) 
{
    texts=new LPSTR[col];
    string buff;
    for (int i=0; i<col; i++)
    {
        buff=strings[i];
        texts[i]=new char[(int) buff.length()];
        strcpy (texts[i], buff.c_str());
    }
}
int main(int argc, char** argv)
{
    LPSTR* texts1;
    vector <string> vec;
    string temp;
    for (int i=0; i<100; i++)
    {
        temp="temp"+i;
        vec.push_back(temp);
    }
    CreateTextList(texts1, vec, 99);
    return 0;
}

Помилки компілятора немає, але після запуску "memory error "

2 Востаннє редагувалося koala (03.03.2021 15:41:30)

Re: how to create char* text List from vector <string>

1. LPSTR - це тип з Windows.h, а він не включений.
2. Дуже багато зайвих дій. Але, звісно, це не викличе помилку.
3. Єдине місце, де я бачу помилку - це копіювання в texts[i], тому що для збереження стрічки потрібно на один байт більше (останній символ '\0').

-        texts[i]=new char[(int) buff.length()];
+        texts[i]=new char[buff.length()+1];

4. Вся дія безглузда - ви виділяєте купу пам'яті і потім губите вказівник на неї, і нічого не виводите.

Подякували: Grecis1

3

Re: how to create char* text List from vector <string>

Ну я переписав код в цій формі і забув windows.h
Зробив заміну тепер працює.
А чому це безглуздо і як зробити нормально?

4

Re: how to create char* text List from vector <string>

Зробив так, усе працює. Змінив

- CreateTextList(LPSTR* texts, vector<string> strings, int col)
+ CreateTextList(LPSTR* &texts, vector<string> strings, int col)  

Це малося на увазі?
Це мені потрібно для створення купи елементів.
Скорочений код #2:

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class CWind
{
    public:
        HWND MainWindow;
        HWND CreateButton(LPSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            if(hwnd==0) return CreateWindow("button", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, MainWindow, hMenu, hInst, NULL);
              else return CreateWindow("button", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd, hMenu, hInst, NULL);
        }
        HWND CreateCombobox(LPSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            if(hwnd==0) return CreateWindow("combobox", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, MainWindow, hMenu, hInst, NULL);
              else return CreateWindow("combobox", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd, hMenu, hInst, NULL);
        }
        HWND CreateEdit (LPSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            if(hwnd==0) return CreateWindow("edit", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, MainWindow, hMenu, hInst, NULL);
              else return CreateWindow("edit", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd, hMenu, hInst, NULL);
        }
        HWND CreateListbox (LPSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            if(hwnd==0) return CreateWindow("list", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, MainWindow, hMenu, hInst, NULL);
              else return CreateWindow("list", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd, hMenu, hInst, NULL);
        }
        HWND CreateScrollbar (LPSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            if(hwnd==0) return CreateWindow("scrollbar", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, MainWindow, hMenu, hInst, NULL);
              else return CreateWindow("scrollbar", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd, hMenu, hInst, NULL);
        }
        HWND CreateStatic (LPSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            if(hwnd==0) return CreateWindow("static", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, MainWindow, hMenu, hInst, NULL);
              else return CreateWindow("static", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd, hMenu, hInst, NULL);
        }    
};

/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    switch(Message) {
        
        /* Upon destruction, tell the main thread to stop */
        case WM_DESTROY: {
            PostQuitMessage(0);
            break;
        }
        
        /* All other messages (a lot of them) are processed using default procedures */
        default:
            return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
}
CreateTextList(LPSTR* &texts, vector<string> strings, int col) 
{
    texts=new LPSTR[col];
    string buff;
    for (int i=0; i<col; i++)
    {
        buff=strings[i];
        texts[i]=new char[(int) buff.length()+1];
        strcpy (texts[i], buff.c_str());
    }
}

/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc; /* A properties struct of our window */
    HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
    MSG msg; /* A temporary location for all messages */

    /* zero out the struct and set the stuff we want to modify */
    memset(&wc,0,sizeof(wc));
    wc.cbSize         = sizeof(WNDCLASSEX);
    wc.lpfnWndProc     = WndProc; /* This is where we will send messages to */
    wc.hInstance     = hInstance;
    wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
    
    /* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszClassName = "WindowClass";
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
    wc.hIconSm         = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */

    if(!RegisterClassEx(&wc)) {
        MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, /* x */
        CW_USEDEFAULT, /* y */
        640, /* width */
        480, /* height */
        NULL,NULL,hInstance,NULL);

    if(hwnd == NULL) {
        MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
        return 0;
    }
    
    CWind w;
    
    w.MainWindow=hwnd;
    
    w.CreateStatic("text", 10, 10, 200, 20, hwnd, (HMENU)10000, hInstance);//first test

    LPSTR* texts1;
    vector <string> vec;
    string temp;
    for (int i=0; i<100; i++)
    {
        temp="temp"+i;
        vec.push_back(temp);
    }
    CreateTextList(texts1, vec, 99);
    
    for (int i=0; i<60; i++)
    {
        w.CreateButton(texts1[i], 10, i*20, strlen(texts1[i])*10, 20, hwnd, (HMENU)10001+i, hInstance);
    }
    
    
    /*
        This is the heart of our program where all input is processed and 
        sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
        this loop will not produce unreasonably high CPU usage
    */
    while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
        TranslateMessage(&msg); /* Translate key codes to chars if present */
        DispatchMessage(&msg); /* Send it to WndProc */
    }
    return msg.wParam;
}

Вивід:
https://i.imgur.com/FnjxNZy.png

5

Re: how to create char* text List from vector <string>

Крім цього знайшов рішення "transform vector <string> to char* array"
https://gist.github.com/javagg/3714006
(у кого нема проксі код)

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

int main() {
    std::vector<std::string> symbols = {"IF1209", "IF1210"};
    std::vector<const char *> chars(symbols.size());

    std::for_each(symbols.begin(), symbols.end(), [](std::string& s) {
        std::cout << s << std::endl;
    });

    std::transform(symbols.begin(), symbols.end(), chars.begin(), std::mem_fun_ref(&std::string::c_str));

    std::for_each(chars.begin(), chars.end(), [](const char *s) {
        std::cout << s << std::endl;
    });

    return 0;
}

Хочу зрозуміти, що значить

std::for_each(chars.begin(), chars.end(), [](const char *s) {
        std::cout << s << std::endl;
    });
[](const char *s)

6

Re: how to create char* text List from vector <string>

w.CreateButton(vec[i].c_str(), 10, i*20, strlen(vec[i].length)*10, 20, hwnd, (HMENU)10001+i, hInstance);
Подякували: Grecis1

7

Re: how to create char* text List from vector <string>

https://en.cppreference.com/w/cpp/algorithm/for_each
https://en.cppreference.com/w/cpp/language/lambda

Подякували: Grecis1

8

Re: how to create char* text List from vector <string>

koala написав:
w.CreateButton(vec[i].c_str(), 10, i*20, strlen(vec[i].length)*10, 20, hwnd, (HMENU)10001+i, hInstance);
161    64    C:\Users\admin\Documents\TestPrj\main2.cpp    [Error] cannot convert 'std::basic_string<_CharT, _Traits, _Alloc>::length<char, std::char_traits<char>, std::allocator<char> >' from type 'std::basic_string<char>::size_type (std::basic_string<char>::)() const {aka unsigned int (std::basic_string<char>::)() const}' to type 'const char*'

Вибачте, я теж нашвидкоруч пишу (прибрали strlen):

161    31    C:\Users\admin\Documents\TestPrj\main2.cpp    [Error] invalid conversion from 'const char*' to 'LPSTR {aka char*}' [-fpermissive]

Це MinGW Dev-Cpp. Цей приклад не працював із самого початку тому довелося strcpy

LPSTR temp2;
    string buff;
    for (int i=0; i<60; i++)
    {
        buff=vec[i];
        temp2=new char[(int) buff.length()+1];
        strcpy (temp2, buff.c_str());
        w.CreateButton(temp2, 10, i*20, vec[i].length()*10, 20, hwnd, (HMENU)10001+i, hInstance);
    }

Вивід майже той самий (дещо змінилися неосмислені символи в кінці).
Напевно, тут щось не так:

vector <string> vec;
    string temp;
    for (int i=0; i<100; i++)
    {
        temp="temp"+i;
        vec.push_back(temp);
    }

І напевно, щось не так бо не визваний ресайз

9

Re: how to create char* text List from vector <string>

1) Працює тільки

w.CreateButton(temp2, 10, i*20, vec[i].length()*10, 20, hwnd, (HMENU)10001+i, hInstance);

наступний не працює:

w.CreateButton(temp2, 10, i*20, vec[i].length*10, 20, hwnd, (HMENU)10001+i, hInstance);
w.CreateButton(temp2, 10, i*20, (vec[i].length)*10, 20, hwnd, (HMENU)10001+i, hInstance);

помилка компілятора

166    51    C:\Users\admin\Documents\TestPrj\main2.cpp    [Error] invalid use of member (did you forget the '&' ?)

2) Визвав

vec.resize(100);

після нього вивід тільки першого CreateStatic() - кнопок немає.
P.S. А щоб не возитися з std, є щось у WinAPI готове? Я пишу статичну лібру на базі якої потім буду робити програми. Може готова така є (з вихідним кодом)?

10

Re: how to create char* text List from vector <string>

        HWND CreateButton(LPCSTR text, int x, int y, int w, int h, HWND hwnd, HMENU hMenu, HINSTANCE hInst)
        {
            return CreateWindow("button", text, WS_CHILD | WS_VISIBLE,
                                  x, y, w, h, hwnd==0?MainWindow:hwnd, hMenu, hInst, NULL);
        }
Подякували: Grecis1

11

Re: how to create char* text List from vector <string>

koala... я Вам дуже вдячний за витрачений час, це допомогло з c_str()

Grecis написав:

Вивід майже той самий (дещо змінилися неосмислені символи в кінці).

Ні, то я помилився, вивід не змінювався.
Допомогло

string temp="t";
temp="t"+temp;

Вивід при цьому правильний:
https://i.imgur.com/1DLDxxa.png
Зрештою, це був лише приклад, а не сама лібра, тому, основне питання вирішено.

Не виходить іще втиснути, прямо в клас, що було би зручно, WndProc:

34    20    C:\Users\admin\Documents\TestPrj\main3.cpp    [Error] cannot convert 'CWind::WndProc' from type 'LRESULT (CWind::)(HWND, UINT, WPARAM, LPARAM) {aka long int (CWind::)(HWND__*, unsigned int, unsigned int, long int)}' to type 'WNDPROC {aka long int (__attribute__((__stdcall__)) *)(HWND__*, unsigned int, unsigned int, long int)}'

Це із шаблону Dev-Cpp вирвано і спроба його вставити у мій клас

//class...
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
            switch(Message) {
                
                /* Upon destruction, tell the main thread to stop */
                case WM_DESTROY: {
                    PostQuitMessage(0);
                    break;
                }
                
                /* All other messages (a lot of them) are processed using default procedures */
                default:
                    return DefWindowProc(hwnd, Message, wParam, lParam);
            }
            return 0;
        }
        HWND CreateMainWindow(HINSTANCE hInstance)
        {
            WNDCLASSEX wc;
            memset(&wc,0,sizeof(wc));
            wc.cbSize         = sizeof(WNDCLASSEX);
            wc.lpfnWndProc     = WndProc; /* This is where we will send messages to */
            wc.hInstance     = hInstance;
            wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
            
            /* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
            wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
            wc.lpszClassName = "WindowClass";
            wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
            wc.hIconSm         = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */

            if(!RegisterClassEx(&wc)) {
                MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
                return 0;
            }
                MainWindow = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, /* x */hwnd
                    CW_USEDEFAULT, /* y */
                    640, /* width */
                    480, /* height */
                    NULL,NULL,hInstance,NULL);
                    
            return MainWindow;            
}
//...
//};

12

Re: how to create char* text List from vector <string>

Бо ваша WndProc - це нестатичний член класу, і, відповідно, ця функція має додатковий неявний параметр this.

Подякували: Grecis1

13

Re: how to create char* text List from vector <string>

Куди поставити this?

this->wc.lpfnWndProc     = WndProc;
34    10    C:\Users\admin\Documents\TestPrj\main3.cpp    [Error] 'class CWind' has no member named 'wc'

Вибачте, я не можу читати документацію, дуже важко. Чекатиму розгорнутої відповіді

14

Re: how to create char* text List from vector <string>

Grecis написав:

Куди поставити this?

Очевидно що нікуди. Ваша функція приймає this, а WndProc не має його приймати. Винесіть цю функцію з класу або хоча б зробіть її статичною.

Grecis написав:

Вибачте, я не можу читати документацію, дуже важко. Чекатиму розгорнутої відповіді

Ви все себе змусьте.

Подякували: Grecis1

15

Re: how to create char* text List from vector <string>

koala написав:
Grecis написав:

Куди поставити this?

Очевидно що нікуди. Ваша функція приймає this, а WndProc не має його приймати. Винесіть цю функцію з класу або хоча б зробіть її статичною.

Grecis написав:

Вибачте, я не можу читати документацію, дуже важко. Чекатиму розгорнутої відповіді

Ви все себе змусьте.

Не можу значить не можу, не можу!=не хочу. Я прямо прошу зробити за мене, бо я тугодум і невдаха, ту лібру, по якій я потім буду робити щось... на замовлення, щоб заробити на хліб (якщо ту лібру хтось не забере собі до цього).