Разбиение большого файла на отдельные модули в C/C++, Java и Python

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Этот подход обречен на провал и обычно требует переписывания с нуля.

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

Это не только упрощает нашу задачу, но и позволяет достичь

Теперь большой вопрос, как "сломать" не теоретически, а ПРОГРАММНО.

Мы увидим несколько различных типов таких единиц в популярных языках ‚Äã‚Äãтаких как C/C++, Python и Java.

C / C++

В иллюстративных целях

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

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

Программа:

FullLinkedList.c


// вставляем полный связанный список


# include "stdio.h >
# include "stdlib.h >


// ------------ -------------- ------
// Объявления - НАЧАЛО:
// ------ --------------------------


struct Узел;

struct Node * create_node ( int data);

void b_insert ( struct Node ** head, int data);

void n_insert ( struct Node ** head, int data, int pos);

void e_insert ( struct Node ** head, int data);

void display ( struct Node * temp);


// ------------ -------------- ------
// Объявления - КОНЕЦ:
// ------ --------------------------


int main ()

{

struct Node * head = NULL;


int ch, data, pos;


printf ( " Связанный список: " );

while (1) {

printf ( "1.Insert at Beginning" );

printf ( "2.Insert в N-й позиции" );

printf ( "3.Insert В конце" );

printf ( "4.Display " );

printf ( "0.Exit " );

printf ( "Введите ваш выбор :" );

scanf ( "% d" , & ch);


переключатель (ch) {

case 1:

printf ( "Введите data:" );

scanf ( "% d" , & данные);

b_insert (& head, data);

break ;


case 2:

printf ( "Введите data:" );

scanf ( "% d" , & данные);


printf ( " Введите позицию: " );

scanf ( "% d" , & pos);

n_insert (& head, data, pos);

break ;


case 3:

printf ( "Введите data:" );

scanf ( "% d" , & данные);

e_insert (& head, data);

break ;


case 4:

< класс кода ="неопределенные пробелы"> отображение (заголовок);

break ;


case 0:

< класс кода ="неопределенные пробелы"> <код класс ="ключевое слово полужирный" > return 0;


по умолчанию :

printf ( "Неверный выбор" );

}

}

}


// ---------------- ---------- ------
// Определения - НАЧАЛО:
// --------------


struct Node {

int < класс кода = "простой" > данные;

struct Node * next;

};


struct Node * create_node ( int данные)

{

struct Node * temp

= ( struct Node *)

malloc ( sizeof ( struct Node));

temp- > данные = данные;

temp- > следующий = ПУСТО;


return temp;

}


void b_insert ( struct Node ** head, int данные)

{

struct Node * new_node = create_node (data);


new_node- > следующий = * голова;

* head = new_node;

}


void n_insert ( struct Node ** head, int data, int pos)

{

if (* head == NULL) {

b_insert (head, data);

return ;

}


struct Node * new_node = create_node (data);


struct Node * temp = * head;


для ( int i = 0; i

temp = темп- > следующий;


new_node- > следующий = темп- > следующий;

temp- > следующий = новый_узел;

}


void e_insert ( struct Node ** head, int данные)

{

if (* head == NULL) {

b_insert (заголовок, данные);

return ;

}


struct Node * temp = * head;


в то время как (temp- > next! = NULL)

temp = temp- > следующий;


struct Node * new_node = create_node (data);

temp- > следующий = новый_узел;

}


void display ( struct Node * temp)

{/code>

printf ( "Элементы:" );

while (temp! = NULL) {

printf ( "% d" , темп->данные);

temp = temp- > следующий;

}

printf ( " " );

}


// ------ --------------------------
// Определения - КОНЕЦ
// --------------------- -----------

Компиляция кода: мы можем скомпилировать приведенную выше программу:

 gcc linkedlist.c -o linkedlist 

И это работает!

Основные проблемы в приведенном выше коде:
Мы уже видим основные проблемы с программой, с кодом не так просто работать ни индивидуально, ни в группе.

Если кто-то хочет работать с вышеперечисленным программа, то некоторые из многих проблем, с которыми сталкивается человек:

  1. Нужно просмотреть полный исходный файл. для улучшения или улучшения некоторых функций.
  2. Невозможно легко повторно использовать программу в качестве основы для других проектов.
  3. Код очень загроможден и совсем не привлекателен, что очень затрудняет навигацию по коду.

В случае группового проекта или крупных программ описанный выше подход гарантированно приведет к увеличению общих затрат, энергии и количества отказов.

Правильный подход:

Мы видим, что эти строки начинаются в каждой программе C/C++, которая начинается с "#include".
Это означает, что включать все функции, объявленные в заголовке "библиотеки" (файлы .h) и, возможно, определенные в файлах library.c / cpp .

Эти строки предварительно обрабатываются во время компиляции.

Мы можем вручную попытаться создать такую библиотеку для наших собственных целей.

Важные вещи, которые следует помнить :

  1. Файлы ".h" содержат только объявления прототипов (таких как функции, структуры) и глобальные переменные.
  2. Файлы ".c/.cpp" содержат фактическую реализацию (определения объявлений в файлах заголовков).
  3. При компиляции всех исходных файлов убедитесь, что несколько определений одной и той же функции, переменная и т. д. не существуют для одного и того же проекта. (ОЧЕНЬ ВАЖНО)
  4. Используйте статические функции, чтобы ограничить себя файлом, в котором они объявлены.
  5. Используйте ключевое слово extern , чтобы использовать переменные, на которые ссылаются внешние файлы.
  6. При использовании C++ будьте осторожны с пространствами имен, всегда используйте namespace_name::function(), во избежание конфликтов.
  7. Разбивая программу на более мелкие коды:
    Изучив приведенную выше программу, мы видим, как эту большую программу можно разделить на подходящие маленькие части и затем легко обрабатывается.

    Вышеупомянутая программа по существу имеет 2 основные функции:
    1) Создание, вставка и сохранение данных в узлах.
    2) Отображение узлов


    Таким образом, я могу разделить программу таким образом, чтобы:
    1) Главный файл был > Драйвер программы, Nice Wrapper из Insertion Modules и где мы используем дополнительные файлы.
    2) Вставить - > Настоящая реализация лежит здесь.

    С учетом упомянутых важных моментов программа делится на:

    linkedlist.c - > Содержит программу-драйвер
    insert.c - > Содержит код для вставки

    linkedlist.h - > Содержит необходимые объявления узлов
    insert.h - > Содержит необходимые объявления вставки узлов

    В каждом заголовочном файле мы начинаем с:

     #ifndef FILENAME_H #define FILENAME_H Declarations ... #endif 

    Причина, по которой мы пишем наши объявления между #ifndef, #define и #endif, , состоит в том, чтобы предотвратить множественные объявления идентификаторов, таких как типы данных, переменные и т. д., когда вызывается один и тот же заголовочный файл. в новом файле, принадлежащем тому же проекту.

    Для этого примера программы:

    insert.h - > Содержит объявление узла вставки, а также объявление самого узла.

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

    connectedlist.h  – > Вспомогательный файл, содержащий объявления Node и его Display, которые должны быть включены в файлы, которые их используют.


    insert.c - > Включите объявление узла с помощью #include "connectedlist.h", которое содержит объявление, а также определения всех других методов, объявленных в файле insert.h.

    connectedlist.c - > Простая обертка, содержащая бесконечный цикл, предлагающий пользователю вставить целочисленные данные в нужные позиции, а также содержащий метод, отображающий список.

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

    Принимая во внимание вышеизложенное, вы должны тщательно разделить на подходящие подпрограммы.

    linkedlist.h


    // connectlist.h


    # ifndef LINKED_LIST_H
    # определить LINKED_LIST_H


    struct Node {

    int data;

    struct Node * next;

    };


    void display ( struct Node * temp);


    # endif

    insert.h


    // insert.h


    # ifndef INSERT_H
    #define INSERT_H


    struct Node;

    struct Node * create_node ( int data);

    void b_insert ( struct Node ** head, int data);

    void n_insert ( struct Node ** head, int data, int pos);

    void e_insert ( struct Node ** head, int data);


    # endif

    insert.c


    // insert.c


    # include "linkedlist.h"
    // " " поэтому препроцессор просматривает
    // текущий каталог и
    // файлы стандартной библиотеки позже.


    # include "stdlib.h >


    struct Node * create_node ( int данные)

    {

    struct Node * temp = ( struct Node *) malloc ( sizeof ( struct Node));

    temp- > данные = данные;

    temp- > следующий = ПУСТО;


    return temp;

    }


    void b_insert ( struct Node ** head, int данные)

    {

    struct Node * new_node = create_node (data);


    new_node- > следующий = * голова;

    * head = new_node;

    }


    void n_insert ( struct Node ** head, int data, int pos)

    {

    if (* head == NULL) {

    b_insert (head, data);

    return ;

    }


    struct Node * new_node = create_node (data);


    struct Node * temp = * head;


    для ( int i = 0; i

    temp = темп- > следующий;


    new_node- > следующий = темп- > следующий;

    temp- > следующий = новый_узел;

    <