Data structure - C++ (unfinished)

Series Article Directory

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
For example: the use of pandas in Chapter 1 Introduction to Python Machine Learning


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


foreword

提示:这里可以添加本文要记录的大概内容:

For example: With the continuous development of artificial intelligence, the technology of machine learning is becoming more and more important. Many people have started to learn machine learning. This article introduces the basic content of machine learning.


1. Linear table

1. Sequential storage structure of linear table

The sequential storage structure of the linear table refers to storing each data element of the linear table sequentially in a memory space with a set of consecutive addresses, so that logically adjacent data elements are also physically adjacent.
If each element of the linear table occupies d storage units, then the table and the iiThe storage location of i elementsL oc ( ai ) Loc(a_{i})L oc ( ai) satisfy the following relationship:L oc ( ai ) = L oc ( a 1 ) + ( i − 1 ) ∗ l Loc(a_{i})=Loc(a_1)+(i-1)*lL oc ( ai)=L oc ( a1)+(i1)l
insert image description here
That is to say, as long as the first address of the sequence table and the number of address units occupied by each data element are known, the address of the i-th data element can be obtained.
Define the data structure type of the following sequence table:

typedef int DataType;
const int MAXSIZE = 20;
class SequenList {
    
    
	//数据元素a1,a2,a3,……,an;对应的索引是data[0],data[1],data[2],……,data[n-1]
public:
	void Initiate(); //初始化
	int Length();
	int Insert(DataType x, int i);//在位置i处前插入值x
	int Deleted(int i);
	int Locate(DataType x); //寻找数据元素x的位置
	DataType Get(int i);
	void print();
private:
	DataType data[MAXSIZE] = {
    
    1,2,3,4,5,6,7,8,9};
	int len=9;
};

The specific algorithm is implemented as follows

void SequenList::Initiate() {
    
    
	//初始化
	len = 0;
}

int SequenList::Insert(DataType x, int i) {
    
    
	//在第i个数据元素前插入一个新的数据元素x
	//将第i个到第len个元素往后移动一个位置,空出的位置插入新的元素x
	//表长度加1
	int j;
	if (len >= MAXSIZE) {
    
    
		cout << "数据溢出" << endl;
		return 0;
	}
	else if (( i < 1 ) ||( i > len + 1)) {
    
    
		cout << "插入位置不合法" << endl;
		return 0;
	}
	else {
    
    
		for (j = len; j >= i; --j) {
    
    
			data[j] = data[j - 1];  //元素后移
		} 
		data[i-1] = x;  //在第i个数据元素前插入元素
		++len;			//表长度加一
		return 1;
	}
}

int SequenList::Deleted(int i) {
    
    
	//删除第i个位置上的元素
	//表长度减1
	int j;
	if ((i < 1) || (i > len)) {
    
    
		cout << "删除位置不合法" << endl;
		return 0;
	}
	else {
    
    
		for (j = i; j < len; ++j) {
    
    
			data[j - 1] = data[j];
		}
		--len;
		return 1;
	}
}

int SequenList::Locate(DataType x) {
    
    
	//寻找数据元素x的位置
	int j=0;
	while ((j < len) && (data[j] != x))
		++j;
	if (j < len)
		return j + 1;
	else
		return 0;
}

int SequenList::Get(int i) {
    
    
	//读取第i个元素的值
	if ((i < 1) || (i > len)) {
    
    
		cout << "读取位置不合法" << endl;
		return NULL;
	}
	else
		return data[i - 1];
}

int SequenList::Length() {
    
    
	return len;
}

void SequenList::print() {
    
    
	for (auto c : data) {
    
    
		cout << c << " ";
	}
	cout << endl;
}
int main()
{
    
    
	SequenList S;
	S.Insert(10, 2);
	S.print();
	int position=S.Locate(3);
	cout << position << endl;
	system("pause");
	return 0;	
}

2. Linked storage structure of linear list - single linked list

Since operations such as insertion, deletion, and movement on the sequential table need to be implemented by moving data, the efficiency is seriously affected. The linked storage structure does not require logically adjacent elements to be physically adjacent, but establishes logical relationships between data elements through links.
For each data element ai a_iai, in addition to storing its own data information (data field), it also needs to store its successor ai + 1 a_{i+1}ai+1The address of the storage unit (pointer field). These two pieces of information constitute a "node".
Since there is only one pointer to the successor in each node, this type is also called a "singly linked list".
insert image description here
The access of the entire linked list must start from the head pointer, which indicates the storage location of the first node of the linked list. At the same time, since the last data element has no direct successor, the pointer of the last node is NULL. The linked list is
insert image description here
different from the sequential list. It is a dynamically managed storage structure. The storage space occupied by each node in the linked list is not pre-allocated. , but is dynamically generated by the system at runtime according to requirements, so the establishment of a singly linked list should start with an empty list.

In addition, for convenience, the head node is generally set in the linked list. As shown in the figure below:
the advantages of doing this are:
1. It is convenient for the head node ( a 1 a_1a1) processing
The address of the head node is stored in the pointer field of the head node, so the operation on the first position of the linked list is consistent with other positions, and no special processing is required 2. It is convenient for unified processing of empty and non-empty
tables
Regardless of whether the linked list is empty or not, the head pointer is a non-null pointer pointing to the head node, so the processing is unified.
insert image description here
Define the data structure type of the following linked list:

typedef int DataType;
class Item {
    
    
public:
	DataType data;
	Item* next;
	Item() = default;
	Item(int x ):data(x),next(nullptr){
    
    }
	Item(int x,Item* next):data(x),next(next){
    
    }
};

class Link {
    
    
public:
	Item* head; //链表头指针
	Link() {
    
     head = NULL; }	//构造函数
	~Link() {
    
     DeleteAll(); }	//析构函数
	void Initiate();	//初始化
	void DeleteAll();	//删除所有结点
	void HeadCreateWithHead(int n);	//从头建立带表头的链表
	void TailCreateWithHead(int n);	//从尾建立带表头的链表
	int Length();			//求链表长度
	Item* LocateX(DataType x);	//查找值为x的元素
	Item* LocateI(int i);		//查找第i个元素
	DataType Get(int i);		//取第i个元素
	bool InsertHead(DataType x, int i);//在第i个结点前插入x
	bool InsertTail(DataType x, int i);//在第i个结点后插入x
	bool Deleted(int i);		//删除第i个结点
	void Print();

};

The specific algorithm is as follows

void Link::Initiate() {
    
    
	DeleteAll();
	head = NULL;
}

void Link::DeleteAll() {
    
    
	Item* p = head, * q;
	while (p != NULL) {
    
    
		q = p->next;
		delete p;
		p = q;
	}
	head = NULL;
}

void Link::HeadCreateWithHead(int n) {
    
    
	DeleteAll();
	Item* p, * s;
	p = new Item();//给头指针分配内存
	p->next = NULL;//初始时刻头指针为空
	for (int i = 1; i <= n; ++i) {
    
    
		s = new Item();
		cin >> s->data;
		s->next = p->next;
		p->next = s;
	}
	head = p;
}

void Link::TailCreateWithHead(int n) {
    
    
	DeleteAll();
	Item* p, * s, * r;
	p = new Item();
	p->next = NULL;
	r = p;
	for (int i = 1; i <= n; ++i) {
    
    
		s = new Item();
		cin >> s->data;
		r->next = s;
		r = s; //令r也指向s
	}
	r->next = NULL;
	head = p;
}

int Link::Length() {
    
    
	Item* p;
	p = head->next;
	int j = 0;
	while (p != NULL) {
    
    
		++j;
		p = p->next;
	}
	return j;
}

Item* Link::LocateX(DataType x) {
    
    
	//返回该节点的指针
	Item* p;
	p = head->next;
	while ((p != NULL) && (p->data != x))
		p = p->next;
	if (p)
		return p;
	else {
    
    
		cout << x << "不存在此链表中" << endl;
		return NULL;
	}
}

Item* Link::LocateI(int i) {
    
    
	//返回该节点的指针
	Item* p;
	int j = 1;
	p = head->next;
	if (i == 0) return head;
	while ((p != NULL) && (j < i)) {
    
    
		p = p->next;
		++j;
	}
	if (j==i)
		return p;
	else {
    
    
		cout << "位置错误" << endl;
		return NULL;
	}
}

DataType Link::Get(int i) {
    
    
	Item* p;
	p = head->next;
	int j = 1;
	while ((j < i) && (p != NULL)) {
    
    
		++j;
		p = p->next;
	}
	if ((p == NULL) || (j > i)) {
    
    
		cout << "位置错误" << endl;
		return NULL;
	}
	else
	{
    
    
		return p->data;
	}
}

bool Link::InsertHead(DataType x, int i) {
    
    
	Item* p, * s;
	p = LocateI(i - 1);
	if (p == NULL) {
    
    
		cout << "位置错误" << endl;
		return NULL;
	}
	s = new Item();
	s->data = x;
	s->next = p->next;
	p->next = s;
	return true;
}

bool Link::InsertTail(DataType x, int i) {
    
    
	Item* p, * s;
	p = LocateI(i);
	if (p == NULL) {
    
    
		cout << "位置错误" << endl;
		return NULL;
	}
	s = new Item();
	s->data = x;
	s->next = p->next;
	p->next = s;
	return true;
}

bool Link::Deleted(int i) {
    
    
	Item* p,*q;
	p = LocateI(i - 1);
	if (p == NULL) {
    
    
		cout << "位置错误" << endl;
		return false;
	}
	q = p->next;
	if (q != NULL) {
    
    
		p->next = q->next;
		delete q;
		return true;
	}
	else {
    
    
		cout << "位置错误" << endl;
		return false;
	}

}

void Link::Print() {
    
    
	Item* p;
	p = head->next;
	while (p != NULL) {
    
    
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}
int main()
{
    
    
	Link L;
	L.TailCreateWithHead(5);
	L.Print();

	system("pause");
	return 0;	
}

3. Linked storage structure of linear list - circular linked list

For a singly linked list, the pointer field of the last node is a null pointer. If the head pointer of the linked list is placed in the pointer field, the head and tail nodes of the linked list are connected to form a circular singly linked list.
insert image description here
The connection operation of the two circular singly linked lists H1 and H2 is to connect the first data node of H2 to the tail node of H1. If the head pointer is used to identify, you need to find the tail node of the first linked list, and its time complexity is O(n); and if the linked list is marked with tail pointers R1 and R2, the time complexity is O(1). The operation is as follows:

p= R1->next;                  //保存R1的头结点指针
R1->next=R2->next->next;      //头尾连接
delete  R2->next;              //释放第二个表的头结点
R2->next=p;                   //组成循环链表​​

3. Linked storage structure of linear list - doubly linked list

Add a pointer field pointing to the predecessor in front of each node, which is a doubly linked list
insert image description here
1, insert operation

① s->prior=p->prior;
② p->prior->next=s;
③ s->next=p;
④ p->prior=s;​​

2. Delete operation

① p->prior->next=p->next;
② p->next->prior=p->prior;
    delete  p;​​

Two, the stack

  • A stack is a linear list that restricts insertion and deletion to one end of the list.
  • The end of the table that allows insertion and deletion is called the top of the stack, and the current position of the top of the stack is dynamically changed;
  • The other end that does not allow insertion and deletion is called the bottom of the stack, and the bottom of the stack is fixed.
  • When there are no elements in the list it is called an empty stack.
  • The insertion operation of the stack is called push, push or push, and the deletion operation of the stack is called unstack or pop.
  • The order of pushing into the stack is e1, e2, e3, and the order of popping out of the stack is e3, e2, e1, so the stack is also called Last In First Out (Last In First Out), referred to as LIFO table, or first in last out linear table . It is characterized by first in first out or last in first out.

1. Sequential stack

As the name implies, a stack implemented using sequential storage is called a sequential stack.
Similar to the definition of the sequence table, to allocate a continuous storage space to store the elements in the stack, the bottom position of the stack can be fixedly set at any end of the array (generally at the end with the subscript 0), and the top of the stack follows the insertion and Delete and change, and then use a variable to indicate the position of the current top of the stack (actually the next position of the top element of the stack).

typedef int DataType;

class SeqStack {
    
    
private:
	DataType* base;//栈底指针
	DataType* top;//栈顶指针,始终指向栈顶元素的最后一个位置
	int size;//栈的大小

public:
	SeqStack(int stacksize = 100) {
    
    
		base = new DataType[stacksize];
		top = base;
		size = stacksize;
	}
	~SeqStack() {
    
    
		delete[] base;
		top =NULL;
		base = NULL;
	}
	int Empty_Stack();               //判断栈是否为空
	int Push_Stack(DataType e);      //将元素e插入栈顶
	int Pop_Stack(DataType& e);      //从栈顶删除一个元素到e中返回
	int GetTop_Stack(DataType& e);    //从栈顶取出一个元素到e中返回
	void Print();
};

int SeqStack::Empty_Stack() {
    
    
	return ((top <= base)); //top≤base为空栈,返回1
}

int SeqStack::Push_Stack(DataType e) {
    
    
	if ((top - base) < size) {
    
    		//判断是否满栈
		*top = e;
		++top;
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}

int SeqStack::Pop_Stack(DataType& e) {
    
    
	if (top > base) {
    
    		//判断栈是否为空
		--top;	//栈顶top指向的是栈顶元素的后一位置
		e = *top;
		return 1;
	}
	else
		return 0;
}

int SeqStack::GetTop_Stack(DataType& e) {
    
    
	if (top > base) {
    
    		//判断栈是否为空
		e = *(top-1);//栈顶top指向的是栈顶元素的后一位置
		return 1;
	}
	else
		return 0;
}

void SeqStack::Print() {
    
    
	int i = 0;
	while ((top-i)>base ) {
    
    
		cout << *(top-1-i) << " ";
		++i;
	}
}

int main()
{
    
    
	SeqStack S;
	S.Push_Stack(1);
	S.Push_Stack(2);
	S.Push_Stack(3);
	S.Push_Stack(4);
	S.Print();
	system("pause");
	return 0;	
}

2. Chain stack

Generally, the chain stack is represented by a singly linked list.
Because the main operation in the chain stack is to perform insertion and deletion operations on the top of the stack, it is obviously more convenient to insert and delete at the head of the singly linked list, so the head pointer is used as the top of the stack, and there is no need to do it for the convenience of operation like a singly linked list. Append a header node.
insert image description here

typedef int DataType;

class StackNode {
    
    
public:
	DataType data;
	StackNode* next;
	StackNode() = default;
	StackNode(int x) :data(x), next(nullptr) {
    
    }
	StackNode(int x, StackNode* next) :data(x), next(next) {
    
    }
};

class LinkStack {
    
    
private:
	StackNode* top;
public:
	LinkStack() {
    
    
		top = NULL;
	}
	~LinkStack() {
    
    
		StackNode* p;
		while (top) {
    
    
			p = top;
			top = top->next;
			delete p;
		}
		top = NULL;
	}
	int Empty_Stack();		//判断是否为空栈
	int Push_Stack(DataType e);//将元素e插入栈顶
	int Pop_Stack(DataType& e);//从栈顶删除一个元素到e中返回
	int GetTop_Stack(DataType& e);//从栈顶取出一个元素到e中返回
	void Print();
};

int LinkStack::Empty_Stack() {
    
    
	return (!top);
}

int  LinkStack::Push_Stack(DataType e) {
    
    
	//入栈操作是在栈的顶部进行插入操作,相当于在单链表的表头(第一个元素之前)插入一个新元素。
	StackNode* p = new StackNode();
	if (p) {
    
    
		p->data = e;
		p->next = top;
		top = p;
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}

int LinkStack::Pop_Stack(DataType& e) {
    
    
	StackNode* p;
	if (top) {
    
    
		p = top;
		e = p->data;
		top = top->next;
		delete p;
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}

int LinkStack::GetTop_Stack(DataType& e) {
    
    
	if (top) {
    
    
		e = top->data;
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}

void LinkStack::Print() {
    
    
	StackNode* p;
	p = top;
	while (p) {
    
    
		cout << p->data << " ";
		p = p->next;
	}
}
int main()
{
    
    
	LinkStack L;
	L.Push_Stack(1);
	L.Push_Stack(2);
	L.Push_Stack(3);
	L.Push_Stack(4);
	L.Print();
	system("pause");
	return 0;	
}

3. Queue

  • A queue is also a special kind of linear table, which is a linear table restricted to insert at one end of the table and delete at the other end.
  • The end of the table that allows insertion is called the rear, and the end that allows deletion is called the front.
  • When there are no elements in the list it is called an empty queue.
  • The insertion operation of the queue is called entering the queue or entering the queue, and the deletion operation of the queue is called dequeuing or dequeuing.
  • The order of entering the queue is e1, e2, e3, e4, e5, and the order of leaving the queue is e1, e2, e3, e4, e5, so the queue is also called First In First Out (FIFO table) . It is characterized by first in first out or last in last out.
    insert image description here

1. Sequence - circular queue

A sequentially stored team is called a sequential team. A continuous storage space must be allocated to store the elements in the queue. Since both the head and the tail of the queue are active, there are two pointers for the head and tail of the queue. It is stipulated here that the queue head pointer points to the previous position of the actual queue head element, and the queue tail pointer points to the position of the actual queue tail element.
Since the sequential queue is statically allocated storage, the operation of the queue is a dynamic process:

  • The operation of entering the queue is to insert an element at the position of rear plus 1 at the end of the queue, and the queue is full when rear moves to the last position of the space;
  • The dequeue operation is to delete an element at the head of the queue, without moving the element, and modify the queue head pointer front plus 1. But this method has false overflow.

The false overflow of the queue is due to the fact that in order to avoid moving elements when deleting elements out of the queue, only the pointer of the head of the queue is modified, which will cause the entire queue to move backward as the queue enters and exits, and the following figure appears The situation shown: the pointer at the end of the queue has moved to the end, and overflow will occur if any element enters the queue, but in fact, the queue is not really "full" at this time, this phenomenon is "false overflow".
insert image description here
One of the methods to solve the false overflow is to connect the data area of ​​the queue head to tail, and the relationship between the head and tail pointers remains unchanged. It is called a circular queue
insert image description here
because it is a circular structure connected from head to tail. When entering the queue, add 1 to the tail pointer to modify it. It is:
rear=(rear+1)% size; (size is the size of the sequential queue space); the
operation of adding 1 to the queue head pointer when leaving the queue is changed to: front=(front+1)% size.
In this way, when the size is reached, it returns to 0 again.

Empty team: front=rear;
full team: if entering the team is faster than leaving the team, the team full condition is also front=rear. Therefore, a different approach is needed.

  • 1. The number of elements in the storage team is num. When num=0, it is empty; when num=size, the team is full
  • 2. Use one less element space, that is, when the tail of the team + 1 is equal to the head of the team, the team is considered full. Judgment condition: (rear+1)%size=front

The second judgment is used below

typedef int DataType;
class SeqQueue {
    
    
private:

	DataType* data;
	int front;
	int rear;
	int size;
public:
	SeqQueue(int QueueSize = 100) {
    
    		//构造一个空队列,默认空间大小100
		data = new DataType[QueueSize];
		front = 0;
		rear = 0;
		size = QueueSize;
	}
	~SeqQueue() {
    
    
		delete[]  data;
	}

	int Empty_Queue();                 //判断队列是否为空
	int En_Queue(DataType e);          //入队将元素e插入队尾
	int De_Queue(DataType& e);         //出队从队头删除一个元素到e中返回
	int Front_Queue(DataType& e);      //取队头元素,从队头取出一个元素到e中返回
	void Print();
};

int SeqQueue::Empty_Queue() {
    
    
	return (front == rear);
}

int SeqQueue::En_Queue(DataType e){
    
    
	if ((rear+1)%size !=front) {
    
    
		rear = (rear + 1) % size;
		data[rear] = e;
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}

int SeqQueue::De_Queue(DataType& e) {
    
    
	if (rear != front) {
    
    
		front = (front + 1) % size;//因为队列的fron指向头元素的前一位置
		e = data[front];
		return 1;
	}
	else
		return 0;
}

int SeqQueue::Front_Queue(DataType& e) {
    
    
	if (rear != front) {
    
    
		e = data[(front + 1) % size];
		return 1;
	}
	else
		return 0;
}

void SeqQueue::Print() {
    
    
	int i;
	i = rear;
	while (i != front) {
    
    
		cout << data[i] << " ";
		--i;
	}
	cout << endl;
}

int main()
{
    
    
	SeqQueue S;
	S.En_Queue(1);
	S.En_Queue(2);
	S.En_Queue(3);
	S.En_Queue(4);
	S.Print();
	DataType e;
	S.De_Queue(e);
	S.Print();
	cout << e << endl;
	system("pause");
	return 0;	
}

2. Chain queue

Use a linear chain to represent the queue, generally a singly linked list.
The head pointer and the tail pointer respectively point to the head and tail elements of the chain queue, and have a head node.
insert image description here

typedef int DataType;

class QueueNode {
    
    
public:
	DataType data;
	QueueNode* next;
};

class LinkNode {
    
    
private:
	QueueNode* front;;
	QueueNode* rear;
public:
	LinkNode() {
    
    
		QueueNode* s = new QueueNode;
		s->next = NULL;
		front = rear = s;
	}
	~LinkNode() {
    
    
		QueueNode* p, * q;
		p = front;
		while (p) {
    
    
			q = p;
			p = p->next;
			delete q;
		}
	}
	int Empty_Queue();                      //判断队列是否为空
	int En_Queue(DataType e);               //将元素e插入队尾
	int De_Queue(DataType& e);              //从队头删除一个元素到e中返回
	int Front_Queue(DataType& e);           //从队头取出一个元素到e中返回
	void Print();
};

int LinkNode::Empty_Queue() {
    
    
	return (front ==rear);
}

int LinkNode::En_Queue(DataType e) {
    
    
	QueueNode* p = new QueueNode;
	if (p) {
    
    
		p->data = e;
		p->next = NULL;
		rear->next = p;
		rear = p;
		return 1;
	}
	else {
    
    
		return 0;
	}
}

int LinkNode::De_Queue(DataType& e) {
    
    
	QueueNode* p;
	if (!Empty_Queue()) {
    
    
		p = front->next;
		e = p->data;
		front->next = p->next;
		if (p->next==NULL) {
    
    	//如果删除的是最后一个结点,需要单独处理,令rear=front。否则rear指针会随着p一起被删除
			rear = front;
		}
		delete p;
		return 1;
	}
	else
		return 0;
}

int LinkNode::Front_Queue(DataType& e) {
    
    
	QueueNode* p;
	if (!Empty_Queue()) {
    
    
		p = front->next;
		e = p->data;
		return 1;
	}
	else
		return 0;
}

void LinkNode::Print() {
    
    
	QueueNode* p = front->next;
	while (p != NULL) {
    
    
		cout << p->data<<" ";
		p = p->next;
	}
	cout << endl;
}

int main()
{
    
    
	LinkNode L;
	L.En_Queue(1);
	L.En_Queue(2);
	L.En_Queue(3);
	L.Print();
	DataType e;
	L.Front_Queue(e);
	cout << e << endl;
	system("pause");
	return 0;

}

Four, string

constexpr int strLength(char c[]) {
    
    
	//求串长
	int i = 0;
	while (c[i] != '\0') {
    
    
		++i;
	}
	return i;
}

int StrConcatl(char *c1, char *c2,char *c) {
    
    
	//链接串c1,c2,组成c
	int i = 0, j, len1, len2;
	len1 = strLength(c1);
	len2 = strLength(c2);
	j = 0;
	while (c1[j] != '\0') {
    
    
		c[i] = c1[j];
		++i;
		++j;
	}
	j = 0;
	while (c2[j] != '\0') {
    
    
		c[i] = c2[j];
		++i;
		++j;
	}
	return 1;
}

int StrSub(char* t, char* s, int i, int len) {
    
    
	//用t接收串s中从第i个字符开始的长度为len的子串
	int slen;
	slen = strLength(s);
	if (1 < 1 || i > slen || len<0 || len>slen - i + 1) {
    
    
		cout << "参数不对" << endl;
		return 0;
	}
	int j;
	for (j = 0; j <= len; ++j) {
    
    
		t[j] = s[i + j - 1];
	}
	t[j] = '\0';
	return 1;

}

int StrComp(char* s1, char* s2) {
    
    
	int i = 0;
	while (s1[i] == s2[i] && s1[i] != '\0')
		++i;
	return (s1[i] == s2[i]);
}

int main()
{
    
    
    char s1[] = "abcdef";
	char s2[] = "english";
	char s3[]= "abcdef";
	char s[20];
	StrConcatl(s1, s2, s);
	cout << s << endl;
	char t[5];
	StrSub(t, s1, 1, 3);
	cout << t << endl;

	cout << StrComp(s1, s3) << endl;
	system("pause");
	return 0;

}

Summarize

Guess you like

Origin blog.csdn.net/Ricardo2/article/details/126570462