Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.71/35: Рейтинг темы: голосов - 35, средняя оценка - 4.71
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371

Оптимизация кода по получению информации об играх из файла

08.04.2023, 00:44. Показов 8157. Ответов 46
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всех приветствую. Мне нужно получить из lua файлов имена и другую информацию об играх. В принципе мой код работает,но если в папке 70-80 и более игр,ui зависает где-то на пару секунд. Я не представляю,что будет,если в папке будет 300 игр. Я понимаю,что возможно мне надо делать это в отдельном потоке,но я не умею работать с потоками в mfc,да и,на мой взгляд,это не нужно,главное оптимизировать код и тогда,на мой взгляд,тормоза уменьшатся. Суть в том,что в каждой папке с игрой мы парсим первые 15 строк из некоторых lua файлов (main.lua и main3.lua) для получения нужной информации (подпапки в играх нас не интересуют). Затем мы добавляем недостающие игры,т.е те игры,которые мы установили вручную,в CListBox,но этот код я не буду выкладывать,т.к,на мой взгляд,он не вызывает тормоза. Вообще,как мне кажется,наибольшие тормоза из этого вызывают регулярки. Если в них основная проблема,подскажите пожалуйста,как обойтись без них,или какую более быструю библиотеку использовать для регулярок. approveInfo - мап типа string,std:air<string,int> (тип я пишу примерно). Вот фрагмент кода класса,в котором показан парсинг строк из файлов. Заранее всех благодарю за помощь по оптимизации этого счастья.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
static CString getGamesDir() {
    TCHAR buff[MAX_PATH];
    ::GetModuleFileName(NULL, buff, sizeof(buff));
    CString baseDir = buff;
    baseDir = baseDir.Left(baseDir.ReverseFind(_T('\\')) + 1);
    return baseDir + L"\\games\\";
}static CString getGamesDir() {
    TCHAR buff[MAX_PATH];
    ::GetModuleFileName(NULL, buff, sizeof(buff));
    CString baseDir = buff;
    baseDir = baseDir.Left(baseDir.ReverseFind(_T('\\')) + 1);
    return baseDir + L"\\games\\";
}static CString getGamesDir() {
    TCHAR buff[MAX_PATH];
    ::GetModuleFileName(NULL, buff, sizeof(buff));
    CString baseDir = buff;
    baseDir = baseDir.Left(baseDir.ReverseFind(_T('\\')) + 1);
    return baseDir + L"\\games\\";
}
static void ListFilesGamInDirectory(LPCTSTR dirName, std::vector<std::pair<CString/*full path*/, CString/*name*/> >& filepaths)
{
    // Check input parameters
    ASSERT(dirName != NULL);
    // Clear filename list
    filepaths.clear();
    // Object to enumerate files
    CFileFind finder;
    // Build a string using wildcards *.*,
    // to enumerate content of a directory
    CString wildcard(dirName);
    wildcard += _T("*.*");
    // Init the file finding job
    BOOL working = finder.FindFile(wildcard);
    // For each file that is found:
    while (working)
    {
        // Update finder status with new file
        working = finder.FindNextFile();
        // Skip '.' and '..'
        if (finder.IsDots())
        {
            continue;
        }
        // Skip sub-directories
        if (finder.IsDirectory())
        {
            // Add file path to container
            filepaths.push_back(std::make_pair(finder.GetFilePath(), finder.GetFileName()));
            continue;
        }
    }
    // Cleanup file finder
    finder.Close();
}
static CString get_game_property(std::wstring property, std::wstring inp) //входной текст
{
    //Обработка отображения объектов сцены
    const std::wregex regex_name(L"\\$\\s*?" + property + L"\\s*?:\\s*?([^\\$]*?)\\$", std::regex_constants::icase);
    std::wsregex_iterator next(inp.begin(), inp.end(), regex_name);
    std::wsregex_iterator end;
    while (next != end) {
        std::wsmatch match = *next;
        if (match.size() == 2)
        {
            CString nameStr(match[1].str().data());
            nameStr = nameStr.Trim(); //триммируем
            return nameStr;
        }
        next++;
    }
    return CString();
}
void LauncherDialog::RescanInstalled()
{
    //int result =std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
    std::vector<std::pair<CString, CString> > filePathsAndNames;
    /*installedGameNameCache.clear();
    m_listInstalled.DeleteAllItems();*/
    ListFilesGamInDirectory(getGamesDir(), filePathsAndNames);
 
    for (int i = 0; i < filePathsAndNames.size(); i++)
    {
        //if (installedGameNameCache.count(filePathsAndNames[i].second) > 0) continue;
        CString string;
        FILE* fStream;
        bool have_file = false;
        if (PathFileExists(filePathsAndNames[i].first + L"\\main.lua"))
        {
            _tfopen_s(&fStream, filePathsAndNames[i].first + L"\\main.lua", L"rt,ccs=UTF-8");
            have_file = true;
        }
        else if (PathFileExists(filePathsAndNames[i].first + L"\\main3.lua"))
        {
            _tfopen_s(&fStream, filePathsAndNames[i].first + L"\\main3.lua", L"rt,ccs=UTF-8");
            have_file = true;
        }
        if (have_file && installedGameNameCache.count(filePathsAndNames[i].second) == 0)installedGameNameCache.insert(filePathsAndNames[i].second);
        if (have_file)
        {
            CStdioFile gameFile(fStream);
            CString game_date;
            CString game_name;
            CString game_name_en;
            CString game_author;
            CString game_author_en;
            CString game_description;
            CString game_language;
            CString game_version;
            const int MAX_STR_CNT = 15; //не больше этого количества строк от начала
            int curr_str = 0;
            while (gameFile.ReadString(string))
            {
                std::wstring buf = string.GetBuffer();
                //MessageBox(buf, L"Тест");
                if (game_date.IsEmpty()) game_date = get_game_property(L"date", buf);
                if (game_name.IsEmpty()) game_name = get_game_property(L"name\\(ru\\s*?\\)", buf);
                if (game_name_en.IsEmpty()) game_name_en = get_game_property(L"name", buf);
                if (game_author_en.IsEmpty()) game_author = get_game_property(L"author", buf);
                if (game_author.IsEmpty()) game_name = get_game_property(L"author\\(ru\\s*?\\)", buf);
                if (game_description.IsEmpty()) game_description = get_game_property(L"info", buf);
                if (game_language.IsEmpty()) game_language = get_game_property(L"lang", buf);
                if (game_version.IsEmpty()) game_version = get_game_property(L"version", buf);
                //Если игра уже установлена,обновляем только версию.
                if (approveInfo.count(filePathsAndNames[i].second+suffix) > 0 && !game_version.IsEmpty()) {
if(game_version !=m_listInstalled.GetItemText(approveInfo[filePathsAndNames[i].second + suffix].second, N_SUBITEM_LIST_VERSION))SetCell(m_listInstalled, game_version, approveInfo[filePathsAndNames[i].second + suffix].second, N_SUBITEM_LIST_VERSION);
string.ReleaseBuffer();
                    break;
                }
                else if (!game_date.IsEmpty() && !game_name.IsEmpty() && !game_description.IsEmpty() && !game_version.IsEmpty() && !game_author.IsEmpty() && !game_language.IsEmpty())
                {
                    AddNewGame(game_date, game_name, game_author, game_description, game_version, game_language, filePathsAndNames[i], m_listInstalled);
                    string.ReleaseBuffer();
                    break;
                }
                string.ReleaseBuffer();
                curr_str++;
                if (curr_str > MAX_STR_CNT) break;
            }
            //Игра не находится в списке скаченных и мы не нашли всей информации
            if (!approveInfo.count(filePathsAndNames[i].second) && (game_date.IsEmpty() || game_name.IsEmpty() || game_description.IsEmpty() || game_author.IsEmpty() || game_language.IsEmpty() || game_version.IsEmpty()))
            {
                AddNewGame(game_date, game_name.IsEmpty() ? game_name_en : game_name, game_author.IsEmpty() ? game_author_en : game_author, game_description, game_language, game_version, filePathsAndNames[i], m_listInstalled);
            }
            gameFile.Close();
        }
    }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.04.2023, 00:44
Ответы с готовыми решениями:

Оптимизация запроса по получению периода если дана дата
Всем привет! Дана таблица с записями (355к строк), в которой есть дата (dat) - начало действия этой строки (например, дата начала...

Оптимизация кода скрипта при большом объеме информации
Уважаемые друзья, нужна ваша помощь в оптимизации запроса, т.к. сервер не дает завершить выполнение скрипта, отдавая ошибку 504. Смысл...

Оптимизация программного кода (считывание информации с Edita в массивы )
Мне для программы нужно считать химическое уравнение с эдита, при этом нужно что бы даные разделялись по элементам, соответствующим им...

46
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
15.04.2023, 15:14  [ТС]
Студворк — интернет-сервис помощи студентам
Огромное Вам спасибо за помощь. Скорее всего я не буду вообще пользоваться регулярками,раз без них всё работает гораздо быстрее. Правда я не понял,что за конструкция:
C++
1
2
3
4
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch)
{
...
}
По поводу многострочных коментариев не беспокойтесь,т.к вообще,как я понимаю,всё расчитано так,что каждый тег находится в отдельной строке,поэтому,на мой взгляд,лучше читать файл построчно. Не знаю,буду ли я использовать вектор,т.к итерация по нему тоже занимает время,но всё равно огромное Вам спасибо за помощь.
0
118 / 86 / 35
Регистрация: 07.11.2022
Сообщений: 355
15.04.2023, 15:35
Цитата Сообщение от КАВ Посмотреть сообщение
не понял,что за конструкция:
ltrim удалить пробелы слева, встроенной функции нет, приходится изворачиваться.

Идет разделение по символу ':' , а после может остаться пробел
C++
1
$Author: Андрей Серегин aka Fazer$
перед Андрей.

в вашем коде есть подобное
Цитата Сообщение от КАВ Посмотреть сообщение
nameStr = nameStr.Trim(); //триммируем

Не по теме:

Добавлено через 7 минут

Цитата Сообщение от КАВ Посмотреть сообщение
Огромное Вам спасибо за помощь.
пожалуйста. четыре дня назад хотел ответить.
времени не было .

0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
15.04.2023, 20:43  [ТС]
Я имел ввиду почему мы в теле метода в этой конструкции открываем новую фигурную скобку. Я понимаю,если бы там был if,но тут его вроде нет.
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
15.04.2023, 20:47
Цитата Сообщение от КАВ Посмотреть сообщение
[](unsigned char ch)
{
...
}
КАВ, это тело лямбда-выражения
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
19.04.2023, 20:03  [ТС]
Ещё возник момент,над которым надо подумать,что после комментария,т.е строки "--" без кавычек может быть н пробелов. Также н пробелов может быть в начале строки. Тут,видимо,надо делать итерацию по символам в CString,т.к от регулярок я решил полностью отказаться.
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
25.04.2023, 16:39  [ТС]
В общем после моей оптимизации код стал быстрее где-то в раз 10-15. Если у кого есть идеи,как его ещё больше оптимизировать,пишите. Мне лично не нравится,что приходится прыгать с CString к wstring и обратно,но unordered_map не поддерживает CString. Также почему-то не удаётся удалить $ в конце строки. Если кто-то сообразит почему,буду благодарен,а то очень обидно,что почти всё работает,но есть одна засада.
0
118 / 86 / 35
Регистрация: 07.11.2022
Сообщений: 355
25.04.2023, 17:19
Цитата Сообщение от КАВ Посмотреть сообщение
unordered_map не поддерживает CString
интернет говорит, что поддерживает How do I implement a CString hash function for use with std::unordered_map?



Цитата Сообщение от КАВ Посмотреть сообщение
код стал быстрее где-то в раз 10-15. Если у кого есть идеи,как его ещё больше оптимизировать,пишите. .... Также почему-то не удаётся удалить $ в конце строки. Если кто-то сообразит почему,буду благодарен,а то очень обидно,что почти всё работает,но есть одна засада.
хорошо бы код показать. может кто-то пожелает в нем разобраться.
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
25.04.2023, 17:30
Цитата Сообщение от КАВ Посмотреть сообщение
но unordered_map не поддерживает CString
прекрасно поддерживает. Но ещё лучше , конечно, туда совать не CString, а std::string / std::wstring

Цитата Сообщение от КАВ Посмотреть сообщение
Мне лично не нравится,что приходится прыгать с CString к wstring и обратно
а ещё лучше - по возможности максимально избегать CString
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
25.04.2023, 20:51  [ТС]
Поддерживает-то поддерживает,но как написано в интернете там надо реализовать свою хеш функцию и другие вещи. Почему-то код не вставился,пробуем дубль 2. Надеюсь теперь мне смогут помочь. ������
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
static  void parseGameInfo(CString line,std::unordered_map<std::wstring, std::wstring>& props) {
    line.Trim(L" \t");
    if (line.GetLength() ==0 ||line[line.GetLength() - 1] != '$') return;
    CString comment = L"--";
    if (line.Mid(0, comment.GetLength()) != comment) return; //сравниваем подстроку,т.к поиск по всей строке занимает больше времени.
    line = line.Mid(comment.GetLength());
    line.TrimLeft(L" \t"); //Удаляем пробелы только слева,т.к справа мы их уже удаляли методом Trim.
    if (line[0] != '$') return; //Убедились,что начальные и конечные символы $ существуют.
    int valPos = line.Find(L":",1); //Нам нужно получить подстроку от символа $ до символа :,не включая его.
    if (valPos < 0) return;
    props[line.Mid(1, valPos-1).MakeLower().GetString()] = line.Mid(valPos+1,line.GetLength() - 1).TrimLeft(L" \t").GetString(); //Берём всю строку от :,кроме последнего символа,т.к он равен $
    //AfxMessageBox(line.Mid(1, valPos-1).GetString());
}
void LauncherDialog::RescanInstalled()
{
UINT64 result =std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
    std::vector<std::pair<CString, CString> > filePathsAndNames;
    std::unordered_map<std::wstring, std::wstring> props;
    /*installedGameNameCache.clear();
    m_listInstalled.DeleteAllItems();*/
    ListFilesGamInDirectory(getGamesDir(), filePathsAndNames);
        for (int i = 0; i < filePathsAndNames.size(); i++)
    {
        //if (installedGameNameCache.count(filePathsAndNames[i].second) > 0) continue;
        CString string;
        FILE* fStream;
        bool have_file = false;
        if (PathFileExists(filePathsAndNames[i].first + L"\\main.lua"))
        {
            _tfopen_s(&fStream, filePathsAndNames[i].first + L"\\main.lua", L"rt,ccs=UTF-8");
            have_file = true;
        }
        else if (PathFileExists(filePathsAndNames[i].first + L"\\main3.lua"))
        {
            _tfopen_s(&fStream, filePathsAndNames[i].first + L"\\main3.lua", L"rt,ccs=UTF-8");
            have_file = true;
        }
        if (have_file && installedGameNameCache.count(filePathsAndNames[i].second) == 0)installedGameNameCache.insert(filePathsAndNames[i].second);
        if (have_file)
        {
            CStdioFile gameFile(fStream);
            const int MAX_STR_CNT = 15; //не больше этого количества строк от начала
            int curr_str = 0;
            boolean gameWasAdded = false;
            while (gameFile.ReadString(string))
            {
                parseGameInfo(string, props);
                //Если игра уже установлена,обновляем только версию.
                if (approveInfo.count(filePathsAndNames[i].second+suffix) > 0 && props.count(L"version")>0) {
if(props[L"version"].c_str() != m_listInstalled.GetItemText(approveInfo[filePathsAndNames[i].second + suffix].second, N_SUBITEM_LIST_VERSION))SetCell(m_listInstalled, props[L"version"].c_str(), approveInfo[filePathsAndNames[i].second + suffix].second, N_SUBITEM_LIST_VERSION);
gameWasAdded = true;
                    break;
                }
                else if (props.count(L"date")>0 && props.count(L"name(ru)") > 0 && props.count(L"info") > 0 && props.count(L"version") > 0 && props.count(L"author(ru)") > 0 && props.count(L"lan") > 0)
                {
                    AddNewGame(props[L"date"].c_str(), props[L"name(ru)"].c_str(), props[L"author(ru)"].c_str(), props[L"info"].c_str(), props[L"version"].c_str(), props[L"lan"].c_str(), filePathsAndNames[i], m_listInstalled);
                    gameWasAdded = true;
                    break;
                }
                curr_str++;
                if (curr_str > MAX_STR_CNT) break;
            }
            //Игра не находится в списке скаченных и мы не нашли всей информации
            if (!gameWasAdded)
            {
                AddNewGame(props[L"date"].c_str(), props.count(L"name(ru)")>0 ? props[L"name(ru)"].c_str() : props[L"name"].c_str(), props.count(L"author(ru)") > 0 ? props[L"author(ru)"].c_str() : props[L"author"].c_str(), props[L"info"].c_str(), props[L"version"].c_str(), props[L"lan"].c_str(), filePathsAndNames[i], m_listInstalled);
            }
            gameFile.Close();
            props.clear();
        }
    }
    result = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - result;
    CString a;
    a.Format(L"%d", result);
AfxMessageBox(a);
}
 
void LauncherDialog::AddNewGame(CString date, CString name, CString author, CString description, CString version, CString language, std::pair<CString, CString> downloadPageAndInstallName, CListCtrl& games, CString sz, CString page)
{
    CString mark = L"Неизвестно";
    CString accComment = L"";
    if (approveInfo.count(downloadPageAndInstallName.second)) {
        accComment = approveInfo[downloadPageAndInstallName.second].first;
        //Приобразуем доступность игр.
        mark = approveInfo[downloadPageAndInstallName.second].second == 1 ? L"Неизвестно" : approveInfo[downloadPageAndInstallName.second].second == 2 ? L"Нет (не проходимо)" : approveInfo[downloadPageAndInstallName.second].second == 4 ? L"Нет" : approveInfo[downloadPageAndInstallName.second].second == 8 ? L"Частично" : L"Да";
    }
    int cnt = games.GetItemCount();
    int col = 0;
    SetCell(games, name, cnt, col++);
    SetCell(games, author, cnt, col++);
    SetCell(games, mark, cnt, col++);
    SetCell(games, accComment, cnt, col++);
    SetCell(games, version, cnt, col++);
    SetCell(games, sz, cnt, col++);
    SetCell(games, description, cnt, col++);
    SetCell(games, date, cnt, col++);
    SetCell(games, downloadPageAndInstallName.second, cnt, col++);
    SetCell(games, page, cnt, col++);
    SetCell(games, downloadPageAndInstallName.first, cnt, col++);
    //installedGameNameCache.insert(downloadPageAndInstallName.second);
    //networkGameDWPageAndName.push_back(downloadPageAndInstallName);
    //networkGameName.insert(downloadPageAndInstallName.second);
}
// This function set the text in the specified SubItem depending on the Row and Column values
void LauncherDialog::SetCell(CListCtrl& ctrl, CString value, int nRow, int nCol)
{
    if (nCol > 0)
    {
        //set the value of listItem
        ctrl.SetItemText(nRow, nCol, value);
    }
    else
    {
        //Fill the LVITEM structure with the values given as parameters.
        TCHAR     szString[256];
        wsprintf(szString, value, 0);
        LVITEM lvItem;
        //ZeroMemory(&lvItem, sizeof(LVITEM));
        lvItem.mask = LVIF_TEXT;
        lvItem.iItem = nRow;
        lvItem.pszText = szString;
        //free(szString);
        lvItem.iSubItem = nCol;
        ctrl.InsertItem(&lvItem);
    }
}
Добавлено через 19 минут
Надеюсь теперь мне смогут помочь,т.к код вставился. ������ Вопросы выше ещё актуальны. unordered_map поддерживает CString,но там есть несколько решений,чтобы эту поддержку добавить. Какое решение,Алексей,на Ваш взгляд лучше и куда лучше вставить этот код? Я,если честно,ранее с шаблонами в c++ не разу не работал,поэтому в решениях на stackoverflow мне многое непонятно,но Ваше решение для unordered_map я,наверное,использую. От CString я не смогу отказаться,т.к xml парсер и списки используют CString. К тому же там есть плюшки,которых нет в std::wstring. Единственное,я попытаюсь добавить поддержку CString для hashmap,главное найти хорошее решение для c++ 17 и выше.

Добавлено через 2 часа 19 минут
Так,с первым вопросом,вроде,разобрался. Нужно от длинны отнять 1 и отнять (valPos+1). Теперь хотелось бы получить ответ на остальные вопросы. Если Вы считаете,что мой код максимально оптимизирован,напишите пожалуйста об этом. Заранее всех благодарю за помощь.
0
118 / 86 / 35
Регистрация: 07.11.2022
Сообщений: 355
26.04.2023, 00:28
В функции parseGameInfo лишние телодвижения, можно проще.
Искать только три символа: первый '$', ':' и последний '$'.

Искать первый '$'. Если найден, то с позиции '$' искать ':' .Если успешно, следом за ':' искать последний '$' .
Если все позиции получены, вырезать ключ и значение, у значения удалить пробелы слева,
вставить ключ-значение в словарь.


Псевдокод
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void parseGameInfo(const CString & line,std::unordered_map<std::wstring, std::wstring>& props) {
 
        //   Найти первый знак доллара , начало ключа
          pos1 = line.Find("$");
           if (  )   // Если первый '$' найден 
             {
               pos2 =  line.Find(":"); // найти ':' , конец ключа 
                 if (   )     // Если  ':' найден 
                 {           
                    pos3  = line.Find("$");    // найти последний '$' -- конец значения
                     if ()  // Если пoследний '$' найден 
                     {
                           key = line.Mid(   ); // извлечь ключ
                           value = line.Mid(  ); // извлечь значение 
 
                           value.TrimLeft( );  // у значения  удалить пробел слева 
                          props[key]  =  value; // установить ключ-значение
                     }
                 }
             }
}
Маленький недочет был в моем последнем коде, нужно вырезать ключ, если значение найдено.
Строку где ключ вырезают, на условие вниз нужно было перенести
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
26.04.2023, 09:03
Цитата Сообщение от КАВ Посмотреть сообщение
добавить поддержку CString для hashmap
попробуй так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//#include <unordered_map>
//#include <string>
 
struct CString_hash
{
    size_t operator()(const CString& s) const noexcept
    {
        return std::hash<std::string_view>{}({s.GetString(), (size_t)s.GetLength()});
    }
};
 
void func()
{
    std::unordered_map<CString, CString, CString_hash> m;
 
    m["1"]="2";
    auto res=m.find("1");
}
Добавлено через 11 минут
аа, ну, если проект юникодный, то std::string_view надо заменить на std::wstring_view
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
26.04.2023, 18:44  [ТС]
Дело в том,что мы ищем ключ только если в строке есть комментарии и перед и после них может быть пробел или символ \t.4

Добавлено через 13 минут
Я вот тут подумываю,а не перенести ли мне всё с CString на std::wstring. Темболее,что,к примеру,mfcшная функция работы с item вроде позволяет использовать cstring. Только чтение файла и парсинг xml работает с CString. Я готов помучатся и переписать всё на wstring,т.к даже те функции,которые возвращают CString,не проблема,т.к мы можем просто вызывать GetString() и c_str соответственно. Но я хочу быть уверен,что после этого скорость работы моих функций и методов увеличится,а не наоборот - уменьшится. п.с Если Вам нетрудно,посмотрите пожалуйста мои изменения. Вдруг у Вас будут идеи,как ещё больше увеличить скорость работы программы,т.к Вы,как я понимаю,работаете с mfc. Конечно,текущая скорость меня почти устраивает,но может можно её ещё больше увеличить?
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
26.04.2023, 19:39
Цитата Сообщение от КАВ Посмотреть сообщение
Но я хочу быть уверен,что после этого скорость работы моих функций и методов увеличится,а не наоборот - уменьшится.
в большинстве случаев минимум - скорость не поменяется, если не делать лишних копирований

Цитата Сообщение от КАВ Посмотреть сообщение
но может можно её ещё больше увеличить
для этого нужно изучить и промерить проект. Но я этим сейчас не готов заниматься. Можешь прицепить проект в ZIP архиве. Кто-то, может быть, глянет
0
118 / 86 / 35
Регистрация: 07.11.2022
Сообщений: 355
26.04.2023, 20:04
Цитата Сообщение от КАВ Посмотреть сообщение
Дело в том,что мы ищем ключ только если в строке есть комментарии и перед и после них может быть пробел или символ \t.4
по моему не нужно проверять что строка это комментарий.
вы читаете не более 15 строк
Цитата Сообщение от КАВ Посмотреть сообщение
Code
1
const int MAX_STR_CNT = 15; //не больше этого количества строк от начала
и мала веротность, что в коде Lua в одной строке встретится комбинация '$' - ':' - '$'.

Добавлено через 11 минут
Если считаете, что такая проверка необходима, тогда конечно лучше её сделать.
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
26.04.2023, 23:49  [ТС]
Ну раз скорость не увеличится,тогда смысла парится,наверное,нет. Алексей,я не прошу Вас или кого-либо смотреть весь проект,т.к он большой (хотя в глубине души мне очень хотелось бы это). Я имел ввиду изменённый код,который я прислал сюда,не более того. Кстати что делает метод GetString у CString и c_str() у wstring? Я имею ввиду не влияют ли они на скорость работы программы?
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
27.04.2023, 09:11
Цитата Сообщение от КАВ Посмотреть сообщение
Ну раз скорость не увеличится,тогда смысла парится,наверное,нет
1) от замены класса сама по себе скорость не изменится, для этого нужна оптимизация.
2) Само собой, оптимизировать намного удобнее, если не будет постоянных конвертаций из одного класса в другой
3) для оптимизации смотреть на кусок кода обычно нет смысла (кроме очевидных косяков), нужно проект ковырять и замерять

Цитата Сообщение от КАВ Посмотреть сообщение
что делает метод GetString у CString
Цитата Сообщение от КАВ Посмотреть сообщение
c_str() у wstring
возвращают указатель на первый символ внутреннего массива строки

Цитата Сообщение от КАВ Посмотреть сообщение
Я имею ввиду не влияют ли они на скорость работы программы?
вернуть указатель - это быстрее, чем вернуть копию строки.
Но, вместе с тем, у CString используется COW и динамическая память, а фича std::wstring - SSO, то есть короткие строки могут лежать на стеке, а не в динамической памяти

поэтому, вот так напрямую сравнить сложно. Всё зависит от характера использования
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
27.04.2023, 15:28  [ТС]
1) от замены класса сама по себе скорость не изменится, для этого нужна оптимизация.
В данном случае,как я понимаю,может измениться,т.к мы меньше будем прыгать от CString к std::wstring и наоборот.
для оптимизации смотреть на кусок кода обычно нет смысла (кроме очевидных косяков), нужно проект ковырять и замерять
Ну я проверил,что именно эта часть проекта вызывает тормоза,когда много папок. После оптимизации тормоза уменьшились,но я хочу убедится,что в этой части я реально сделал всё,что мог,или наоборот чего-то не сделал. Может,к примеру,что-то можно оптимизировать в плане mfc или в работе со строками,поэтому я и прошу Вас посмотреть оптимизированный код. Может получится так,что Ваши советы я смогу применить и в других частях проекта.
возвращают указатель на первый символ внутреннего массива строки
А я думал,что он постоянно проводит конвертацию и возвращает отконвертированный результат,а он,всё-таки,возвращает готовый указатель.
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
27.04.2023, 15:37
Цитата Сообщение от КАВ Посмотреть сообщение
TCHAR buff[MAX_PATH];
    ::GetModuleFileName(NULL, buff, sizeof(buff));
тут ошибка - надо std::size(buff)

а сейчас передаётся в два раза бОльший размер, что, возможно, приводит к UB из-за порчи стека
0
17 / 5 / 0
Регистрация: 16.04.2016
Сообщений: 371
27.04.2023, 16:37  [ТС]
Огромное Вам спасибо. Я этого и не знал и проект делался до меня. А в каких случаях нужно использовать sizeof(buff)),а в каких - std::size(buff). В других частях проекта я это тоже поправлю. Что значит порча стека? Просто я слышал про утечки памяти,а про это слышу в первый раз. Если Вы ещё где-то найдёте проблемы,или у Вас будет идея,как увеличить скорость работы метода по добавлению игр,сообщите мне пожалуйста.
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,424
27.04.2023, 16:45
Цитата Сообщение от КАВ Посмотреть сообщение
А в каких случаях нужно использовать sizeof(buff)),а в каких - std::size(buff)
sizeof(buff) - возвращает размер объекта в байтах (в данном случае - размер автоматического массива buff)

std::size(buff) - вернёт размер автоматического массива в ЭЛЕМЕНТАХ (что и требуется для функции GetModuleFileName)

Добавлено через 4 минуты
Цитата Сообщение от КАВ Посмотреть сообщение
void LauncherDialog::RescanInstalled()
{
    //int result =std::chrono::duration_cast<std::chrono: :milliseconds>(std::chrono::high_resolut ion_clock::now().time_since_epoch()).cou nt();
    std::vector<std:air<CString, CString> > filePathsAndNames;
    ListFilesGamInDirectory(getGamesDir(), filePathsAndNames);
поскольку при каждом вызове вектор перенабивается заново, имеет смысл сделать вектор сделать глобальным (образно говоря. На самом деле - можно членом класса). А в этой точке делать ему clear()
Таким образом будет меньше реаллокаций. Если это место интенсивно используется, это может увеличить производительность.
Но если используется редко, то нет смысла в этом телодвижении
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.04.2023, 16:45

Литература по получению MD5 файла в C++ с CryptoApi
Помогите пожалуйста, требуется написать программу, которая выводит на экран хеш файла через CryptiApi. На сайте MSDN есть статейка: Example...

Оптимизация кода пакетного файла для создания бэкапов
Добрый день. Столкнулся с задачей: требуется оптимизировать создание бэкапов. деление на ежедневные, еженедельные и ежемесячные. Для...

Оптимизация методом Ньютона (нахождение точки минимума). Оптимизация кода
MATLAB только начал осваивать. Попытался реализовать нахождение точки минимума методом Ньютона для функции 2*X12 - X1*X2 + 3*X22 -...

Оптимизация кода. Замер времени выполнения части кода.
Доброе утро. Есть желание посмотреть сколько времени занимает выполнение какого-то блока кода/отдельной функции или процедуры/программы...

Алгоритм передачи информации в играх
Собрал простенькую игру компонентах IdTCPClient и IdTCPServer на делфи в крестики нолики. Можно играть ей на двух компьютерах используя...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Транслитерация текста с кириллицы на латиницу (вариант №2)
Maks 13.11.2026
Обновленная версия ранее созданной обработки. Добавлено: - Проверка исходного текста на кириллицу, через обращение к стандартной функции "ТолькоКириллицаВСтроке" из общего модуля. . .
Часы с термометром и праздничным календарем
yariko 12.11.2026
Сегодня мы рассмотрим как можно сделать отличные многофункциональные часы. Итак, поставим конкретную задачу: разработать часы с календарем, двумя термодатчиками, выводом поздравительных сообщений. . .
Транслитерация текста с кириллицы на латиницу (вариант №1)
Maks 11.11.2026
Решил облегчить жизнь себе и коллегам админам при создании электронных почтовых ящиков для пользователей, в результате написал обработку "Транслитерация текста" с кириллицы на латиницу, а в ней. . .
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru