Как разделить программу на модули си

Я пишу программу на С ++, которая имеет две функции, которые могут работать совершенно независимо друг от друга. Поэтому я хочу разбить их на две программы.

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

Я знаю, что это глупый вопрос, но я не смог найти никакой документации по этому вопросу.

Если код необходим, попросите его, и я опубликую его.

РЕДАКТИРОВАТЬ:

Функциями, которые могут работать независимо, являются make_video () и delete_video ()
Пожалуйста, имейте в виду, что это далеко не сделано.

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct config_t< std::string sql_host; //mysql host std::string sql_user; //mysql user std::string sql_pass; //mysql password std::string sql_db; //zoneminder database name std::string sql_ev_zm; //zoneminder events table std::string sql_ev_vid; //video events table std::string sql_ev_videxp; //video events expiration table std::string sql_mon; //zm monitors table std::string dir_ev; //Zoneminder events directory std::string dir_vid; //manager videos directory std::string dir_ram; //Ramfs mount directory std::string ram_size; //ramfs size >; int is_dir(const char *pathname) < struct stat info; if( stat( pathname, else if( info.st_mode else return 0;>// trim from start (in place) static inline void ltrim(std::string s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); > // trim from end (in place) static inline void rtrim(std::string s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); > // trim from both ends (in place) static inline void trim(std::string ltrim(s); rtrim(s); >// trim from start (copying) static inline std::string ltrimmed(std::string s) < ltrim(s); return s; >// trim from end (copying) static inline std::string rtrimmed(std::string s) < rtrim(s); return s; >// trim from both ends (copying) static inline std::string trimmed(std::string s) < trim(s); return s; >bool DirectoryExists ( const char* path ) < if( path == NULL )return false; DIR *d; d = opendir(path); if (d)< closedir(d); return true; >return false; > std::ifstream::pos_type filesize(const char* filename) < std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary); return in.tellg(); >bool mount_ramfs(config_t *conf)< return false; >bool make_video(config_t *conf, std::string path = «», int depth = 0)< try< sql::mysql::MySQL_Driver *driver; sql::Connection *con; sql::Statement *stmt; sql::ResultSet *res; driver = sql::mysql::get_mysql_driver_instance(); con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass); stmt = con->createStatement(); stmt->execute(«USE » + conf->sql_db); std::string query = «SELECT Id, MonitorId, StartTime, EndTime, Length, Frames FROM » + conf->sql_ev_zm + » WHERE EndTime IS NOT NULL LIMIT 10″; //select a bunch of events for processing, EndTime NOT NULL means that the event is complete and not corrupted //syslog (LOG_DEBUG, «Mysql Query: %s», query.c_str()); res = stmt->executeQuery(query);// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() — INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1 // SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE «%2015-11-18%» and MonitorId = 56 // conf.dir_ev + «/» + MonitorId + «/» + todir(StartTime) while (res->next()) < int monitor = res->getInt(«MonitorId»); std::string start_time = res->getString(«StartTime»); std::string end_time = res->getString(«EndTime»); int lenght = res->getInt(«Length»); int frames = res->getInt(«Frames»); //Get event directory form table data; the dir structure is id/YY/MM/DD/HH/mm/ss/ char sttm[60] = <>; std::strcpy(sttm, start_time.c_str()); char * tkn = (char*)malloc(60); std::stringstream pathSS; pathSS dir_ev while (tkn != NULL) < pathSS std::string src = pathSS.str(); pathSS.clear();pathSS dir_vid pathSS dir_vid + path; syslog (LOG_DEBUG, «%s», cmd.c_str()); std::system(cmd.c_str()); cmd = «tar -zcf » + conf->dir_vid + path + «/» + dirlist[i] +».tar.gz » + conf->dir_ev + path + «/» + dirlist[i]; syslog (LOG_DEBUG, «%s», cmd.c_str()); std::system(cmd.c_str()); cmd = «rm -rf » + conf->dir_ev + src + «*»; syslog (LOG_DEBUG, «%s», cmd.c_str()); std::system(cmd.c_str());*/ try< //insert new row in videos table pathSS << «INSERT INTO » sql_ev_vid execute(pathSS.str()); pathSS.clear(); //delete non existing event pathSS << «DELETE FROM » sql_ev_zm > delete res; delete stmt; delete con; > catch(sql::SQLException syslog (LOG_ERR, «Mysql Exception: %s, ERRNO %i, MySQL State: %s», e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str()); exit(EXIT_FAILURE); >return true; > bool delete_video(config_t *conf)< try< sql::mysql::MySQL_Driver *driver; sql::Connection *con; sql::Statement *stmt; sql::ResultSet *res; sql::ResultSet *subres; driver = sql::mysql::get_mysql_driver_instance(); con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass); stmt = con->createStatement(); stmt->execute(«USE » + conf->sql_db); std::string query = «SELECT monitor, recording_days FROM » + conf->sql_ev_videxp + » WHERE 1″; //syslog (LOG_DEBUG, «Mysql Query: %s», query.c_str()); res = stmt->executeQuery(query);// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() — INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1 // SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE «%2015-11-18%» and MonitorId = 56 // conf.dir_ev + «/» + MonitorId + «/» + todir(StartTime) while (res->next()) < int r_days = res->getInt(«recording_days»); //syslog (LOG_DEBUG, «Id: %i, Recording Days: %i», id, r_days); std::stringstream subQuerySS; subQuerySS << «SELECT id, file FROM » sql_ev_vid executeQuery(subQuery); while (subres->next()) < int subid = subres->getInt(«id»); std::string file = subres->getString(«file»); std::string cmd = «rm -f » + file; syslog (LOG_DEBUG, «%s», cmd.c_str()); std::system(cmd.c_str()); std::stringstream delQuerySS; delQuerySS << «DELETE FROM » sql_ev_vid execute(delQuery); > > delete res; delete subres; delete stmt; delete con; > catch(sql::SQLException syslog (LOG_ERR, «Mysql Exception: %s, ERRNO %i, MySQL State: %s», e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str()); exit(EXIT_FAILURE); >return true; > void signalHandler( int signum ) < syslog (LOG_NOTICE, «signal received (%i)», signum); closelog(); exit(signum); >int main(void) < /* Our process ID and Session ID */ pid_t pid, sid;/* Fork off the parent process */ pid = fork(); if (pid < 0) < exit(EXIT_FAILURE); >/* If we got a good PID, then we can exit the parent process. */ if (pid > 0) < std::ofstream pid_file; pid_file.open(«evmanager.pid», std::ofstream::trunc); if( pid_file.is_open())< pid_file exit(EXIT_SUCCESS); > /* Change the file mode mask */ umask(0); setlogmask (LOG_UPTO (LOG_DEBUG)); openlog («dt_event_manager», LOG_PID, LOG_DAEMON); syslog (LOG_NOTICE, «Program started by User %d», getuid ()); /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) < syslog (LOG_ERR, «SID Creation Failed»); exit(EXIT_FAILURE); >/* Change the current working directory */ if ((chdir(«/»)) < 0) < syslog (LOG_ERR, «Failed while Changing directory to /»); exit(EXIT_FAILURE); >/* Read Initial Configuration */ std::ifstream conf_file; std::string line; config_t conf; conf_file.open(«/etc/zm/evmanager.conf»); if( conf_file.is_open()) < while( std::getline(conf_file, line) )< if(line[0] == ‘#’)continue; std::istringstream is_line(line); std::string key; if( std::getline(is_line, key, ‘=’) )< std::string value; if( std::getline(is_line, value) )< trim(key); trim(value); if( key == «sql_host» )conf.sql_host = value; //mysql host else if( key == «sql_user» )conf.sql_user = value; //mysql user else if( key == «sql_pass» )conf.sql_pass = value; //mysql password else if( key == «sql_db»)conf.sql_db = value; //zoneminder database name else if( key == «sql_ev_zm» )conf.sql_ev_zm = value; //zoneminder events table else if( key == «sql_ev_vid» )conf.sql_ev_vid = value; //video events table else if( key == «sql_ev_videxp» )conf.sql_ev_videxp = value; //Zoneminder videos expiration directory else if( key == «sql_mon» )conf.sql_mon = value; //Zoneminder Monitors directory else if( key == «dir_ev» )conf.dir_ev = value; //Zoneminder events directory else if( key == «dir_vid» )conf.dir_vid = value; //Manager Videos directory else if( key == «dir_ram» )conf.dir_ram = value; //Ramfs mount dir else if( key == «ram_size» )conf.ram_size = value; //Ramfs size else< syslog (LOG_ERR, «Bad config readout»); exit(EXIT_FAILURE); >> > > > else< syslog (LOG_ERR, «Failed to open configuration file»); exit(EXIT_FAILURE); >/* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); /* Daemon-specific initialization goes here */ /* The Big Loop */ signal(SIGINT, signalHandler); syslog (LOG_INFO, «Daemon Started»); while (1) < make_video(); delete_video(); sleep(10); /* wait 10 seconds */ >exit(EXIT_SUCCESS); >

Читайте также:
Программы для диагностики автомобилей Киа соренто

Решение

Это большой вопрос. Я действительно много решаю эту проблему со студентами, так как я был наставником C ++.

Язык C++ с нуля | #35 Разделение программного кода на несколько файлов в c++

5. Язык Си: как разделить код на модули

В качестве примера, скажем, если это было вашим основным:

//main.cpp: #include #include «add.h» /// This comes in later 🙂 using namespace std; int main()

Теперь вы можете поместить несколько функций в один заголовочный файл, или каждая функция может иметь свой собственный заголовочный файл, но это ваш выбор Надеюсь, это поможет!

Другие решения

У вас есть несколько вариантов. Самое простое — создать несколько файлов, возможно, так:

shared_header.hpp shared_functionality.cpp prog_a.cpp prog_b.cpp

Затем программа A компилируется с источниками prog_a.cpp и shared_functionality.cpp, а программа B компилируется с источниками prog_b.cpp и shared_functionality.cpp. Все исходные файлы содержат заголовок, а prog_a.cpp и prog_b.cpp определяют свои собственные main функционировать каждый.

Источник: web-answers.ru

Модульное программирование на Си. Классы памяти и области действия переменных

Модульное программирование – это процесс разработки программы, состоящей из нескольких логически завершенных и взаимосвязанных единиц – модулей.

Классически, в Си, завершённый модуль – функция.

На более глобальном (макро) уровне,

модуль – текстовый файл программы, объединяющий некоторое количество функций, определений типов данных и переменных.

Использовать принцип модульного программирования на уровне файлов –значит:

— получить возможность разделить полный текст программы на несколько файлов;

— транслировать их независимо друг от друга;

— использовать как заготовки для других программ, т.е., фактически, применять объектный подход на более примитивном, низком или логическом уровне.

демонстрирует применение модульного подхода при программировании элементарной базы данных, где каждый файл – законченный элемент логической структуры программы.

Читайте также:
Программа для скрытой записи звука с ноутбука

Изменяем наполнение модулей – создаём новые варианты уже готовой задачи.

Пишем новый код – используем стандартные функции S в готовых модулях, например в menu.c.

Частным, часто используемым случаем модульного программирования является использование библиотечных функций, т.к. библиотеки представляют собой аналогичные Си-программы, независимо оттранслированные и помещенные в каталог библиотек.

В данной лекции, нас, прежде всего, будет интересовать, какими свойствами обладают переменные и функции, определенные в различных точках модуля – файла,

как они «узнают» о существовании друг друга, каким образом взаимодействуют между собой.

Для начала сформулируем ряд необходимых терминов:

МОДУЛЬ – файл Си-программы, транслируемый независимо от других файлов (модулей)

ОПРЕДЕЛЕНИЕ ПЕРЕМЕННОЙ ИЛИ ФУНКЦИИ – процесс создания программного эквивалента переменной или функции транслятором по их описанию в программе (трансляция во внутреннее представление)

Несколько отойдём от непосредственно модульного подхода в программировании и поговорим о необходимой составляющей этого процесса

определении переменных и функций в модулях и их взаимосвязи в многомодульном варианте программы.

Определение функции включает в себя её заголовок и тело.

Определение переменной – обычное контекстное определение и, возможно, её инициализация.

Рассмотрим подробнее на примерах:

int strcmp(char *s, char *d)

В определении функции:

— задан тип результата;

— задано имя функции;

— задан список формальных параметров и их типов;

— транслируется тело функции;

— для вызова функции из других модулей в текущем модуле может быть создана точка входа.

В определении переменной:

— задан тип переменной;

— задано имя переменной;

— определяется размерность и резервируется память. Размерность массивов в определении обязательно должна быть задана;

— производится инициализация памяти;

— для доступа к переменной из других модулей в текущем модуле может быть создана точка входа.

Читайте также:
Как удалить программу атом в ноутбуке

ОБЪЯВЛЕНИЕ ПЕРЕМЕННОЙ ИЛИ ФУНКЦИИ – информация транслятору о том, что указанные переменная или функция где-то определены, но неизвестны в данный момент транслятору

Например, определение размещается далее по тексту в текущем модуле или находится в другом модуле.

Переменная или функция при объявлении во внутреннее представление не переводятся, транслятору сообщается лишь факт их существования, имя и тип. Это необходимо для формирования правильного обращения к переменной или к функции.

extern int a, B[];

В объявлении переменной:

— задан тип переменной;

— задано имя переменной;

— запоминается факт наличия переменной с указанными именем и типом. Размерность массивов в объявлении может отсутствовать.

int strcmp();

int strcmp(char*, char*);

extern int strcmp();

extern int strcmp(char*, char*);

B объявлении функции:

— задается тип функции;

— задается имя функции;

— может быть задан список типов формальных параметров (прототип).

— запоминается факт наличия функции с указанными именем, результатом и, возможно, параметрами.

Различия между определением и объявлением принципиальны!

Похожие материалы

  • Типы данных. Определение структуры и структурированных переменных
  • Разнотипные переменные. Динамический и статический способы создания переменных
  • Работа со строками. Значение индекса начала повторяющегося фрагмента символов

Источник: vunivere.ru

1. Модульное программирование

С увеличением объема программы становится невозможным удерживать в памяти все детали. Естественным способом борьбы со сложностью любой задачи является ее разбиение на части. В C++ задача может быть разделена на более простые и обозримые с помощью функций, после чего программу можно рассматривать в более укрупненном виде – на уровне взаимодействия функций. Это важно, поскольку человек способен помнить ограниченное количество фактов. Использование функций является первым шагом к повышению степени абстракции программы и ведет к упрощению ее структуры.

Разделение программы на функции позволяет также избежать избыточности кода, поскольку функцию записывают один раз, а вызывать ее на выполнение можно многократно из разных точек программы. Процесс отладки программы, содержащей функции, можно лучше структурировать. Часто используемые функции можно помещать в библиотеки. Таким образом, создаются более простые в отладке и сопровождении программы.

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

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

Это уменьшает общий объем информации, которую необходимо одновременно помнить при отладке. Разделение программы на максимально обособленные части является сложной задачей, которая должна решаться на этапе проектирования программы.

Скрытие деталей реализации называется инкапсуляцией. Инкапсуляция является ключевой идеей как структурного, так и объектно-ориентированного программирования. Пример инкапсуляции – помещение фрагмента кода в функцию и передача всех необходимых ей данных в качестве параметров.

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

Модульность в языке C++ поддерживается с помощью директив препроцессора, пространств имен, классов памяти, исключений и раздельной компиляции (строго говоря, раздельная компиляция не является элементом языка, а относится к его реализации).

Источник: h-l-l.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru