Modular programming

Modular programming

1. Why modular programming?

A: if I were Party A, I would put forward my requirements to you. After a month, you finally wrote the code I wanted. However, if you write all the functions in a c file, do you think I will ask you for later maintenance? Impossible, because I understand your whole program framework, I will maintain it myself ------------ [the above is purely a joke]
*****We need to split the function and modularize it. In this way, there are not many things in our main function. With the increase of the project, we may need A team to complete the development. Everyone is responsible for different functions. For example, I need an input-output function. Then A is responsible for writing the input function and B is responsible for writing the output function. Finally, it can be called through the main function. This is convenient and efficient.

2. How to split the written program?

2.1 procedure decomposition

*****Put one The n sub functions in the c program are divided into one by one c Documents
Here is a demonstration of the program written last night:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 5
#define M 3
#define SIZE 3
//Describe a student's: name age three scores

typedef struct student
{
	char name[N];
	int age;
	float scores[M]i;

}Stu;
//Function function: realize the exchange of structures
//Parameter 1: structure 1
//Parameter 2: structure 2
//Function return value: void
void swap(Stu *pa,Stu *pb)
{
	Stu temp = {0};
	temp = *pa;
	*pa = *pb;
	*pb = temp;
}
//Function: find the total score
//Parameter 1: first address of array (with pointer)
//Parameter 2: number of array elements
//Function return value: total score
float sumScores(float pc[],int count)
{
	float sum = 0;
	int i;
	for(i = 0;i < count;i++)
		{
		sum = sum + pc[i];
		}
	return sum;
}
//Function function: encapsulate sub functions to realize output
//Parameter 1: structure first address (using pointer) Stu *pc
//Parameter 2: number of structures int count
//Function return value: void
void input(Stu *ps,int count)
{
	int i,j;
	for(i = 0;i < count;i++)
	{
		printf("please input the student name age scores:\n");
		scanf("%s",ps->name);
		scanf("%d",&ps->age);
		for(j = 0;j < M;j++)
		{
			scanf("%f",&ps->scores[j]);
		}
		ps++;
	}
}
//Function function: output
//Parameter 1: first address of structure
//Parameter 2: number of structures
//Function return value: void
void output(Stu *ps,int count)
{
	int i,j;
	for(i = 0;i < count;i++)
	{
		printf("%s ",ps->name);
		printf("%d ",ps->age);
		for(j = 0;j < M;j++)
		{
			printf("%.1f  ",ps->scores[j]);
		}
		ps++;
		printf("\n");
	}
}
//Function function: find the first address of the oldest person
//Parameter 1: structure first address Stu *ps
//Parameter 2: number of structures int count
//Function return value: Stu*
Stu * calPmaxAge(Stu *ps,int count)
{
	//Define a structure pointer to save the first address of the oldest person in the grade
	Stu *pMax = NULL;
	//Suppose the first is the first address of the oldest person
	pMax = ps;
	//Sequential comparison
	int i;
	for(i = 1;i < count;i++)
	{
		if(pMax->age < (ps+i)->age)
		{
			pMax = ps+i;
		}
	}
	return pMax;	
}
//Function function: sort by age
//Parameter 1: structure first address Stu *ps
//Parameter 2: number of structures int count
//Return value: void
void sortByAge(Stu *ps,int count)
{
	int i,j;
	for(i = 0;i < count-1;i++)
	{
		for(j = 0;j < count-1;j++)
		{
			if((ps+j)->age > (ps+j+1)->age)
			{
				//change of position
				swap(ps+j,ps+j+1);
			}
		}
	}
}
//Function function: sort by age
//Parameter 1: structure first address Stu *ps
//Parameter 2: number of structures int count
//Return value: void
void sortByName(Stu *ps,int count)
{
	int i,j;
	for(i = 0;i < count-1;i++)
	{
		for(j = 0;j < count-1;j++)
		{
			if(strcmp((ps+j)->name,(ps+j+1)->name) > 0)
			{
				//change of position
				swap(ps+j,ps+j+1);
			}
		}
	}
}
//Function function: sort according to the total score
//Parameter 1: structure first address Stu *ps
//Parameter 2: number of structures int count
//Return value: void
void sortBySumScores(Stu *ps,int count)
{
	int i,j;
	for(i = 0;i < count-1;i++)
	{
		for(j = 0;j < count-1-i;j++)
		{
			if(sumScores((ps+j)->scores,M) > sumScores((ps+j+1)->scores,M))
			{
				//change of position
				swap(ps+j,ps+j+1);
			}
		}
	}
}
int main(void)
{
	//Apply for a space as large as SIZE Stu
	//void *malloc(size_t size)
	//Function: apply for space
	//Parameter: size of space to be applied for
	//Return value: the first address of the successful application is returned successfully, and NULL is returned if it fails
	//Define a structure pointer variable to receive the return value of malloc
	int op;
	Stu *ps = NULL;
	Stu *pMax = NULL;
	ps = (Stu *)malloc(sizeof(Stu) *SIZE);
	//The space malloc applied for has no name, and only the first address is returned
	if(NULL == ps)
	{
		perror("malloc error");
		return -1;
	}
	while(1)
	{
		printf("Please enter options:\n");
		printf("1----------input\n");
		printf("2----------output\n");
		printf("3----------calPmaxAge\n");
		printf("4----------sortByAge\n");
		printf("5----------sortByName\n");
		printf("6----------sortBySumScores\n");
		printf("-1---------exit\n");
		scanf("%d",&op);
		if(-1 == op)
		{
			break;
		}
		switch(op)
		{
			case 1:
				input(ps,SIZE);
				break;
			case 2:
				output(ps,SIZE);
				break;
			case 3:
				pMax = calPmaxAge(ps,SIZE);
				printf("The first address of the oldest is%p\n",pMax);
				break;
			case 4:
				sortByAge(ps,SIZE);
				break;
			case 5:
				sortByName(ps,SIZE);
				break;
			case 6:
				sortBySumScores(ps,SIZE);
				break;
		}
	}
	//release
	//Parameter: the first address applied to the space
	free(ps);
	ps = NULL;
	//After the release, the space is released, but the value is still there
	return 0;
}

2.1.1 first look at the main function:

int main(void)
{
	//Apply for a space as large as SIZE Stu
	//void *malloc(size_t size)
	//Function: apply for space
	//Parameter: size of space to be applied for
	//Return value: the first address of the successful application is returned successfully, and NULL is returned if it fails
	//Define a structure pointer variable to receive the return value of malloc
	int op;
	Stu *ps = NULL;
	Stu *pMax = NULL;
	ps = (Stu *)malloc(sizeof(Stu) *SIZE);
	//The space malloc applied for has no name, and only the first address is returned
	if(NULL == ps)
	{
		perror("malloc error");
		return -1;
	}
	while(1)
	{
		printf("Please enter options:\n");
		printf("1----------input\n");
		printf("2----------output\n");
		printf("3----------calPmaxAge\n");
		printf("4----------sortByAge\n");
		printf("5----------sortByName\n");
		printf("6----------sortBySumScores\n");
		printf("-1---------exit\n");
		scanf("%d",&op);
		if(-1 == op)
		{
			break;
		}
		switch(op)
		{
			case 1:
				input(ps,SIZE);	//Input function
				break;
			case 2:
				output(ps,SIZE);//Output function
				break;
			case 3:
				pMax = calPmaxAge(ps,SIZE);//The first address of the structure storing the oldest student
				printf("The first address of the oldest is%p\n",pMax);
				break;
			case 4:
				sortByAge(ps,SIZE);//Sort by students' age
				break;
			case 5:
				sortByName(ps,SIZE);//Sort by student's name (string)
				break;
			case 6:
				sortBySumScores(ps,SIZE);//Sort according to the total score of three subjects
				break;
		}
	}
	//release
	//Parameter: the first address applied to the space
	free(ps);
	ps = NULL;
	//After the release, the space is released, but the value is still there
	return 0;
}

Through careful observation, we can find that the main function has been in an endless loop to judge the swatch statement. There are six sub functions in total. Next, we will split this long code into independent ones c documents.

2.1.2 split step 1: Customize header file

1. Create h file
My whole program is called malloc c. So I want to create a malloc in the current directory H documents.
The. h file includes five blocks: header file, macro definition, structure type definition, enumeration type definition and function declaration

Command: VI molloc h
As shown in the figure above, cut the header file, macro definition, structure type definition, enumeration and sub function declaration in the original function. It should be noted that after pasting the sub function declaration, you need to add a semicolon at the end
To avoid future problems h file is repeatedly called to generate errors, so it needs to be defined in h at the beginning of the document: if there is no definition h file, then define h file, defined at the end

#ifndef _MALLOC_H 	//	 If malloc is not defined H file
#define _MALLOC_H 	// Then define malloc H file
.....
#endif 				// End definition

Of the three statements h function name should be capitalized, where the dot is'‘ Underlined '' Replace.

#ifndef _MALLOC_H
#define _MALLOC_H
//1. Import function header file
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//2. Macro definition
#define N 20  				// Define name array
#define M 3 				// Define an array for storing three grades
#define SIZE 3 				// Define the number of structures

//3. Definition of structure type
typedef struct person 		 	//Define a student information structure
{
	char name[N];			//full name
	int age;			//Age
	float scores[M];		//An array of scores
}Stu;					//Add Stu at the end and rename the structure to: Stu

//4. Enumeration type definition

//5. Function declaration
void sortByName(Stu *ps , int count);	//Name exchange
void sortByAge(Stu *ps , int count);	//Sort by age
void sortBySumScores(Stu *ps , int count);//Sort by total score
float Sum(float score[] , int count);	//Summation function  
Stu * pMaxAge(Stu *ps , int count);	//Take the first address of the oldest structure
void Input(Stu *ps , int count);	//Input function to define a struct pointer p of type struct person
void Output(Stu *p , int count);	//Output function, ditto

#endif

So far The h file is created.

2.1.3 links

Since there are no declarations in the main function, you need to refer to the one just defined h file
One thing to note here is: custom h file and library function h. differences between documents
Generally, the reference header file is: #include < stdio h> #include<string. h> Wait, these are all enclosed in angle brackets H file, but customized When the H file is quoted, angle brackets cannot be used, and English double quotation marks "malloc.h" should be used.

#include<stido. h> 	// Label library function header file
#include<string.h>
#include<math.h>
//-----------//
#include"malloc.h" 	// Custom header file
#include"sum.h"

2.1.4 gedit text compiler

  • The function step we split before is to store five types of files in a malloc h file [see 2.1.2], and then in malloc This is referenced in the C function by #include"malloc.h" h file, and finally gcc compilation is no problem.
  • But this is just a statement. The definition is split out. We're in malloc Many sub functions defined in this function are still in the same place as the main function In the c file, a huge function needs to be composed of multiple functions for the efficient and division of labor of future projects c file, usually we see many programs written by big guys are composed of multiple c documents, each c files represent different functions, which are finally called through a main function.
  • So based on the current separation function, we need to add Mallo c function continues to be split, and each sub function inside is encapsulated into an independent function c file, which introduces - > GEDIT text compiler
    We have a total of sub functions:
void sortByName(Stu *ps , int count);	//Name exchange
void sortByAge(Stu *ps , int count);	//Sort by age
void sortBySumScores(Stu *ps , int count);//Sort by total score
float Sum(float score[] , int count);	//Summation function  
Stu * pMaxAge(Stu *ps , int count);	//Take the first address of the oldest structure
void Input(Stu *ps , int count);	//Input function to define a struct pointer p of type struct person
void Output(Stu *p , int count);	//Output function, ditto

The next step is to use gedit:
gedit io.c pMaxAge.c sort.c sum.c malloc.c press enter after input, and you will find such an interface:

He will open more than one at a time c documents, if any If the c file does not exist, it will be created and opened. After opening it, we will use malloc.c om according to different functions The sub functions in the c program are cut to the opposite c file, and then each one The first line of the c file should refer to what we have defined h file (malloc.h), and finally save and close it.
Re ls, refresh the current directory file, so that we can store malloc There are several more under the same path of c C documents.

Next, we will introduce the most important step: Make. First, we need to understand the workflow of gcc:

3. gcc working principle

gcc compilation is divided into four stages: preprocessing, compilation, assembly and linking
1> Pretreatment:
gcc -E test.c -o test.i first write us C file compiled as i file. This step deals with files starting with # sign, that is, header files, macro definitions, etc
2> Compile:
gcc -S tesi.i -o test.s and then we preprocess it I file compilation to generate assembly language. [it should be noted that the assembly code has been generated before the assembly is executed]
3> Compilation:
This step is mainly to translate the compiled assembly code into machine language - > binary code. At this time, the computer can recognize the program, but there is no running permission, that is, [executable permission]
4> Link:
gcc test.o -o test after the first three steps of operation, our The c file has become o file, link will be o file gives execution permission and generates tese file/ Test can be run directly.

There are two ways to compile gcc:

Method 1: combine the first three stages into one
**

gcc -c test.c -o test.o

**, generate o file before running GCC test o - o test generates the executable file test.

Method 2: directly generate executable files in one step

gcc test.c -o test

4. Multi file compilation

eg:
gcc -c a.c -o a.o
gcc -c b.c -o b.o
gcc -c sum.c -o sum.o
gcc -c tmd.c -o tmd.o
Multiple files can be compiled at the same time to generate executable files:
gcc a.o b.o sum.o tmd.o -o test to generate the executable file test.

  • At first, I was splitting my malloc c function, I encountered a problem that plagued my whole evening self-study, that is, when I created a malloc h file, I put malloc c header file, macro definition... Etc. [details 2.1.2] in malloc h file, in malloc c referenced in the document h file can be compiled, but I continue to disassemble the molecular functions and di vi de them into one by one c file, although in each Malloc. Is referenced in all c files h declared, but still reported an error.
  • Finally, after watching the playback of the class carefully, I finally found the problem. It turned out that after I split the sub function, I didn't carry out the first three steps of gcc compilation [unclear can return to title 3]. Because I didn't carry out the first three steps, these are the first three steps The c file was not generated o files, so the computer will not recognize them.
  • Now that we have found the problem, it is clear how to solve it: we just need to put each one c files are compiled into o file!
    Or two methods, step by step, or three-step integration. I believe that students who are a little smarter than me know how to use the second method. You never thought of it. I forgot the second method. When I updated my blog tonight, I looked through yesterday's notes and found that there was such a simple method------ To get back to the point, after compilation, everyone claimed o file, then/ malloc, he can run normally
    The following figure: (please consciously ignore those. I. S files ^ ^ ^)

5. Make project manager

The make command will find a file called Makefile/makefile in the current path
Note: both uppercase m and lowercase m are OK
Here is a quote from a blogger's article: original link: https://blog.csdn.net/qq_43687652/article/details/119713711

For a project composed of hundreds of files, if only one or a few files have been modified, according to the gcc compilation tool learned before, you have to recompile all these files, because the compiler does not know which files have been updated recently
So people want to have a project manager that can automatically identify the updated file code
In fact, the make project manager is also an "automatic compilation manager". Here, automatic means that it can automatically find the updated files according to the file timestamp to reduce the workload of compilation. At the same time, it performs a lot of compilation work by reading the contents of the makefile file. Users only need to write a simple compilation statement once.

5.1Makefile specification

Target file 1: dependent file 1
(Tab key) how dependent file 1 generates target file 1
Target file 2: dependent file 2
(Tab key) how dependent file 2 generates target file 2
be careful:
1. There is no relationship between the two target files. Only target file 1 is executed by default
2. There can be multiple targets in a Makefile
3. When calling make, you need to tell it what the target is. If no target is specified, make takes the first target in the Makefile as the execution target

Tags: C C++ data structure

Posted by benjam on Fri, 13 May 2022 03:45:45 +0300