C++11 Study Notes (4) - General Tools (Part 2)

It's too long, let's write it in two parts,
the book will continue

4. Numerical extremes

std::numeric_limits is a template class defined in the C++ Standard Library, located in a header file. It provides information about properties and extreme values ​​of various numeric types. This information can help us understand the numerical range, precision, and other numerical-related characteristics of a specific type when we perform numerical processing in the program.

Minimum precision

type minimum length
char 1 byte
short int 2 bytes
int 2 bytes
long int 4 bytes
long long int 8 bytes
float 4 bytes
double 8 bytes
long double 8 bytes

Generic numeric_limits

template<typename T>
class numeric_limits {
    
    
public:
    static constexpr bool is_specialized = false;

    static constexpr T min() noexcept {
    
    
        return T();
    }

    static constexpr T max() noexcept {
    
    
        return T();
    }

    // 其他成员函数和常量...
};

Generic templates provide default limit values ​​means that when using the generic template of std::numeric_limits it will provide a default set of limit values ​​if no specialization is made for a particular type.

For basic data types (such as integers, floating-point numbers, etc.), the general template will provide suitable default extreme values ​​according to the characteristics of the type. For example, for signed integer type int, std::numeric_limits::min() returns the minimum value of the type, and std::numeric_limits::max() returns the maximum value of the type.

For floating-point types, std::numeric_limits::min() returns the smallest positive value of that type, and std::numeric_limits::max() returns the largest finite value of that type.

The generic template also provides some other default extremum information, such as precision, rounding error, etc. These default extremes are defined based on the general characteristics of the type and standard specifications.

#include <iostream>
#include <limits>

int main() {
    
    
    std::cout << "int 类型的最小值:" << std::numeric_limits<int>::min() << std::endl;
    std::cout << "int 类型的最大值:" << std::numeric_limits<int>::max() << std::endl;
    std::cout << "float 类型的最小精度:" << std::numeric_limits<float>::epsilon() << std::endl;
    std::cout << "double 类型的正无穷大:" << std::numeric_limits<double>::infinity() << std::endl;
    std::cout << "double 类型的静默非数值(NaN):" << std::numeric_limits<double>::quiet_NaN() << std::endl;
    std::cout << "double 类型的位数:" << std::numeric_limits<double>::digits << std::endl;

    return 0;
}

specialized numeric_limits

For certain data types, such as user-defined class types or special numeric types, these defaults may not apply because these types may have different numeric ranges or special behavior. To cater for these special cases, a specialization of std::numeric_limits is available.

Specialization is achieved by providing a specialized version of a template for a particular type, to override default properties and extrema. By specializing std::numeric_limits, we can provide custom limit values ​​and attribute information for specific types.

The following is an example showing how to specialize std::numeric_limits to provide custom limit values ​​and attribute information for a custom type MyType:

#include <iostream>
#include <limits>

class MyType {
    
    
    // 自定义类型的定义和实现
};

namespace std {
    
    
    template <>
    class numeric_limits<MyType> {
    
    
    public:
    	static constexpr bool is_specialized = true;
        static constexpr MyType min() {
    
     return MyType{
    
    }; }  // 自定义的最小值
        static constexpr MyType max() {
    
     return MyType{
    
    }; }  // 自定义的最大值
    };
}

int main() {
    
    
    std::cout << "MyType 类型的最小值:" << std::numeric_limits<MyType>::min() << std::endl;
    std::cout << "MyType 类型的最大值:" << std::numeric_limits<MyType>::max() << std::endl;

    return 0;
}

In the example above, we provided custom minimum and maximum values ​​for the custom type MyType by defining a specialization of std::numeric_limits under the std namespace. Through specialization, we can provide custom extremum and property information for any type as needed.

It should be noted that the specialization of std::numeric_limits is an advanced usage, which is usually used when dealing with custom types or special needs. For most basic data types, the default std::numeric_limits is usually sufficient.

Replenish

The general numeric_limits and specialized versions are placed in the <limite> header file, and the specialized versions cover all numeric basic types.
The original C constants are defined in <climits>,<limits.h>,<cfloat>,<float.h>
insert image description hereinsert image description hereinsert image description here

5.Type trait

Type traits (Type Traits) is a set of template classes in C++ for obtaining and manipulating type information at compile time. They provide a way to perform type checking and manipulation at compile time, enabling the compiler to perform operations such as conditional compilation, type conversion, and template specialization based on properties of types.

Elastic overloading for integer types

Assuming that there is a function that may pass in integer and floating-point actual parameters, it is usually necessary to write multiple overloaded functions including short, int, float, double, etc., which is not only cumbersome but also needs to add new types, and Type trait can simplify it.

#include <iostream>
#include <type_traits>

// 重载版本1:针对整数类型
template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type
process(T value) {
    
    
    std::cout << "整数值:" << value << std::endl;
}

// 重载版本2:针对非整数类型
template <typename T>
typename std::enable_if<!std::is_integral<T>::value>::type
process(T value) {
    
    
    std::cout << "非整数值:" << value << std::endl;
}

int main() {
    
    
    process(10);        // 调用重载版本1,传入整数类型
    process(3.14);      // 调用重载版本2,传入非整数类型

    return 0;
}

In this way, only two implementations are required to contain multiple parameter types

Handle common types

Common Type refers to the lowest common type in a group of types that can operate and return a consistent type. In C++, you can use the std::common_type type trait template to obtain the lowest common type of a set of types.

Here is a sample code that demonstrates how to use std::common_type to handle common types:

#include <iostream>
#include <type_traits>

template <typename T1, typename T2>
void process(T1 value1, T2 value2) {
    
    
    using CommonType = typename std::common_type<T1, T2>::type;
    CommonType result = value1 + value2;
    std::cout << "结果:" << result << std::endl;
}

int main() {
    
    
    process(10, 3.14);      // 传入整数和浮点数
    process(5.5, 2.7);      // 传入两个浮点数
    process(7, 8);          // 传入两个整数

    return 0;
}

In the above example, we define a process function template that accepts two parameters value1 and value2 and uses std::common_type to get the lowest common type CommonType of these two parameters. Then, we use CommonType to declare a variable result, add value1 and value2 and assign the result to result. Finally, we output the result to the console.

In the main function, we call the process function to pass in different types of parameters, including integers and floating point numbers. std::common_type will automatically deduce the lowest common type, and perform corresponding type conversion and operation on the result.

By using std::common_type, we can process a set of parameters with different types and obtain their lowest common type, thereby realizing the processing of common types. This is useful in generic programming and template metaprogramming to handle operations on various types of combinations.

other operations

for all types

insert image description here

for class class

insert image description here

Note that bool and all characters are treated as integer classes

Check type relationship

insert image description here

type change

insert image description here

other

insert image description here

reference wrapper

std::reference_wrapper is a class template in the C++ standard library, located in a header file. It is used to wrap reference types, providing a lightweight reference semantics, allowing objects to be passed and manipulated by reference.

The main function of std::reference_wrapper is to encapsulate the reference type into an object, so that it has object semantics. This makes it easy to pass references as function arguments, store them in containers, or use them in other situations where objects are required, without introducing additional pointer semantics and memory management.

Using std::reference_wrapper can achieve the following functions:

  • Passing references as function parameters: You can pass references as function parameters without using pointers or copying objects.
  • Storing reference types: Reference types can be stored in containers, such as std::vector<std::reference_wrapper>.
  • Using references in algorithms: You can use reference types in standard library algorithms without using pointers or copying objects.

Below is a sample code that demonstrates how to use

#include <iostream>
#include <functional>

void increment(int& value) {
    
    
    ++value;
}

int main() {
    
    
    int num = 10;
    std::reference_wrapper<int> ref(num);

    increment(ref);

    std::cout << "num: " << num << std::endl;

    return 0;
}

In the above example, we defined an increment function that takes a reference parameter and increments it. In the main function, we create a std::reference_wrapper object ref and pass the reference of num to it. Then, we call the increment function and pass ref, actually a reference to num. Finally, we print the value of num and see that it has been incremented.

By using std::reference_wrapper, we can pass and manipulate reference types as objects, providing more convenient and flexible reference semantics. It is often used in scenarios such as generic programming, function objects, STL algorithms, etc.

Function Type Wrapper

std::function is a class template provided in the C++ standard library, which is used to encapsulate different types of callable objects and provide a consistent calling interface.

The class template for std::function is defined as follows:

template<class R, class... Args>
class function<R(Args...)>;

where R is the return type and Args... is the list of argument types.

By using std::function, you can create a function object that can wrap different types of callable entities, such as function pointers, function objects, member function pointers, lambda expressions, etc.

std::function provides the following main functionality and usage:

  • Encapsulation of callable objects: std::function can be used to encapsulate various callable objects into a unified function object so that they have the same calling interface.
  • Storing and passing callable objects: std::function objects can be copied, stored and passed around like ordinary objects. This makes it ideal for passing callable objects as arguments to functions, stored in containers, or as class member variables.
  • Polymorphic call: Through std::function, different types of callable objects can be called in a unified way, without caring about their specific types. This makes the code more flexible and extensible.

Here is an example showing how to use std::function:

#include <iostream>
#include <functional>

int add(int a, int b) {
    
    
    return a + b;
}

class Foo {
    
    
public:
    int multiply(int a, int b) {
    
    
        return a * b;
    }
};

int main() {
    
    
    std::function<int(int, int)> func;

    func = add;
    int result1 = func(3, 4);
    std::cout << "Result1: " << result1 << std::endl;

    Foo foo;
    func = std::bind(&Foo::multiply, &foo, std::placeholders::_1, std::placeholders::_2);
    int result2 = func(3, 4);
    std::cout << "Result2: " << result2 << std::endl;

    return 0;
}

In the above example, we first defined an add function and a Foo class, where the Foo class has a member function multiply. Then, we declare a std::function object func whose function type is int(int, int).

We first assign the add function to func, then use func to call the add function and output the result. Next, we bind the member function multiply of the Foo class to func using std::bind, passing an object pointer of the Foo class and two placeholders as parameters. Finally, we call Foo::multiply with func and output the result.


Placeholders are special objects in the C++ standard library that occupy the parameter positions of function objects. In the function object, the placeholder indicates that the parameter at this position will be replaced with the corresponding value when it is actually called.

In the usage of std::bind, the placeholders std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, and more successively increasing placeholders _4, _5, etc. are used to identify the parameter positions of the function object. With placeholders, we can specify the position of the parameter when binding the function without providing the actual parameter value.

In the sample code, we use two placeholders std::placeholders::_1 and std::placeholders::_2:

func = std::bind(&Foo::multiply, &foo, std::placeholders::_1, std::placeholders::_2);

Here, we bind the Foo::multiply member function to func and use two placeholders to specify the position of the parameters. This means that when we call func, the arguments will be passed in place of the placeholders.

When actually calling func(3, 4), the placeholder std::placeholders::_1 corresponds to the first parameter, which is 3, and the placeholder std::placeholders::_2 corresponds to the second parameter, which is 4. Therefore, parameters 3 and 4 will be passed to the Foo::multiply member function as actual parameters.

The use of placeholders can make function objects more flexible, especially in terms of function object binding and parameter location mapping. It allows us to defer the passing of parameters and provide parameter values ​​dynamically when calling the function object.

It should be noted that the number and position of placeholders should match the number and position of parameters of the function object. Otherwise, it will lead to incorrect parameter passing or compilation errors.

In the example, placeholders are used to associate the bound function object with the foo object and the parameter positions. This way, when we call the bound function object, it calls the multiply function on the foo object, passing the corresponding positional arguments to the function.


Through std::function, we can encapsulate different types of callable objects into a unified object and call them in a unified way. This provides greater flexibility and generality, making the use of function objects more convenient and extensible.

6. Helper functions

Maximum and minimum

All minmax() functions and all functions with initial value columns start from c++11
insert image description here. When we use functions in header files, we usually need to specify comparison functions (or predicates) to determine the order of elements or to meet other conditions. A comparison function is a callable object that takes two arguments and returns a boolean value that compares the order of two elements.

custom comparison

Here is an example of sorting using comparison functions:


#include <algorithm>
#include <vector>
#include <iostream>

bool cmp(int a, int b) {
    
    
    // 按照绝对值大小进行比较
    return std::abs(a) < std::abs(b);
}

int main() {
    
    
    std::vector<int> nums = {
    
    -3, 2, -1, 4, -5};
    std::sort(nums.begin(), nums.end(), cmp);

    for (const auto& num : nums) {
    
    
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

In the above example, we defined a comparison function cmp, which compares elements according to their absolute value. We then sort the nums container using the std::sort function, passing in the cmp function as a comparison function.

The sorting results will be sorted according to the absolute value of the elements from small to large, and the output results are: -1, 2, -3, 4, -5.

By customizing the comparison function, we can sort or compare elements according to specific conditions. This is useful in many algorithms and operations, such as custom sort orders, filtering elements by specific rules, and more. According to different needs, we can write different comparison functions to meet specific sorting or comparison logic.

swap two values

std::swap is a general swap function in the C++ standard library, located in the header file.

The std::swap function has several overloaded versions for exchanging objects of different types. Its generic template is defined as follows:

namespace std {
    
    
    template <class T>
    void swap(T& a, T& b);
}

where T is the type of the object to be swapped and a and b are references to the objects to be swapped.

When calling std::swap(a, b), depending on the actual object type, the compiler will choose the appropriate overloaded version to perform the swap operation. std::swap already has default specialization definitions for built-in types and types provided by the standard library.

In addition, for a custom type, we can implement the swap operation of the custom type by defining a specialized version of the type or providing a custom swap function. For example:

namespace std {
    
    
    template <>
    void swap<MyType>(MyType& a, MyType& b) {
    
    
        // 自定义类型的交换操作
    }
}

By providing a specialization of the custom type MyType in the std namespace, we can overload the std::swap function to perform a specific swap operation when swapping objects of the custom type.

The following is an example of value exchange using std::swap:

#include <algorithm>
#include <iostream>

int main() {
    
    
    int a = 10;
    int b = 20;

    std::cout << "Before swap: a = " << a << ", b = " << b << std::endl;

    std::swap(a, b);

    std::cout << "After swap: a = " << a << ", b = " << b << std::endl;

    return 0;
}

In the above example, we defined two integer variables a and b and initialized to 10 and 20 respectively. Then, we swapped the values ​​of a and b using the std::swap function.

The output is:

Before swap: a = 10, b = 20
After swap: a = 20, b = 10

By using std::swap, we can conveniently swap the values ​​of two objects without explicitly writing temporary variables or custom swap functions. This is very useful in many situations, such as in sorting algorithms, container operations, etc. where values ​​need to be exchanged. Since c++11, the standard library provides an overloaded version for array . In addition, for user-defined types, user-defined exchange operations can be implemented by overloading operator=.

To sum up, std::swap is a general exchange function provided by the C++ standard library, which can be used to exchange objects of different types. There are already default specialization definitions for built-in types and types provided by the standard library. For a custom type, we can implement the swap operation of the custom type through a specialized version or a custom swap function.

comparison operator

In C++11, the following operators can be used to compare the size relationship of two objects:

!=(不等于):用于检查两个对象是否不相等。
>(大于):用于检查一个对象是否大于另一个对象。
<(小于):用于检查一个对象是否小于另一个对象。
>=(大于等于):用于检查一个对象是否大于或等于另一个对象。
<=(小于等于):用于检查一个对象是否小于或等于另一个对象。

These operators can be used on built-in types (such as integers, floating-point numbers, etc.) and user-defined types, provided that the corresponding operator overloads are defined or the objects support the relevant comparison operations.

Here is an example showing how to use these operators to compare two integers:

#include <iostream>

int main() {
    
    
    int a = 10;
    int b = 5;

    if (a != b) {
    
    
        std::cout << "a is not equal to b" << std::endl;
    }

    if (a > b) {
    
    
        std::cout << "a is greater than b" << std::endl;
    }

    if (a < b) {
    
    
        std::cout << "a is less than b" << std::endl;
    }

    if (a >= b) {
    
    
        std::cout << "a is greater than or equal to b" << std::endl;
    }

    if (a <= b) {
    
    
        std::cout << "a is less than or equal to b" << std::endl;
    }

    return 0;
}

The output is:

a is not equal to b
a is greater than b
a is not less than b
a is greater than or equal to b
a is not less than or equal to b

In the above example, we compare two integers a and b, and output a corresponding message based on their magnitude relationship. Note that if you want to compare objects of a custom type, you need to overload the corresponding comparison operator.

7.Class ratio<>

std::ratio is a template class in the C++ Standard Library for representing ratios of rational numbers. It's in the header file.

The std::ratio template class is defined as follows:


template <intmax_t Num, intmax_t Denom = 1>
class ratio;

Among them, Num represents the numerator, Denom represents the denominator, and the default value is 1. Both Num and Denom must be integer types.

The std::ratio template class provides a way to represent ratios of rational numbers at compile time, which can be used to perform unit conversions, calculate ratio relationships, and more. Its main role is to provide a compile-time static type to represent common proportional relationships without the need for runtime calculations.

Here is an example using std::ratio:

#include <iostream>
#include <ratio>

int main() {
    
    
    using one_half = std::ratio<1, 2>;
    using one_third = std::ratio<1, 3>;
    using two_thirds = std::ratio_add<one_third, one_third>;

    std::cout << "1/2 = " << one_half::num << "/" << one_half::den << std::endl;
    std::cout << "1/3 = " << one_third::num << "/" << one_third::den << std::endl;
    std::cout << "1/3 + 1/3 = " << two_thirds::num << "/" << two_thirds::den << std::endl;

    return 0;
}

The output is:

1/2 = 1/2
1/3 = 1/3
1/3 + 1/3 = 2/3

In this example, we define three aliases for the std::ratio type: one_half for 1/2, one_third for 1/3, and two_thirds for 1/3 + 1/3.

By accessing the num and den static member variables of the std::ratio class, we can obtain the numerator and denominator of the ratio of rational numbers and output them.

Expression

insert image description here

predefined units

The header files in the C++ standard library provide some predefined std::ratio units, which are used to represent common proportional relationships.
insert image description here
These predefined units make it more convenient to express physical quantities, and you can directly use them for unit conversion and ratio calculations. For example, std::kilo represents a thousand, and you can multiply a value by std::kilo to convert it to a thousand times.

It should be noted that std::ratio is a type calculated at compile time, its value is determined at compile time, and does not support runtime arithmetic operations. It is mainly used for unit conversion and ratio calculation at compile time, for example, it has a wide range of applications in template metaprogramming and static type checking.

8. Clock and timer

Header files were introduced in C++11 to provide functions related to Clock and Timer for measuring time and implementing timers.

Duration (time period)

The header files in C++11 introduce the std::chrono::duration class template for representing time intervals or durations. std::chrono::duration is a general time quantity class that can be used to represent time intervals in different units, such as seconds, milliseconds, microseconds, etc.

The template parameter of std::chrono::duration consists of two parts: Rep and Period. Rep represents the underlying type of the time interval, usually an arithmetic type (such as int, double, etc.), and Period represents the unit of the time interval. Period is an instance of std::ratio type, which is used to represent the proportional relationship between numerator and denominator, which determines the unit of the time interval.

Here is an example using std::chrono::duration:

#include <iostream>
#include <chrono>

int main() {
    
    
    // 定义一个持续时间为 5 秒的 duration
    std::chrono::duration<int> durationSeconds(5);

    // 定义一个持续时间为 2.5 秒的 duration
    std::chrono::duration<double> durationSecondsDouble(2.5);

    // 输出 duration 的数值和单位
    std::cout << "durationSeconds: " << durationSeconds.count() << " seconds" << std::endl;
    std::cout << "durationSecondsDouble: " << durationSecondsDouble.count() << " seconds" << std::endl;

    // 将 duration 转换为毫秒
    std::chrono::duration<int, std::milli> durationMilliseconds = std::chrono::duration_cast<std::chrono::duration<int, std::milli>>(durationSeconds);

    // 输出转换后的 duration 的数值和单位
    std::cout << "durationMilliseconds: " << durationMilliseconds.count() << " milliseconds" << std::endl;

    return 0;
}

In this example, we create two std::chrono::duration objects of different types: a duration of type integer with a duration of 5 seconds, and a duration of type double with a duration of 2.5 seconds. We use the count() member function to get the value of duration, and use std::chrono::duration_cast for unit conversion.

The output is:

durationSeconds: 5 seconds
durationSecondsDouble: 2.5 seconds
durationMilliseconds: 5000 milliseconds

insert image description hereinsert image description here

By using std::chrono::duration, time intervals can be easily calculated, converted, and represented without manually managing conversions between different units.

Clock

Clock is a benchmark for time measurement. C++11 provides three types of clocks:

  • std::chrono::system_clock: used to represent the current time of the system.
  • std::chrono::steady_clock: used to represent a relatively stable time and will not be affected by the system time.
  • std::chrono::high_resolution_clock: Provides a high-precision clock, which may be an alias for system_clock or steady_clock.

These clocks provide the now() member function to get the current clock's time.

Here is an example using std::chrono::steady_clock:

#include <iostream>
#include <chrono>

int main() {
    
    
    auto start = std::chrono::steady_clock::now();

    // 执行一些操作

    auto end = std::chrono::steady_clock::now();
    auto duration = end - start;

    std::cout << "耗时:" << std::chrono::duration<double>(duration).count() << " 秒" << std::endl;

    return 0;
}

In this example, we use std::chrono::steady_clock to get the start and end time points, and calculate the time difference between them to get the execution time of the program.
insert image description here

Timer

C++11 does not directly provide a standard library class for timers, but you can use Clock and some other functions to implement timer functionality. For example, you can use the std::this_thread::sleep_for() function to let the thread sleep for a period of time to implement a simple timer function.

Here is an example of implementing a timer using std::this_thread::sleep_for():

#include <iostream>
#include <chrono>
#include <thread>

int main() {
    
    
    int count = 0;
    int target = 5;

    while (count < target) {
    
    
        std::this_thread::sleep_for(std::chrono::seconds(1));
        count++;
        std::cout << "定时器触发:" << count << std::endl;
    }

    std::cout << "定时器结束" << std::endl;

    return 0;
}

In this example, we use the std::this_thread::sleep_for() function to make the program sleep for 1 second and output the number of times the timer fires. The program ends the timer when the count reaches the target value.

It is important to note that the implementation of timers may vary between operating systems and compilers. The above example only provides a simple implementation method, and more complex timer functions may be required in actual applications, which can be expanded and optimized according to specific requirements.
insert image description here

function in C

Definitions originally in <time.h> are now included in <ctime>
insert image description here

Conversion between Timepoint and calendar time

In the header file of C++11, the std::chrono::time_point class template can be used to represent the time point (Time Point). A point in time is an abstract concept of a specific moment, corresponding to Calendar Time.

To convert between a point in time and a calendar time, the following functions and types can be used:

  • std::chrono::system_clock: std::chrono::system_clock is a clock type used to represent the current time of the system. It can be used to get the current calendar time.

  • std::chrono::time_point: std::chrono::time_point is a class template representing a point in time. It can be used to store and manipulate values ​​at points in time.

  • std::chrono::duration: std::chrono::duration is a class template representing a time interval. This can be used to calculate the difference between time points.

Here is an example conversion between a point in time and a calendar time:

#include <iostream>
#include <chrono>
#include <ctime>

int main() {
    
    
    // 获取当前的日历时间
    std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

    // 将日历时间转换为时间点
    std::chrono::time_point<std::chrono::system_clock> timePoint = std::chrono::system_clock::from_time_t(currentTime);

    // 将时间点转换为日历时间
    std::time_t convertedTime = std::chrono::system_clock::to_time_t(timePoint);

    // 输出转换后的日历时间
    std::cout << "Converted time: " << std::asctime(std::localtime(&convertedTime));

    return 0;
}

In this example, we first use std::chrono::system_clock::now() to get the current time point, and then use std::chrono::system_clock::to_time_t() to convert the time point to calendar time (std::time_t type). Next, we convert the calendar time back to a point in time using std::chrono::system_clock::from_time_t(). Finally, we output the converted calendar time to the standard output stream using std::asctime().

Note that point-in-time and calendar time may vary in precision and range. Points in time generally have higher precision and range, while calendar times are limited to the precision and range of the std::time_t type.

Using the conversion between time point and calendar time, you can easily convert and operate between different time representations to meet different needs.

Timers are often used in threads, this part is described in detail in the thread chapter later

9. Some important header files

<cstddef>

The <cstddef> header file defines some types and functions related to size and pointer operations
insert image description here

<cstdlib>

The header file defines some common library functions, such as memory management functions (such as malloc and free), type conversion functions (such as atoi and atof), random number functions (such as rand and srand), and other common functions.
insert image description here

<cstring>

The <cstring> header file defines some functions and types related to string manipulation, such as string copy functions (such as strcpy and strncpy), string concatenation functions (such as strcat and strncat), string comparison functions (such as strcmp and strncmp), and other string processing functions.
insert image description here

example

#include <iostream>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <string>

int main() {
    
    
    // 使用 cstddef 定义的类型
    std::size_t size = 10;
    std::ptrdiff_t diff = 5;
    std::nullptr_t nullPtr = nullptr;

    // 使用 cstdlib 的库函数
    int randomNumber = std::rand();
    std::cout << "Random number: " << randomNumber << std::endl;

    // 使用 cstring 的字符串操作函数
    char str1[] = "Hello";
    char str2[10];
    std::strcpy(str2, str1);
    std::strcat(str2, " World");
    std::cout << "Concatenated string: " << str2 << std::endl;

    // 使用 string 类进行字符串操作
    std::string s1 = "Hello";
    std::string s2 = "World";
    std::string s3 = s1 + " " + s2;
    std::cout << "Concatenated string: " << s3 << std::endl;

    return 0;
}

This example demonstrates how to use , , and header files for primitive types, library functions, and string manipulation. Note that when working with strings in C++, it is recommended to use the std::string class instead of traditional C-style strings (represented as character arrays) for safer and more convenient string manipulation functions.

  • end of chapter five

Guess you like

Origin blog.csdn.net/qq_44616044/article/details/131223759