The second chapter is programming technology. This article is 2.2.3 built-in function pointer and 2.2.4 nested structure .

We know that arrays and pointers are collections of ordered data of the same type, but in many cases it is necessary to bundle different types of data together as a whole to make programming easier. In the C language, such a set of data is called a structure.

> > > 2.2.3 Built-in function pointer

Faced with a series of data, what really matters is not how to store data, but how to use it. In fact, a member of a structure can be data, or it can be a function pointer that contains operational data. In order to support this style, it is possible to introduce a new concept here - the method is declared as part of a structure, and the method can operate the data stored in the structure.

Type and variable

When a function pointer is a member of a structure, the check parameter is wrapped with the function pointer that calls the validator to form a new structure type. With a type, you can define a variable of that type, and then you can use this variable to reference the checksum and call the validator function.

To support this style, C allows the method to be declared as part of a structure, so it is easy to manipulate the data stored in the structure, as shown in Listing 2.18.

Listing 2.18 Range Value Checker Interface

Next, we need to design a validateRange() interface function to determine whether the value value meets the range value requirements. For details, see Listing 2.19.

Listing 2.19 Implementation of the range value validator interface function

For the same reason, the definition of the even checker OddEvenValidator and the variable oddEvenValidator are detailed in Listing 2.20.

Listing 2.20 Even parity interface

Next, you need to design a validateOddEven() interface function that determines whether the value is in compliance with the even parity requirement. For details, see Listing 2.21.

Listing 2.21 Implementation of the even parity interface function

Obviously, no matter what the verifier is, the commonality is the value value legality judgment, so you can share a function pointer, that is, the special function pointer types RangeValidate and OddEvenValidate are generalized to the general function pointer type Validate. Second, since each function has a pThis pointer to the current object, the special struct types struct _RangeValidator * and struct _OddEvenValidator * are generalized to void * types, which accept arguments of any type of data. such as:

This is the paradigm programming, the implementation of the validator interface is detailed in Listing 2.22. Since pRangeValidator is different from pThis, you must cast a cast to the pThis pointer to reference the members of the corresponding structure.

Listing 2.22 Implementation of the Universal Validator Interface (validator.c)

Thus, when the method is declared as part of the structure, the method and data are directly packaged into a new data type RangeValidator. With the RangeValidator type, you can create a variable rangeValidator of that type, which can reference the structure's data through the rangeValidator and call the corresponding handler. What I really want to reinforce is the idea of ​​defining a structure by a method, not the data that happens to be used when implementing a structure.

2. Initialization

Initialize the structure with a macro called newRangeValidator:

Among them, validateRange is the function name of the range value checker, and the usage is as follows:

The macro expands as follows:

It is equivalent to:

If there are the following definitions:

The min and max of the RangeValidator can be referenced by pValidator. The calling function is called as follows:

The premise of the above call form is that the pValidator is known to point to the determined structure type. If the pValidator will point to the unknown validator, obviously the above call form cannot be generalized, then how will it be called?

Although pValidator is not the same type as &rangeValidator.validate, but their values ​​are equal, you can use this feature to get the address of the validateRange() function. such as:

The form of its call is as follows:

3. Interface and implementation

For ease of reading, the interface to the universal validator is shown in detail in Listing 2.23.

Listing 2.23 Universal Validator Interface (validator.h)

Taking the range value checker as an example, the implementation of the rangeCheck() function that calls validateRange() is as follows:

The call form of the rangeCheck() function is as follows:

Thus, the implementation of the rangeCheck() function does not depend on any specific validators. Note that the author does not provide the complete code here, please supplement it.

> > > 2.2.4 Nested Structure

Refactoring

With the addition of one function after another, dealing with one error after another, the structure of the code will gradually degenerate. If you ignore this, this degradation will eventually lead to tangled, difficult to maintain chaotic code, so you need to refactor the code frequently to reverse this degradation.

Refactoring is a series of small improvements made to improve the structure of the system without changing the behavior of the code. While every improvement is trivial and even hardly worthwhile, the improvement in system design and architecture is evident when all the transformations are added together.

After each minor improvement, run the unit test to make sure the improvement does not cause any damage before proceeding to the next improvement. This reciprocating and recurring, running after each improvement, in this way to ensure that the system can work properly while improving the system design.

Refactoring is ongoing, not at the end of the project, at the time of release, at the end of the iteration, or even when it is off work every day. Refactoring is something that is done every hour or half an hour, and refactoring can consistently keep code as clean, simple, and expressive as possible.

A lot of practice has proved that repetition may be the root of all evil in software. Many principles and practical rules are created to control and eliminate duplication. The best way to eliminate duplication is to abstract, moving all common function pointers into a single struct, creating a generic Validator type validator. That is to say, if the two things are similar, there must be some kind of abstraction that can unify them, so eliminating the repeated behavior will force the team to extract a lot of abstractions, further reducing the coupling between the codes.

Since the invention of the subroutine, all innovations in the field of software development are constantly trying to eliminate duplication from the source code, that is, DRY (Don't Repeat Yourself) principle - do not repeat yourself, because repeated stickers will bring a lot of problems So no matter where you find duplicate code, you have to eliminate them.

2. Types and variables

In fact, whether it is a range value verifier or a parity checker, it is essentially a validator. The same attribute is the check parameter and the value to be checked. The same behavior can be shared by a function pointer. Different checkers. According to the principle of dependency inversion, abstract their same attributes and behaviors into a structure type Validator. such as:

Here, taking the range value check as an example, a Validator type structure is nested in the RangeValidatro structure, that is, the variable isa of the Validator type is a member of the RangeValidator structure. such as:

Since the values ​​of &rangeValidator and &rangeValidator.isa are equal, the following relationship is true. such as:

You can prototype the validateRange() function:

The "void *pThis" in the conversion to "Validator *pThis", the prototype of the validatrRange() function evolved to:

3. Initialization

When the Validator type of isa is used as a member of the RangeValidator structure, it is clear that rangeValidator.isa is a structure variable name that can be used like any normal structure variable. Use the Validator type expression:

You can reference the member validate of the structure member isa of the rangeValidator variable, that is, rangeValidator.isa is the left operator of another dot operator. such as:

Since the combination of dot operators is from left to right, parentheses can be omitted. It is equivalent to:

Just think of rangeValidator.isa as a variable of type Validator.

Initialize the structure with a macro called newRangeValidator:

Where validateRange is the range value validator function name, which is used as follows:

The macro expands as follows:

Among them, the outer {} assigns a value to the RangeValidator structure, and the internal {} assigns a value to the member variable isa of the RangeValidator structure. which is:

If there are the following definitions:

That is, you can use the pValidator to reference the min and max of the RangeValidator.

Since pValidator and &rangeValidator.isa are not only of the same type and equal in value, the following relationship holds true:

So you can use this feature to get the address of the validateRange() function, ie pValidator->validate points to validateRange(). The form of its call is as follows:

4. Interface and implementation

Taking the range value checker as an example, the call form of the validatorCheck() function is as follows:

Of course, you can also take the following form of call:

The effect is the same.

For ease of reading, the interface to the universal validator is shown in detail as shown in Listing 2.24.

Listing 2.24 General Validator Interface (validator.h)

Taking the range value checker as an example, the implementation of the validatorCheck() function that calls validateRange() is as follows:

Thus, the implementation of the validatorCheck() function does not depend on any specific validator. The implementation of the universal validator interface is shown in Listing 2.25.

Listing 2.25 Implementation of the Universal Validator Interface (validator.c)

Here, the author does not provide the complete code, please fill it out.

VEIIK Ticko Vape Series

VEIIK Ticko Vape Series are so convenient, portable, and small volume, you just need to take them out of your pocket and take a puff, feel the cloud
of smoke, and the fragrance of fruit surrounding you. It's so great.
We are the distributor of the VEIIK Vape brand, we sell veiik e cigarette, veiik vape pen, veiik disposable vaporizer, and so on.
We are also China's leading manufacturer and supplier of Disposable Vapes puff bars, disposable vape kit, e-cigarette, vape pens, and e-cigarette kit,
and we specialize in disposable vapes, e-cigarette vape pens, e-cigarette kits, etc.

veiik ticko vape bar,veiik ticko vape starter kit,veiik ticko vape device,veiik ticko vape pen,veiik ticko vape disposable

Ningbo Autrends International Trade Co.,Ltd. , https://www.supervapebar.com