Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60

О корректном завершении программ на с++

01.11.2025, 19:49. Показов 6532. Ответов 77
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток,

Изучая книгу Страуструппа "Язык программирования С++. Специальное издание", обратил внимание на следующее утверждение "При вызове exit() не будут вызваны деструкторы локальных переменных во всех функциях вверх по цепочке имевших место функциональных вызовов. Генерация и перехват исключений гарантируют корректное уничтожение локальных объектов. Вызов же exit() не позволяет корректно отработать всем функциям из цепочки вызовов. Поэтому лучше не ломать контекст вызова функций и просто сгенерировать исключение, а вопрос о том, что делать дальше, оставить обработчикам"

Допустим, в моей программе в месте, далеком по цепочке вызовов от main(), возникло событие, означающее что программа штатно закончило свою работу. Означает ли написанное выше что:
1) не стоит использовать библиотечные фукнции std::exit(), std::abort()
2) можно не заморачиваться с "правильным" завершением всех функций из цепочки вызовов, а достаточно сгенерировать исключение throw finish(), например. Разместить обработчик в main() и предусмотреть в нем вызов деструкторов глобальных объектов?

Хотелось бы понять и запомнить как правильно поступать при необходимости завершения сложных программ, от которых зависят в т.ч. другие процессы. Понятно, что простые учебные программы можно завершать как угодно.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.11.2025, 19:49
Ответы с готовыми решениями:

Корректное закрытие программы при завершении работы Windows
Моя программа при старте сворачивается в трей и периодически выполняет определенные операции. Окно...

Корректное завершение работы сокетов
У меня система работает на синхронных сокетах. Для приема данных создается отдельный поток...

Корректное завершение потока
В программе по нажатию на кнопку запускается поток. В случае если закрыть окно, из которого запущен...

77
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
02.11.2025, 11:28
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от ADnD Посмотреть сообщение
Я еще не дошел до изучения такой конструкции как [&], пока осваиваю "базу". Что такое [&]?
Lambda expressions
1
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
02.11.2025, 11:31
Цитата Сообщение от ADnD Посмотреть сообщение
Код исправил как вы посоветовали
если что, я не советовал кидаться что-то исправлять

Но если покрыто тестами - то ок
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6178 / 2873 / 1042
Регистрация: 01.06.2021
Сообщений: 10,522
02.11.2025, 13:35
Цитата Сообщение от Алексей1153 Посмотреть сообщение
где написано, что он мне нравится или не нравится? Я к нему равнодушен.
Я значит неверно понял твой смайлик. Тогда пиши буквами, чтобы не было таких недоразумений. Просто на форуме некоторые нездорово реагируют на goto, причем до такой степени, что мне кажется, что такое поведение уже следует добавить в МКБ-11.

Цитата Сообщение от Алексей1153 Посмотреть сообщение
почему же ?
потому что, если сравнить все методы, то в вышеописанном случае goto является самым эффективным - прямой переход с нулевыми накладными расходами, всего одна инструкция jmp. Для критичного к производительности кода именно goto нужно использовать. Использование флаговой переменной, возврат из функции, использование исключений, лямда с ранним возвратом и все прочие методы уступают в эффективности, хотя, не спорю, что некоторые из них по читаемости лучше.

Цитата Сообщение от Алексей1153 Посмотреть сообщение
Он мне ни разу не пригодился, ну и я даже не знаю, где бы он мог пригодиться
Это вообще не аргумент. Готов поспорить, что тебе, как и многим другим программистам, не пригодились более половины вещей, которые есть в С++, а то и возможно даже больше.

В С++ действительно есть вещи, от которых можно полностью отказаться, поскольку в языке есть более лучшая альтернатива. Но goto к ним не относится.

ADnD, как и предполагал, использование goto в твоем коде не оправдано. Нужно переписать функцию. Тут можно обойтись без goto и код станет более читаемым.
Кроме того, у тебя нарушена философия С++, а именно принцип единой ответственности, ибо у тебя одна функция делает абсолютно разные вещи. Лучшее решение - разделить на отдельные функции.
1
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
02.11.2025, 13:45
Цитата Сообщение от Royal_X Посмотреть сообщение
Но goto к ним не относится.
для него я пока что не нашёл применений. Но если вдруг - я воспользуюсь

Цитата Сообщение от Royal_X Посмотреть сообщение
не пригодились более половины вещей, которые есть в С++
перечисли навскидку, мне тоже интересно. Вдруг, я начну ими пользоваться
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6178 / 2873 / 1042
Регистрация: 01.06.2021
Сообщений: 10,522
02.11.2025, 14:07
Цитата Сообщение от Алексей1153 Посмотреть сообщение
перечисли навскидку, мне тоже интересно. Вдруг, я начну ими пользоваться
можешь задать ИИ вопрос, какие вещи почти не используются программистами С++ и он тебе всё распишет. Нейросеть неплохо обучена на кодах гитхаба, поэтому он лучше меня перечислит все эти вещи. Но нужно спросить именно про актуальные вещи, а не про всякие deprecated, как register.
Или можно просто открыть cppreference и пробежаться по алфавитному списку, вот увидишь, что ты много чего не используешь... И речь даже не про самый свежачок из С++23 / С++26, но много вещей найдешь из С++11 - С++20, которые ты вообще не использовал.
0
1968 / 824 / 115
Регистрация: 01.10.2012
Сообщений: 4,855
Записей в блоге: 2
02.11.2025, 14:17
Цитата Сообщение от ADnD Посмотреть сообщение
Функция из тренировочной программы, которая ищет исходники программы на с++, анализирует на наличие директив #include, ищет заголовочные файлы, читает их и извлекает различную информацию, в данном случае о комментариях
Ну что return/continue никак не хуже goto - это ясно. Но некоторые принципиально избегают даже return/continue. Никогда не был с этим согласен, но надо признать: иногда получается красиво. Во всяком случае если, как у Вас, переходов слишком много - значит точно что-то не так. Как сделать лучше - тут разговор может получиться длинным, не знаю есть ли у Вас желание "идти эту степь"
0
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
02.11.2025, 14:18
нет, нейросеть меня не интересует.

Про новые стандарты то понятно, кое-то я оттуда посматриваю, но реально не использовал ещё.

Тут же речь про то, что давно есть в языке
0
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
02.11.2025, 14:38  [ТС]
Цитата Сообщение от Royal_X Посмотреть сообщение
ADnD, как и предполагал, использование goto в твоем коде не оправдано. Нужно переписать функцию. Тут можно обойтись без goto и код станет более читаемым.
Подсказать можете, как в моем случае лучше было бы написать? Выше Алексей1153 привел пример с лямбдой, я проверил - работает, goto не нужно, но общая струкутра кода осталась прежней. И, по моему мнению, читаемость осталась прежней.

Цитата Сообщение от Royal_X Посмотреть сообщение
Кроме того, у тебя нарушена философия С++, а именно принцип единой ответственности, ибо у тебя одна функция делает абсолютно разные вещи. Лучшее решение - разделить на отдельные функции.
Я правильно понимаю, речь о том, чтобы вынести в отдельную функцию этот кусок кода?
C++
1
2
3
4
5
6
7
    txt = headerFile;
    while (*txt)
    {
        while (*txt == ' ' || *txt == '\t' || *txt == '\n' || *txt == '\r') if (!*++txt) return;
        while (*txt != ' ' && *txt != '\t' && *txt != '\n' && *txt != '\r') if (!*++txt) break;
        headerInfo->words++;
    }
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6178 / 2873 / 1042
Регистрация: 01.06.2021
Сообщений: 10,522
02.11.2025, 14:49
Цитата Сообщение от ADnD Посмотреть сообщение
Подсказать можете, как в моем случае лучше было бы написать?
Типа так можно упростить код. Это просто скелет кода. Сам код лень писать) Тут уже видно, что каждая функция делает именно то, что написано в ее имени. Если код пишешь для себя, то можно даже так и оставить, если всё работает. Но он трудно читается, если ты пишешь для других людей.

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
class lexical_analizer 
{
private:
    void processSingleLineComment(char*& txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
    void processMultiLineComment(char*& txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
    
    void analyzeCommentsAndRows(char* txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
    void countWords(char* txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
public:
    void getInfoFromHeader(HeaderInfo* headerInfo, char* headerFile) 
    {
        headerInfo->commented = 0;
        headerInfo->words = 0;
        analyzeCommentsAndRows(headerFile, headerInfo);
        countWords(headerFile, headerInfo);
    }
};
1
1968 / 824 / 115
Регистрация: 01.10.2012
Сообщений: 4,855
Записей в блоге: 2
02.11.2025, 16:53
Цитата Сообщение от ADnD Посмотреть сообщение
Я правильно понимаю, речь о том, чтобы вынести в отдельную функцию этот кусок кода?
Для этого куска посмотрите std::isspace. Все гораздо хуже. Вы решаете все задачи "в лоб", каждую мелочь делаете сами, на месте. Так Вы быстро надорветесь, такой код трудно читать, понимать, контролировать. Нужны "инструменты" в виде готовых, проверенных ф-ций/классов.

Тут скользкий момент. С готовыми инструментами для char * в языке совсем не густо, лучше для std::string, хотя по-моему и там бедненько. Многие предпочитают не тратить времени на "допотопный" char *, это имеет свои плюсы/минусы. Лично мне не кажется что написать пяток-десяток хороших ф-ций - такая уж потеря времени, пользы больше.
2
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
02.11.2025, 19:48  [ТС]
Igor3D, Вы затронули очень интересные для меня вопросы:

Цитата Сообщение от Igor3D Посмотреть сообщение
Для этого куска посмотрите std::isspace. Все гораздо хуже. Вы решаете все задачи "в лоб", каждую мелочь делаете сами, на месте. Так Вы быстро надорветесь, такой код трудно читать, понимать, контролировать. Нужны "инструменты" в виде готовых, проверенных ф-ций/классов.
Я столкнулся с тем, что библиотечные функции заголовка <cctype> такие как std::isspace(), std::isalpha(), std::isalnum() ведут к вылетам когда встречаются кириллические символы. Работаю в кодировке 1251. При обработке стандартных ASCII-символов проблем нет, но как только встречается кириллица, неважно как: при консольном вводе, при чтении файла, я получаю результат:
Кликните здесь для просмотра всего текста

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

Цитата Сообщение от Igor3D Посмотреть сообщение
Тут скользкий момент. С готовыми инструментами для char * в языке совсем не густо, лучше для std::string, хотя по-моему и там бедненько. Многие предпочитают не тратить времени на "допотопный" char *, это имеет свои плюсы/минусы.
Я написал данную учебную программу в двух версиях:
1) с динамическими массивами char[] с обращением через char* и char**
2) со строками string

Сравнил производительность через std::chrono::high_resolution_clock и ужаснулся: одну и ту же папку char-версия обрабатывает за 21 мс, а std::string-версия за 77 мс. Хотя по комментариям из интернета они должны быть +/- равнозначны. Может я использую не те алгоритмы, но я пока только учусь. Сейчас char* мне кажется предпочтительным. При такой разнице в производительности, можно приучить себя к дисциплине и контролировать удаление объектов, которые я создавал при помощью операции new.
Изучал использование памяти обоих версий при помощи профилирования кучи Visual Studio, итоговый расход памяти в килобайтах на неразрешенные выделения в версии std::string (где нет ни одного new) даже выше чем в версии с char* и new + delete[]

Может ли использование функций WIN32 API привести к такому падению производительности при использовании std::string??? Например, этих:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
1) WINBASEAPI HANDLE WINAPI FindFirstFileA(_In_ LPCSTR lpFileName, _Out_ LPWIN32_FIND_DATAA lpFindFileData);
2) WINBASEAPI BOOL WINAPI FindNextFileA(_In_ HANDLE hFindFile, _Out_ LPWIN32_FIND_DATAA lpFindFileData);
3) WINBASEAPI _Must_inspect_result_ BOOL WINAPI ReadFile(
    _In_ HANDLE hFile,
    _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToRead,
    _Out_opt_ LPDWORD lpNumberOfBytesRead,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );


Цитата Сообщение от Igor3D Посмотреть сообщение
Лично мне не кажется что написать пяток-десяток хороших ф-ций - такая уж потеря времени, пользы больше.
Уже начал)))
Кликните здесь для просмотра всего текста
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
namespace utilities_for_char_packages
{
    // добавляет строку в динамический массив char[]
    // @param char***               указатель на расширяемый массив в куче
    // @param int*                  указатель на переменную с текущим размером массива
    // @param const char*       добавляемая строка
    void char_pushback(char***, int*, const char*);
 
    // объединяет две строки char* и возвращает первую строку
    // @param target        расширяемая строка
    // @param source        добавляемая строка
    char* cat(const char*, const char*);
 
    // сравнивает две строки РАЗНОЙ РАЗМЕРНОСТИ, адресуемые указателями char
    // критерий сравнения - идентичность последовательности символов до терминального нуля
    // символы после терминального нуля не учитываются
    // @param cFileName     Указатель на строку char[MAX_PATH]
    // @param sample            Указатель на строку char произвольной длины
    inline bool cmp_arr_ptr(const char* cFileName, const char* sample)
    {
        while (*cFileName == *sample)
        {
            cFileName++;
            sample++;
            if (*cFileName == '\0' && *sample == '\0') return true;
        }
        return false;
    }
}
0
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
02.11.2025, 19:51
Цитата Сообщение от ADnD Посмотреть сообщение
char-версия обрабатывает за 21 мс, а std::string-версия за 77 мс
варианты, почему так:

1) измерение производится в дебажной версии
2) что-то делается неэффективно
3) ещё что-нибудь

Но лучше сразу перейти на std::string_view, он прям создан для написания парсеров
1
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
02.11.2025, 19:51
Цитата Сообщение от ADnD Посмотреть сообщение
Я столкнулся с тем, что библиотечные функции заголовка <cctype> такие как std::isspace(), std::isalpha(), std::isalnum() ведут к вылетам когда встречаются кириллические символы.
С вашей стороны требуется чуть более внимательное чтение документации:
Like all other functions from <cctype>, the behavior of std::isalnum is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char:
C++
1
2
3
4
bool my_isalnum(char ch)
{
    return std::isalnum(static_cast<unsigned char>(ch));
}
2
фрилансер
 Аватар для Алексей1153
6454 / 5655 / 1129
Регистрация: 11.10.2019
Сообщений: 15,054
02.11.2025, 19:53
ADnD, std::string короткие строки (0...15) хранит на стеке, а дальше идёт в динамическую память
0
1968 / 824 / 115
Регистрация: 01.10.2012
Сообщений: 4,855
Записей в блоге: 2
02.11.2025, 23:45
Цитата Сообщение от ADnD Посмотреть сообщение
Я не стал разбираться проблема ли это конкретно моей системы: раз ошибка появилась у меня, значит может появиться и у другого пользователя, значит этими инструментами этой библиотеки я пользоваться не буду.
А что "буду"? Писать велосипед на каждую библиотечную ф-цию? Это не выход. Даже не гуглили сообщение об ошибке. Это не то место где сачковать, здесь нужно разбираться "до упора"
Цитата Сообщение от ADnD Посмотреть сообщение
Уже начал)))
Опять плоховато со стандартными средствами, по-моему все приведенные 3 ф-ции успешно ими решаются, без всяких великов. Напр нет никаких оснований городить "динамический массив" (вместо std::vector<char *>).
Цитата Сообщение от ADnD Посмотреть сообщение
Сравнил производительность..
Легкость и доступность контейнеров (std::string тоже контейнер) порождают массовые злоупотребления, появляется пагубная манера ляпать ими к месту и не к месту. Поэтому Ваше стремление к дисциплине одобряю. Все-таки сначала надо научиться писать вменяемый код (хоть с char * хоть с std::string, как хотите). Можно попробовать довести до ума фрагмент выше. Какие ф-ции там нужны? Какую будете писать первой?
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6178 / 2873 / 1042
Регистрация: 01.06.2021
Сообщений: 10,522
02.11.2025, 23:52
Цитата Сообщение от Алексей1153
Но лучше сразу перейти на std::string_view
+100500
0
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
03.11.2025, 19:10  [ТС]
Цитата Сообщение от Igor3D Посмотреть сообщение
А что "буду"? Писать велосипед на каждую библиотечную ф-цию? Это не выход. Даже не гуглили сообщение об ошибке. Это не то место где сачковать, здесь нужно разбираться "до упора"
Замечание принял. Буду внимательнее в таких ситуациях!

Цитата Сообщение от Igor3D Посмотреть сообщение
Все-таки сначала надо научиться писать вменяемый код (хоть с char * хоть с std::string, как хотите). Можно попробовать довести до ума фрагмент выше. Какие ф-ции там нужны? Какую будете писать первой?
Royal_X подсказал разделить на 5 функций:
Кликните здесь для просмотра всего текста
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
class lexical_analizer 
{
private:
    void processSingleLineComment(char*& txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
    void processMultiLineComment(char*& txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
    
    void analyzeCommentsAndRows(char* txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
    void countWords(char* txt, HeaderInfo* headerInfo) 
    {
        // code
    }
 
public:
    void getInfoFromHeader(HeaderInfo* headerInfo, char* headerFile) 
    {
        headerInfo->commented = 0;
        headerInfo->words = 0;
        analyzeCommentsAndRows(headerFile, headerInfo);
        countWords(headerFile, headerInfo);
    }
};


В начале я бы разделил свою функцию void lexical_analizer::getInfoFromHeader(HeaderInfo* headerInfo, char* headerFile) на 3:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
namespace                          // реализация
{
  void analyzeCommentsAndRows(char* txt, lexical_analizer::HeaderInfo* headerInfo);
  void countWords(headerFile, headerInfo);
}
namespace lexical_analizer                          // интерфейс
{
  void lexical_analizer::getInfoFromHeader(HeaderInfo* headerInfo, char* header[S][/S]File)
}


Далее постараюсь логически четче и проще структурировать код. Напишу что получится!

также определю функцию
Цитата Сообщение от DrOffset Посмотреть сообщение
inline bool my_isspace(char ch)
{
    return std::isspace(static_cast<unsigned char>(ch));
}
Добавлено через 2 часа 24 минуты

Вот что получилось. И правильно работает.
Кликните здесь для просмотра всего текста
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
namespace
{
    bool processSingleLineComment(lexical_analizer::HeaderInfo*, char*&);
    bool processMultiLineComment(lexical_analizer::HeaderInfo*, char*&);
    void analyzeCommentsAndRows(lexical_analizer::HeaderInfo*, char*);
    void countWords(lexical_analizer::HeaderInfo*, char*);
    inline bool my_isspace(char ch)
    {
        return std::isspace(static_cast<unsigned char>(ch));
    }
}
namespace lexical_analizer
{
    void getInfoFromHeader(HeaderInfo*, char*);
}
 
// @return      true если достигнут конец текста
bool processSingleLineComment(lexical_analizer::HeaderInfo* headerInfo, char*& txt)
{
    headerInfo->commented++;
    while (*txt != '\n') if (!*++txt) return true;
    return false;
}
 
// @return      true если достигнут конец текста
bool processMultiLineComment(lexical_analizer::HeaderInfo* headerInfo, char*& txt)
{
    for (;;)
    {
        headerInfo->commented++;
        while (*txt != '\n')
        {
            if (!*++txt) return true;
            if (*txt == '*')
            {
                if (!*++txt) return true;
                if (*txt != '/') continue;
                while (*txt != '\n') if (!*++txt) return true;
                return false;
            }
        }
        if (!*++txt) return true;
    }
}
 
void analyzeCommentsAndRows(lexical_analizer::HeaderInfo* headerInfo, char* txt)
{
    headerInfo->notCommented = 1;
    while (*txt)
    {
        if (*txt == '/')
        {
            if (!*++txt) return;
            if (*txt == '/')
            {
                if (::processSingleLineComment(headerInfo, txt)) return;
                txt++;
                continue;
            }
            else if (*txt == '*')
            {
                if (::processMultiLineComment(headerInfo, txt)) return;
                txt++;
                continue;
            }
        }
        if (*txt++ == '\n') headerInfo->notCommented++;
    }
}
 
void countWords(lexical_analizer::HeaderInfo* headerInfo, char* txt)
{
    while (*txt)
    {
        while (::my_isspace(*txt)) if (!*++txt) return;
        while (!::my_isspace(*txt)) if (!*++txt) break;
        headerInfo->words++;
    }
}
 
void lexical_analizer::getInfoFromHeader(HeaderInfo* headerInfo, char* headerFile)
{
    headerInfo->commented = 0;
    headerInfo->notCommented = 0;
    headerInfo->words = 0;
    ::analyzeCommentsAndRows(headerInfo, headerFile);
    ::countWords(headerInfo, headerFile);
}



!!!!!! При этом, моя изначальная версия работает быстрее!!!! Файл обрабатывался за 24 мс, стал за 34 мс !!!!! Накладные расходы на вызов функций???
0
1968 / 824 / 115
Регистрация: 01.10.2012
Сообщений: 4,855
Записей в блоге: 2
03.11.2025, 20:50
Цитата Сообщение от ADnD Посмотреть сообщение
Далее постараюсь логически четче и проще структурировать код. Напишу что получится!
Кратко изложите/сформулируйте какую задачу решает Ваш фрагмент (из кода это не вполне ясно). Это даст участникам темы возможность предложить свою версию/реализацию. Не бойтесь что Вас "уничтожат интеллектом", сравнение разных подходов интересно и полезно.
Цитата Сообщение от ADnD Посмотреть сообщение
Royal_X подсказал разделить на 5 функций:
Вполне нормальный способ, мы планируем ф-ционал так как мы бы хотели им пользоваться/видеть, так сказать "заходим с фасада". Но используется много подходов/приемов, обычно сочетание многих. Напр есть такой метод
Что здесь плохо? Почему выходит хреновато?
Мои соображения:

- while с инкрементом в конце цикла здесь явно не удачен, на каждый чих нужно проверять финальный null. Лучше цикл for (счетчик найдем через strlen)

- а нужны ли тут вообще какие-то циклы и пробеги по строке? Не обойтись ли типовыми ф-циями поиска подстроки (типа strstr), пусть они и бегают

- ну и главное
С текстом выгодно работать строка за строкой
Даже если с первого взгляда такой необходимости нет, она обычно выплывает. Чтобы потом не бегать с \n (что кстати не всегда верно). Общий алгоритм всегда такой: отгрыз строку - обработал - отгрыз следующую и.т.д. пока строки не кончились. Др словами читаем из исходного char* как из файла. Поэтому первой надо писать ф-цию получения строки, напр
C++
1
const char * TakeLine( const char *& ioSrc, int * oLen );
Заметим что выгодно иметь и др ф-ции "отгрызания", напр TakeWord
1
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
03.11.2025, 21:15  [ТС]
Igor3D, большое спасибо за помощь, вы действительно подсказываете и помогаете развиваться!

Фрагмент кода просматривает текст исходника с++, считает количество строк с комментариями, строк без комментариев и общее количество слов в тексте. Просто учебная программа

Я замерил производительность последней версии программы, с разделением void lexical_analizer::getInfoFromHeader(HeaderInfo* headerInfo, char* headerFile) на 5 функций и использованием std::isspace(char). Неприятно удивлен падением производительности. Время обработки файла увеличилось с 24 до 34 мс.

Причина в замене этого:
C++
1
2
while (*txt == ' ' || *txt == '\t' || *txt == '\n' || *txt == '\r') if (!*++txt) return;
while (*txt != ' ' && *txt != '\t' && *txt != '\n' && *txt != '\r') if (!*++txt) break;
на это:

C++
1
2
while (::my_isspace(*txt)) if (!*++txt) return;
while (!::my_isspace(*txt)) if (!*++txt) break;
0
19497 / 10102 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
03.11.2025, 21:25
ADnD, надеюсь вы эти замеры не в отладочной версии делаете?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
03.11.2025, 21:25
Помогаю со студенческими работами здесь

Корректное завершение работы консольного приложения
Есть консольное приложение на Qt, которое запускает несколько потоков. Фактически в main я создаю...

Корректное освобождение памяти при принудительном завершении потока TThread
У меня в отдельном потоке выполняются некоторые вычисления. В процессе выполнения этой функции...

Потоки и их корректное завершение
Доброго времени суток! Необходима Ваша помочь. Есть поток, организованный так: void...

Корректное завершение
Когда закрываю окно QGraphicsView`а, процесс остается еще запущен и пишет еще что возникла ошибка....

Корректное завершение QCoreApplication
Добрый день! OC: Windows 7 Professional Qt: 5.7.0 Есть приложение QCoreApplication: int...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru