Bootstrap

C语言题目代码总结解析

目录

简单版三子棋实现

简单的扫雷的实现 

简单的通讯录实现

最大公约数----辗转相除法

判断一个数是否是素数 

二分查找----有序数组查找

递归实现字符串反转

递归实现汉诺塔问题

青蛙跳台阶问题

几个字符串库函数的实现  

qsort的冒泡实现版本 

杨式矩阵 

字符串左旋 


简单版三子棋实现

实现的功能和总体结构概述

  •  目标  为了实现三子棋的游戏
  • game.h 头文件为了实现函数定义和符号定义
  • game.cpp实现程序所有需要的函数
  • test.cpp 实现程序的逻辑
  • void printCaiDan();//这个函数用来打印菜单
  • void Initarr(char arr[ROW][COW],int row,int cow);//这个函数用来初始化数组内容都为空格
  • void printQiPan(char arr[ROW][COW], int row, int cow);//打印棋盘
  • void PlayerMove(char arr[ROW][COW], int row, int cow);//模拟玩家下棋
  • void ComputerMove(char arr[ROW][COW],int row,int cow);//模拟电脑下棋
  • char IsWin(char arr[ROW][COW],int row, int cow);//判断玩家赢还是电脑赢还是平局或者是继续游戏
  • char IsFull(char arr[ROW][COW], int row, int cow);//判断棋盘是不是已经满了

打印菜单函数

void printCaiDan()
{
	printf("**********************************************\n");
	printf("*************玩游戏输入1,退出输入0************\n");
	printf("**********************************************\n");
	printf("**********************************************\n");
}

 初始化二维数组函数 

void Initarr(char arr[ROW][COW], int row, int cow)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < cow; j++)
		{
			arr[i][j] = ' ';
		}
	}
}

打印棋盘 

void printQiPan(char arr[ROW][COW], int row, int cow)
{
    /*int i = 0;
    for ( i = 0; i <row; i++)
    {
    printf(" %c | %c | %c ", arr[i][0], arr[i][1], arr[i][2]);
    if (i<row-1)
        {
        printf("---|---|---");
    }  
  只能实现3字棋盘的打印}
    */     
//可以实现任意大小棋盘的打印    //将效果图的图案先输出  * | * | *     
//                                      然后输出 ___|___|___
    int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < cow; j++)
		{
			printf(" %c ", arr[i][j]);
			if (j < cow - 1)
			{
				printf("|");
			}

		}
		//这个循环实现输出  * | * | *   
		printf("\n");
		if (i<row-1)
		{

		int j = 0;
		for ( j = 0; j < cow; j++)
		{
			printf("---");
			if (j<cow-1)
			{
				printf("|");
			}
		}
		//这个循环实现输出 ___|___|___
		printf("\n");
		}
	}
}

效果图

81a69870695047f58a514188b44dc6be.png

 模拟玩家出棋

void PlayerMove(char arr[ROW][COW], int row, int cow)
{
	int i = 0;
	int j = 0;
	printf("玩家开始下棋\n");
	while (1)
	{
		printf("请输入你想下棋的坐标——>\n");
		scanf("%d%d", &i, &j);
		if (i >= 1 && j >= 1 && i <= row && j <= cow)//判断坐标是否合法
		{
			if (arr[i - 1][j - 1] == ' ')//判断这个位置是否已经被使用过
			{
				arr[i - 1][j - 1] = '*';
				break;
			}
			else
			{
				printf("这个坐标已经被占用,请重新输入\n");
			}

		}
		else
		{
			printf("输入坐标非法,请重新输入\n");
		}
	}
}

模拟电脑下棋

void ComputerMove(char arr[ROW][COW], int row, int cow)
{
	int i = 0;
	int j = 0;
	printf("电脑开始下棋\n");
	while (1)
	{
		i = rand() % ROW;//利用随机数函数将i控制在0到ROW-1
		j = rand() % COW;//利用随机数函数将j控制在0到COW-1
		if (arr[i ][j ] == ' ')//判断这个坐标是否被占用
		{
			arr[i ][j ] = '#';
			break;
		}
	}
}

 判断游戏输赢

  • c表示游戏继续
  • p表示游戏平局
  • *表示玩家胜利
  • #表示电脑胜利
char IsFull(char arr[ROW][COW], int row, int cow)
{
	//判断是否平局
	int i = 0;
	int j = 0;
	for ( i = 0; i <row; i++)
	{
		for ( j = 0; j < cow; j++)
		{
			if (arr[i][j] == ' ')
			{
				return 'C';//如果存在一个空格,则说明还能继续下棋
			}
		}
	}
	return 'P';//表示棋盘已经满了,表示平局
}
char IsWin(char arr[ROW][COW], int row, int cow)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)//判断三行
	{
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
		{
			return arr[i][0];
		}
	}
	for (i = 0; i < cow; i++)//判断三列
	{
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
		{
			return arr[0][i];
		}
	}
	if (arr[0][0] == arr[1][1] && arr[2][2] == arr[1][1] && arr[1][1] != ' ')//判断左对角线
	{
		return arr[1][1];
	}
	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')//判断右对角线
	{
		return arr[1][1];
	}
	//判断平局
	char full = IsFull(arr, cow, row);//判断是否棋盘是否满了
	return full;
	//这个算法非常低级,只能实现简单的三子棋,不能实现更大的五子棋,需要学习算法来完成
}

game.h  

#pragma once
//这个头文件是用来被引用的,里面定义了需要的符号常量,和相关函数的声明
#include<stdio.h>//在头文件引入这个,在调用这个头文件就不需要再次去调用这个库函数
#include<stdlib.h>//提供随机数的函数
#include<time.h>//提供随机值的
#define ROW 3//定义所需二维数组的列长
#define COW 3//定义所需二维数组的行长
void printCaiDan();//这个函数用来打印菜单
void Initarr(char arr[ROW][COW],int row,int cow);//这个函数用来初始化数组内容都为空格
void printQiPan(char arr[ROW][COW], int row, int cow);//打印棋盘
void PlayerMove(char arr[ROW][COW], int row, int cow);//模拟玩家下棋
void ComputerMove(char arr[ROW][COW],int row,int cow);//模拟电脑下棋
char IsWin(char arr[ROW][COW],int row, int cow);//判断玩家赢还是电脑赢还是平局或者是继续游戏
char IsFull(char arr[ROW][COW], int row, int cow);//判断棋盘是不是已经满了

test.cpp  

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
	char arr[ROW][COW];//定义所需要存储棋盘数据的空间
	Initarr(arr,ROW,COW);//将这个数组的内容都初始化为空格
	printQiPan(arr, ROW, COW);//将棋盘打印出来
	char ret = 0;
	while (1)
	{
		PlayerMove(arr, ROW, COW);//这个函数模拟玩家下棋
		printQiPan(arr, ROW, COW);//打印棋盘
		 ret=IsWin(arr, ROW, COW);
		if (ret!='C')
		{
			break;
		}
		ComputerMove(arr, ROW, COW);//模拟电脑下棋
		printQiPan(arr, ROW, COW);//打印棋盘
		ret = IsWin(arr, ROW, COW);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret== '*')
	{
		printf("玩家胜利\n");
		printQiPan(arr, ROW, COW);//将棋盘打印出来
	}
	 if (ret == '#')
	{
		printf("电脑胜利\n");
		printQiPan(arr, ROW, COW);//将棋盘打印出来
	}
	 if (ret=='P')
	{
		printf("平局\n");
		printQiPan(arr, ROW, COW);//将棋盘打印出来
		
	}

}
int main()
{
	int input=0;
	srand((unsigned int)time(NULL));
	do
	{
		printCaiDan();
		printf("请输入——》");
		scanf("%d", &input);
		switch (input)
			{
			case 1:
				game();
				break;
			case 0:
				printf("结束游戏\n");
				break;
			default:
				printf("输入非法字符,请重新输入\n");
				break;
			}
		
	} while (input);
	
	return 0;
}

简单的扫雷的实现 

实现的功能和总体结构

  • 功能:实现简单的扫雷,只能一个一个排除雷,不能一片展开
  • game.h 头文件为了实现函数定义和符号定义
  • game.cpp实现程序所有需要的函数
  • test.cpp 实现程序的逻辑
  • void printmeun();输出菜单
  • void Initarr(char arr[ROWS][COLS], int rows, int cols, char set);//初始化棋盘的
  • void Displayarr(char arr[ROWS][COLS], int row, int col);//打印棋盘
  • void Setarr(char arr[ROWS][COLS], int row, int col);//布置雷
  • void Findarr(char arr[ROWS][COLS], char arr1[ROWS][COLS], int row, int col);//排查雷

game.h 

#include<time.h>//提供time的函数
#include<stdlib.h>//提供随机数函数
#define ROW 9//定义行
#define COL 9//定义列
#define ROWS ROW+2//定义整体的行 因为这样定义好给旁边的点计算有多少个雷
#define COLS COL+2//定义整体的列
#define COUNT 10//定义有多少个雷
void printmeun();

//初始化棋盘的
void Initarr(char arr[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void Displayarr(char arr[ROWS][COLS], int row, int col);

//布置雷
void Setarr(char arr[ROWS][COLS], int row, int col);
//排查雷
void Findarr(char arr[ROWS][COLS], char arr1[ROWS][COLS], int row, int col);

test.cpp 

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
	char arr[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char arr1[ROWS][COLS] = { 0 };//存放好排除的雷的信息
	//初始化棋盘
	Initarr(arr, ROWS, COLS, '0');//'0'
	Initarr(arr1, ROWS, COLS, '*');//'*'

	//打印一下棋盘
	Displayarr(arr, ROW, COL);
	Displayarr(arr1, ROW, COL);
	//布置雷
	Setarr(arr, ROW,COL);
	/*Displayarr(arr, ROW, COL);*/

	排查雷
	Findarr(arr, arr1, ROW, COL);
}
int main()
{
	
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		printmeun();
		printf("请选择-》");
		scanf("%d" ,&input);
		switch (input)
		{
		case 1:
			printf("开始扫雷游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输出非法字符,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

打印菜单  

void printmeun()
{
	printf("**************************\n");
	printf("**************************\n");
	printf("*** 退出选0, 玩游戏选1 ***\n");
	printf("**************************\n");
	printf("**************************\n");
}

 初始化棋盘

//初始化棋盘的
void Initarr(char arr[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for ( i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

打印棋盘

void Displayarr(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("---扫雷游戏开始了---\n");
	for ( i = 0; i <=col; i++)
	{
		printf("%d ", i);//打印出0 1 2.。。。。。9能知道属于那一列
	}
	printf("\n");
	for ( i = 1; i <= row; i++)
	{
		printf("%d ", i);//能知道属于那一行
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_8,color_FFFFFF,t_70,g_se,x_16

布置雷 

void Setarr(char arr[ROWS][COLS], int row, int col)
{
	int i;
	int j;
	int count =COUNT;//一共布置count个雷
	while (count)
	{
		i = rand() % 9 + 1;
		j = rand() % 9 + 1;
		if (arr[i][j]=='0')//如果这个地方不是雷,就可以设置为雷
		{
			arr[i][j] = '1';
			count--;
		}
	}
}

排查雷 

static int get_arr_num(char arr[ROWS][COLS], char arr1[ROWS][COLS], int x, int y)
{
	int num=0;
	for (int  i = -1; i <= 1; i++)
	{
		for (int j = -1; j <= 1; j++)
		{
			num +=( arr[x+i][y+j] - '0');
		}
	}
	//将arr[x][y]周围排除一遍 如果是'1'-0就是整型1    
	//将'0'-'0'为整数0
	//不用查arr[x][y]因为arr[x][y]进这个函数肯定是‘0’
	return num;
}

//排查雷
void Findarr(char arr[ROWS][COLS], char arr1[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - COUNT)
	{
		printf("请输入你想查的点的坐标\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) //判断坐标是否合法
		{
			if (arr[x][y] == '1')
			{
				printf("你踩到雷了,游戏结束");
				Displayarr(arr, ROW, COL);
				break;
			}
			else
			{
				arr1[x][y] = (get_arr_num(arr, arr1, x, y) + '0');//8+'0'就变成了'8'的ASCII码
				win++;
				Displayarr(arr1, ROW, COL);
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win== row * col - COUNT) //一个count个雷 一共row*col,所以只要玩row * col - COUNT次就说明游戏胜利
	{
		printf("恭喜你,排雷成功\n");
		Displayarr(arr, row, col);
	}
}

简单的通讯录实现

实现的功能和总体概述

  • 实现简单的通讯录信息存储功能
  • 三个版本 静态版本  动态版本 文件版本
  • 静态版本 1通讯录能存放1000个人的信息 2每个人的信息是学号+姓名+性别+年龄+电话+地址 3增加人的信息 4删除人的信息 5修改指定人信息 6查找指定人 7将通讯录按学号排序
  •  动态版本 由于静态版本每次都开辟1000个空间,可能用不掉,所以会导致内存浪费在动态内存区开辟空间,一开始只开辟3个大小的空间当空间满了,增加2个信息
  •  文件版本 当通讯录退出的时候,将信息写入文件 当通讯录初始化的时候,加载文件的信息进通讯录中
  • Concst.h 头文件为了实现函数定义和符号定义
  • Concst.cpp实现程序所有需要的函数
  • test.cpp 实现程序的逻辑
  • void menu() 打印菜单函数
  • void Initcon(Concst* con) 初始化通讯录的函数 三个版本的功能都不一样
  • void AddInformation(Concst *con) 添加信息的函数 动态和静态的版本不一样
  • void PrintInformation(Concst* con) 打印通讯录的内容
  • int FindInformation_NUM(Concst* con, char* p) 寻找num为*p的信息
  • void DelteInformation(Concst* con)删除信息的函数
  • void SearchInformation_num(Concst* con) 查找信息的函数并输出
  • void ModifyInformation_num(Concst* con )修改指定num的数据
  • void SORTInformation_num(Concst* con) 将通讯录以num排序
  • void DestoryCon(Concst* con)释放通讯录的空间,是动态和文件版本的专属
  • SaveCon(Concst* con)将通讯录的内容放入文件中存储

 Concst.h

#pragma once
//版本1静态版本
//1通讯录能存放1000个人的信息
//2每个人的信息是学号+姓名+性别+年龄+电话+地址
//3增加人的信息
//4删除人的信息
//5修改指定人信息
//6查找指定人
//7将通讯录按学号排序

//版本二 动态版本
//由于静态版本每次都开辟1000个空间,可能用不掉,所以会导致内存浪费
//在动态内存区开辟空间,一开始只开辟3个大小的空间
//当空间满了,增加2个信息

//版本三 文件版本
//当通讯录退出的时候,将信息写入文件
//当通讯录初始化的时候,加载文件的信息进通讯录中
#include<stdio.h>//引入标志输入输出库
#include<stdlib.h>//用malloc开辟动态空间
#include<string.h>//用memest来初始化通讯录内存
#define MAX_NAME 10//名字的最大长度
#define MAX_NUM 10//学号的最大长度
#define MAX_SEX 5//性别的最大长度
#define MAX_TELE 12//电话的最大长度
#define MAX_ADD 20//地址的最大长度
#define MAX 1000//静态通讯录的最大存储人数
#define DEFAULT_SIZE 3//动态刚开始初始化的通讯录能存储的人数
#define INC_SZ 2//动态内存不够时,每次增加的通讯录存储人数的大小
typedef struct PeoInfo
{
	char num[MAX_NUM];//学号 唯一标识的
	char name[MAX_NAME];//姓名
	char sex[MAX_SEX];//性别
	int age;//年龄
	char tele[MAX_TELE];//电话
	char add[MAX_ADD];//地址

}PeoInfo;//定义存储一个人信息的结构体类型
typedef struct Concst
{
	//静态版本
	//	int sz;//表示现在通讯录里有多少个人的信息
	//	PeoInfo date[MAX];//存放放进来人的信息
	//动态版本
	int sz;//表示现在通讯录有多少人的信息
	PeoInfo* date;//定义一个指针,指向存储人的信息的首地址
	int capacity;//表示现在的存储空间有多大
};//定义通讯录的结构体类型
void menu();
void Initcon(Concst* con);
void AddInformation(Concst *con);
void PrintInformation(Concst* con);
void DelteInformation(Concst* con);
int FindInformation_NUM(Concst* con, char* p);
void SearchInformation_num(Concst* con);
void ModifyInformation_num(Concst *con);
void SORTInformation_num(Concst* con);
void DestoryCon(Concst* con);
void SaveCon(Concst* con);
void Load

test.h 

#define _CRT_SECURE_NO_WARNINGS 1
#include"Concst.h"
enum OPtion//定义一个枚举变量来表示对应的操作
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};
int main()
{
	int input;
	Concst con;
	Initcon(&con);//初始化通讯录
	do
	{
		menu();
		printf("请输入你需要的功能");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:
			//动态版本要销毁通讯录
		/*	DestoryCon(&con);*/
			//文件版应该先保存信息进文件,然后再销毁
			SaveCon(&con);//保存信息
			DestoryCon(&con);
			break;
		case ADD:
			//添加人的信息
			AddInformation(&con);
			break;
		case DEL:
			//删除人的信息
			DelteInformation(&con);
			break;
		case SEARCH:
			//用学号来查找一个人的信息
			SearchInformation_num(&con);
			break;
		case MODIFY:
			//修改学号指定的人的信息
			ModifyInformation_num(&con);
			break;
		case SORT:
			//按照学号来排序
			SORTInformation_num(&con);
			break;
		case PRINT:
			PrintInformation(&con);
			break;
		default:
			break;
		}
	} while (input);

}

实现打印菜单的函数 

void menu()
{
	printf("************************************\n");
	printf("****1 添加	2删除*******************\n");
	printf("****3 查询	4修改*******************\n");
	printf("****5 排序	6打印*******************\n");
	printf("****0 退出	************************\n");
	printf("************************************\n");
}

实现初始化通讯录的函数 

void Initcon(Concst* con)
{
	//静态版本
	//con->sz = 0;
	//memset(con->date, 0, sizeof(con->date));//完成通讯录的存储数据的初始化
	
	//动态版本
	con->date= (PeoInfo*)malloc(DEFAULT_SIZE * sizeof(PeoInfo));
	if (con->date==NULL)
	{
		perror("Initcon");
		return;
	}
	con->sz = 0;
	con->capacity = DEFAULT_SIZE;
	//加载文件
	LoadCon(con);
}
void LoadCon(Concst* con)//加载文件信息进通讯录
{
	FILE* pf = fopen("contact.dat", "r");
	if (pf==NULL)
	{
		perror("LoadCon");
		return;
	}
	//读文件 fread每次最多读count个,如果可以读到count个就返回count,
	// 如果读不到,就返回一个比count小的值,表示读取结束
	PeoInfo tmp = { 0 };
	
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		if (con->sz == con->capacity)
		{
			printf("空间不够,增加容量\n");
			PeoInfo* ptr = (PeoInfo*)realloc(con->date, (con->capacity + INC_SZ) * sizeof(PeoInfo));
			if (ptr != NULL)
			{
				con->date = ptr;
				con->capacity += INC_SZ;
				printf("增容成功\n");
			}
			else
			{
				perror("AddInformation");
				printf("增加类型失败");
				return;
			}
		}
		con->date[con->sz] = tmp;
		con->sz++;
	}
	printf("文件导入成功\n");
	//关闭文件
	fclose(pf);
	pf = NULL;
}

实现通讯录增加人的信息的函数

/ //静态版本的增加联系人
void AddInformation(Concst* con)
{
	if (con->sz==MAX)
	{
		printf("通讯录已经满了,添加失败\n");
		return;
	}
	else
	{
		printf("请输入学号->");
		scanf("%s", con->date[con->sz].num);
		printf("请输入名字->");
		scanf("%s", con->date[con->sz].name);
		printf("请输入性别->");
		scanf("%s", con->date[con->sz].sex);
		printf("请输入年龄->");
		scanf("%d",&( con->date[con->sz].age));
		printf("请输入电话->");
		scanf("%s", con->date[con->sz].tele);
		printf("请输入地址->");
		scanf("%s", con->date[con->sz].add);
		con->sz++;
		printf("信息输入成功\n");
	}
}

 

//动态版本的增加联系人 
void AddInformation(Concst* con)
{
	if (con->sz==con->capacity)
	{
		printf("空间不够,增加容量\n");
		PeoInfo*ptr=(PeoInfo*) realloc(con->date, (con->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr!=NULL)
		{
			con->date = ptr;
			con->capacity += INC_SZ;
			printf("增容成功\n");
		}
		else
		{
			perror("AddInformation");
			printf("增加类型失败");
			return;
		}
	}
		//增加一个人的信息
		printf("请输入学号->");
		scanf("%s", con->date[con->sz].num);
		printf("请输入名字->");
		scanf("%s", con->date[con->sz].name);
		printf("请输入性别->");
		scanf("%s", con->date[con->sz].sex);
		printf("请输入年龄->");
		scanf("%d",&( con->date[con->sz].age));
		printf("请输入电话->");
		scanf("%s", con->date[con->sz].tele);
		printf("请输入地址->");
		scanf("%s", con->date[con->sz].add);
		con->sz++;
		printf("信息输入成功\n");
}

打印通讯录的函数 

void PrintInformation(Concst* con)
{
	printf("%-10s\t%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n", "学号", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->sz; i++)
	{
		printf("%-10s\t%-10s\t%-5s\t%-5d\t%-12s\t%-20s\n",
										con->date[i].num,
										con->date[i].name,
										con->date[i].sex,
										con->date[i].age,
										con->date[i].tele,
										con->date[i].add);
	}
}

实现查找学号为num的函数 

int FindInformation_NUM(Concst* con, char* p)
{
	int i = 0;
	for ( i = 0; i < con->sz; i++)
	{
		if (strcmp(con->date[i].num, p)==0)
		{
			return i;
		}
	}
	return -1;
}
void SearchInformation_num(Concst* con)
{
	printf("请输入你要查找的人的学号");
	char p[10];
	scanf("%s", p);
	int ret = FindInformation_NUM(con, p);
	if (ret==-1)
	{
		printf("查找的人不存在\n");
		return;
	}
	else
	{
		printf("%-10s\t%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n", "学号", "姓名", "性别", "年龄", "电话", "地址");
		printf("%-10s\t%-10s\t%-5s\t%-5d\t%-12s\t%-20s\n",
			con->date[ret].num,
			con->date[ret].name,
			con->date[ret].sex,
			con->date[ret].age,
			con->date[ret].tele,
			con->date[ret].add);
		return;
	}
}

删除信息的函数 


int FindInformation_NUM(Concst* con, char* p)
{
	int i = 0;
	for ( i = 0; i < con->sz; i++)
	{
		if (strcmp(con->date[i].num, p)==0)
		{
			return i;
		}
	}
	return -1;
}
void DelteInformation(Concst* con)
{
	if (con->sz==0)
	{
		printf("通讯录为空,删除失败");
	}
	else
	{
		char numfind[10];
		printf("请输入你要查找学生的学号->");
		scanf("%s", numfind);
		int ret=FindInformation_NUM(con, numfind);
		if (ret == -1)
		{
			printf("通讯录没有这个人,删除失败");
			return;
		}
		else
		{
			for (int i = ret; i < con->sz-1; i++)
			{
				con->date[i] = con->date[i + 1];
			}
			printf("删除成功\n");
			con->sz--;
		}
	}

}

改变特定num的信息的函数 

int FindInformation_NUM(Concst* con, char* p)
{
	int i = 0;
	for ( i = 0; i < con->sz; i++)
	{
		if (strcmp(con->date[i].num, p)==0)
		{
			return i;
		}
	}
	return -1;
}
void ModifyInformation_num(Concst* con)
{
	printf("请输入你要修改的人的学号");
	char p[10];
	scanf("%s", p);
	int ret = FindInformation_NUM(con, p);
	if (ret == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	else
	{
		printf("请输入要修改的学号->");
		scanf("%s", con->date[ret].num);
		printf("请输入要修改的名字->");
		scanf("%s", con->date[ret].name);
		printf("请输入要修改的性别->");
		scanf("%s", con->date[ret].sex);
		printf("请输入要修改的年龄->");
		scanf("%d", con->date[ret].age);
		printf("请输入要修改的电话->");
		scanf("%s", con->date[ret].tele);
		printf("请输入要修改的地址->");
		scanf("%s", con->date[ret].add);
		return;
	}
}

 以num将通讯录排序

int sort_num(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->num, ((PeoInfo*)e2)->num);
}
void SORTInformation_num(Concst* con)
{
	int sz = con->sz;
	qsort(con->date, sz, sizeof(con->date[0]), sort_num);
	printf("排序成功\n");
}

 将动态空间释放的函数,动态版和文件版专属

void DestoryCon(Concst* con)
{
    free(con->date);
    con->date = NULL;
    con->capacity = 0;
    con->sz = 0;
}

将通讯录的内容导入文件,永久存储 

//这样写可以显示我们能看懂的数据,自己写的
//void SaveCon(Concst* con)
//{
//	FILE* pf = fopen("contact.dat", "w");
//	if (pf == NULL)
//	{
//		perror("SaveCon");
//		return;
//	}
//	//写文件
//	fprintf(pf, "%-10s\t%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n", "学号", "姓名", "性别", "年龄", "电话", "地址");
//	for (int i = 0; i < con->sz; i++)
//	{
//		fprintf(pf, "%-10s\t%-10s\t%-5s\t%-5d\t%-12s\t%-20s\n", con->date[i].num,
//			con->date[i].name,
//			con->date[i].sex,
//			con->date[i].age,
//			con->date[i].tele,
//			con->date[i].add);
//	}
//	//关文件
//	fclose(pf);
//	pf = NULL;
//}
void SaveCon(Concst* con)//保存文件
{
	FILE* pf = fopen("contact.dat", "w");
	if (pf == NULL)
	{
		perror("SaveCon");
	}
	//写文件
	int i = 0;
	for (int  i = 0; i < con->sz; i++)
	{
		fwrite(con->date + i, sizeof(PeoInfo), 1, pf);
	}
	//关文件
	fclose(pf);
	pf = NULL;
}

最大公约数----辗转相除法

求两个数的最大公约数-------辗转相除法

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

  最小公倍数=m*n/最大公约数

#incldue<stdio.h>int main()
{
    //辗转相除法
    int m = 0,n = 0;
    scanf("%d%d", &m, &n);
    int t = 0;
    while (t=m%n)
    {   m = n;
        n = t;
    }   printf("最大公约数是 %d",n);
    return 0;
}

判断一个数是否是素数 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_18,color_FFFFFF,t_70,g_se,x_16

#include<stdio.h>
#include<math.h>
//判断一个数是是不是素数
int ifprime(int x)
{
	int ret = 1;
	for (int  i = 2; i <=sqrt(x); i++)
	{
		if (x%i==0)
		{
			ret = 0;
		}
	}
	return ret;
}

二分查找----有序数组查找

折半查找法,每次都是去找最中间的数,前提是这个数组必须是有序的,从小到大

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

#include<stdio.h>
#define N 100
int main()//二分法前提查找的数据是有序的
{
    int arr[N] = { 0 };
    for (int i = 0; i < N; i++)
    {
        arr[i] = i;
    }
    int n=0;
    scanf("%d", &n);
    int right = 99;
    int left = 0;
    while (left<=right)
    {    int mid = (right + left) / 2;
         if (arr[mid] == n)
            {    printf("找到了,下标是%d", mid);
                 break;
            }
         if (arr[mid]>n)
            {
            right = mid-1;
            }
         if (arr[mid]<n)
            {
                left = mid+1;
            }
    }
        if (left>right){printf("该数字不存在");}
        return 0;
}

递归实现字符串反转

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

#include<stdio.h>
//用递归实现strlen
int my_strlen1(char* str)
{
	if (*str )
	{
		return 1 + my_strlen1(++str);
	}
	else
	{
		return 0;
	}
}
//字符串逆序(递归实现)
void reverse_string(char* arr)
{
	int len = my_strlen1(arr);
	char tmp = *arr;
	*arr = *(arr + len - 1);

	*(arr + len - 1) = '\0';
	if (strlen(arr + 1) >= 2)
		reverse_string(arr + 1); 
	*(arr + len - 1) = tmp;
}
int main()
{
	char arr[] = "wwwdwdbnscnab";
	reverse_string1(arr);
	printf("%s", arr);
	return 0;
}

递归实现汉诺塔问题

问题描述,有三个柱子分别是A,B,C,A柱子上套着n个圆盘,按照盘子大小从大到小自上而下的套着n个盘子,现在我们需要遵守

1每次只能移动最上面的盘子

2小盘子上不能放大盘子

那我们把n个盘子从A移到B需要多少步呢,该怎么移动呢?

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

先从一个简单的3个盘子开始分析 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

我们从上面的三个盘子移动的步骤中可以分析出来

前三步是A借助B将A除了最下面一个盘子其余盘子都按大到小移动到了C柱子,

中间一步 是将A上的盘子放到B上

后三步 是将C上的盘子借助A全放在B上

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

 借助上面的思想,我们可以看看四层的怎么解决

1将上面三个盘子由A移到C(就是三层盘子的解法,上面是从A到B,这是从A到C解法是一样的,只是借助的柱子不一样)

2将最大的盘子移动到B

3将C的三个盘子借助A移到B(就是三层盘子的解法,上面是从A到B,这是从C到B,解法是一样的,只是借助的柱子不一样)

解法

解决n层汉诺塔的步骤,即:利用z柱将n个圆盘从x柱转移至y柱。
将n个圆盘从x柱,经由z柱中转,移到y柱时:

  • 当n=0时:
    • * 不做任何操作
  • 当n>0时:
    • * 首先,将n-1个圆盘从A柱移到C柱(解出n-1层)
    • * 然后,将(n个中)最大的圆盘从A柱移到B柱
    • * 最后,将n-1个圆盘从C柱移到B柱(解出n-1层)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int count = 0;
void move(int num,char x,char y, char z)
{
	printf("将%c最上面的%d个盘子移动到%c\n",x, num, z);
}
//汉诺塔模拟 x为起始柱子 y为中间柱子,z为目标柱子,num为要移动盘子的数量
void  haoni(int num,char x, char y, char z)
{
	if (num == 0)
	{

	}
	else
	{
		haoni(num - 1, x, z, y);//将x起始柱上的n-1个盘子从x借助目标柱子z移动到z中间柱子y上
		move(1,x,y, z);//将x起始柱子上的最下面一个大盘子移到目标柱子上
		count++;
		haoni(num - 1, y, x, z);//将y的目标柱子上的n-1个盘子借助起始柱x移到到目标柱子z上
	}
}
int main()
{
	int num=0;
	char x, y, z;
	scanf("%d %c %c %c",&num,&x, &y, &z);
	haoni(num, x, y, z);
	printf("%d ", count);
	return 0;
}

青蛙跳台阶问题

问题描述

有一只青蛙,一次最多可以跳2个台阶,请问青蛙跳n个台阶有多少种跳法呢?

问题分析

  • n=1时,只有一种跳法
  • n=2时,有两种跳法(1,1)或者(2)
  • n=3时,可以先跳到1,然后剩下2层就是2层的跳法,也可以先跳到2,然后剩下的就是1层的跳法
  • n=4时,可以先跳到1,然后剩下的就是三层的跳法,也可以先跳到2,然后剩下的就是2层的跳法
  • n=k时,就是(k-1)+(k-2)这两个跳法之和

代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int  tioatai1(int n)
{
	if (n == 1)
	{
		return 1;
	}
	else if (n == 2)
	{
		return 2;
	}
	else
	{
		return tioatai1(n - 1) + tioatai1(n - 2);
	}

}


int main()
{
	int n = 0;
	scanf("%d", &n);
	int sum = tioatai1(n);
	printf("%d ", sum);
}

青蛙一次能跳k个台阶的解法

int frog(int n, int k)
{
   if(n == 1)
   {
      return 1;
   }
   if(n == 2)
   {
      return 2;
   }
   .......
   .......
   if(n == k)
   {
      return ?//跳 k 层台阶时的方法
   }
   return frog(n-1) + frog(n-2)+ ........+frog(n-k);
}

存在的问题

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_19,color_FFFFFF,t_70,g_se,x_16

 我们发现这个递归存在着大量的重复运算,所以效率非常低,数据稍微大一点,就会跑死,怎么改进呢,我们可以定义两个全局数组来记录这个数据是否已经算过

优化的代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MAX 1000
int arr[MAX] = { 0,1,1 };
int arr1[MAX] = {0,1,2};
int  tioatai(int n)
{
	if (arr[n]==1)
	{
		return arr1[n];
	}
	else
	{
		arr1[n] = tioatai(n - 1) + tioatai(n - 2);
		arr[n] = 1;
		return arr1[n];
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int sum = tioatai(n);
	printf("%d ", sum);
}

几个字符串库函数的实现  

//strlen实现
//计数器版本
int my_strlen(const char* p)
{
	assert(p);
	int count = 0;
	while (*p++)
	{
		count++;
	}
	return count;
}
//指针版本
int my_strlen1(const char* p)
{
	assert(p);
	const char *start = p;
	while (*p++)
	{
		;
	}
	return  p - start-1;
}
//递归版本
int my_strlen2(const char* str)
{
	assert(str);
	if (*str == '\0')//不能使用计数器版本
		return 0;
	else
		return 1 + my_strlen1(str + 1);
}
//strcpy
char* my_strcpy(char* p, const char* str)
{
	char* ret = p;
	assert(p && str);
	while ((*p++=*str++))
	{
		;
	}
	return ret;
}
//strcat实现
char* my_strcat(char* p, const char* str)
{
	assert(p && str);
	char* start = p;
	while (*p)
	{
		p++;
	}
	//while (*str)
	//{
	//	*p = *str;
	//	p++;
	//	str++;
	//}
	//*p = '\0';
	while ((*p++=*str++))
	{
		;
	}
	return start;
}
int my_strcmp(const char* arr, const char* arr1)
{
	assert(arr && arr1);
	while (*arr==*arr1)
	{
		if (*arr==0)
		{
			return 0;
		}
		arr++;
		arr1++;
	}
		return *arr - *arr1;
}
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* sr = str1;
	while (*sr)
	{
		s1 = sr;
		s2 = str2;
		while (*s1 && *s2 && !(*s1-*s2) )
		{
			s1++;
			s2++;
		}
		if (*s2=='\0')
		{
			return (char*)sr;
		}
		sr++;

	}
	return NULL;
}
//模拟实现strncpy
char* my_strncpy(char* str2, const char* str1, size_t num)
{
	assert(str1 && str2);
	char* start = str2;
	while ((num--)&&(*str2++=*str1++))
	{
		;
	}
	*str2= '\0';
	return start;
}
//模拟实现strncat
char* my_strncat(char* str1, const char* str2, size_t num)
{
	assert(str1&&str2);
	char* start = str1;
	while (*str1)
	{
		str1++;
	}
	while ( (num--) &&(*str1++=*str2++))
	{
		;
	}
	*str1 = '\0';
	return start;
}

几个内存函数的实现

memmove可以实现重复空间的替换

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_12,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_12,color_FFFFFF,t_70,g_se,x_16

#define _CRT_SECURE_NO_WARNINGS 1
//memmove
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, void* str, size_t num)
{
	assert(dest);
	assert(str);
	void* sr = dest;
	char* dest1 = (char*)dest;
	char* str1 = (char*)str;
	int n = num;
	if (str > dest)
	{
		while (n--)
		{
			*dest1 = *str1;
			dest1++;
			str1++;
		}
	}
	else
	{
		while (n--)
		{
			*(dest1 + n) = *(str1 + n);
		}
	}
	return sr;
}
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	my_memmove(arr+1, arr , 2 * sizeof(arr[0]));
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

实现memcpy

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, void* str, size_t num)
{
	assert(dest);
	assert(str);
	char* dest1 = (char*)dest;
	char* str1 = (char*)str;
	void* sr = dest;
	int n = num;
	while (n--)
	{
		*dest1 = *str1;
		dest1++;
		str1++;
	}
	return sr;
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr1[10] = { 0 };
	my_memcpy(arr1, arr, sizeof(arr));
	for (int i = 0; i < 10; i++)
	{
	printf("%d ", arr1[i]);
	}
	return 0;
}

qsort的冒泡实现版本 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

qsort的使用

//实现以整数的大小来排序
int int_cmp1(const void* p, const void* p1)
{
	return(*(int*)p - *(int*)p1);
}
typedef  struct people1
{
	char name[20];
	int age;
	double socre;
}People1;
//以名字排序
int name_cmp1(const void* p, const void* p1)
{
	return strcmp((*(People1*)p).name, (*(People1*)p1).name);
}
//按年龄从小到大排序
int age_cmp1(const void* p, const void* p1)
{
	return (*(People1*)p).age-(*(People1*)p1).age;
}
int age_cmp2(const void* p, const void* p1)
{
	return (*(People1*)p1).age - (*(People1*)p).age;
}
int score_cmp1(const void* p, const void* p1)
{
	if ((*(People1*)p1).socre - (*(People1*)p).socre > 0)
	{
		return -1;
	}
	else
	{
		return 1;
	}
}
int main()
{
	int arr[10] = { 1,3523,3,2423,52,41,2,12,312,3 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), int_cmp1);
	printarr(arr, sz);
	People1 p[3] = { {"zhangsan",19,89.5},{"lisi",22,60.0},{"wangwu",16,98.4} };
	int sz1 = sizeof(p) / sizeof(People1);
	qsort(p, sz1, sizeof(p[0]), name_cmp1);
	printf("按名字从小到大排序\n");
	for (int i = 0; i < sz1; i++)
	{
		printf("名字%-5s\t年龄%-5d\t成绩%-5.1lf\n", p[i].name, p[i].age,p[i].socre);
	}
	qsort(p, sz1, sizeof(p[0]), age_cmp1);
	printf("按年龄从小到大排序\n");
	for (int i = 0; i < sz1; i++)
	{
		printf("名字%-5s\t年龄%-5d\t成绩%-5.1lf\n", p[i].name, p[i].age, p[i].socre);
	}
	qsort(p, sz1, sizeof(p[0]), age_cmp2);
	printf("按年龄从大到小排序\n");
	for (int i = 0; i < sz1; i++)
	{
		printf("名字%-5s\t年龄%-5d\t成绩%-5.1lf\n", p[i].name, p[i].age, p[i].socre);
	}
	qsort(p, sz1, sizeof(p[0]), score_cmp1);
	printf("按成绩从小到大排序\n");
	for (int i = 0; i < sz1; i++)
	{
		printf("名字%-5s\t年龄%-5d\t成绩%-5.1lf\n", p[i].name, p[i].age, p[i].socre);
	}
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
typedef  struct people
{
	char name[20];
	int age;
}People;
//冒泡排序实现qsort
//以一个整数来决定顺序
int int_cmp(const void* p, const void* p1)
{
	return(*(int*)p - *(int*)p1);
}
//以名字排序
int name_cmp(const void* p, const void* p1)
{
	return strcmp((*(People*)p).name, (*(People*)p1).name);
}
void swap(const void* p, const void* p1,int size)
{
	char* e1 = (char*)p;
	char* e2 = (char*)p1;
	for (int  i = 0; i < size; i++)
	{
		char tmp = *(e1 + i);
		*(e1 + i) = *(e2 + i);
		*(e2 + i) = tmp;
	}
}
void my_qsort(void* str, int count, int size, int (*cmp)(const void*, const void*))
{
	int i = 0;
	for ( i = 0; i < count-1; i++)
	{
		int j = 0;
		for ( j = 0; j < count-1-i; j++)
		{
			if (cmp( (char*)str + j * size, (char*) str + (j + 1) * size) >0)
			{
				swap((char*)str + j * size, ((char*)str + (j + 1) * size),size);
			}
		}
	}
}
void printarr(int* arr,int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[10] = { 12,134,2,14,54,2,1,5,13,4 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), int_cmp);
	printarr(arr, sz);
	People p[3] = { {"zhangsan",19},{"lisi",22},{"wangwu",16} };
	int sz1 = sizeof(p) / sizeof(People);
	my_qsort(p, sz1, sizeof(p[0]), name_cmp);
	for (int i = 0; i < sz1; i++)
	{
		printf("%s %d", p[i].name, p[i].age);
	}
	return 0;
}

杨式矩阵 

有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
int find_num(int arr[3][3], int* px, int* py, int k)
{
	int x = 0;
	int y = *py - 1;
	while (x<*px&&y>=0)
	{
		if (arr[x][y] < k)
		{
			x++;
		}
		else if(arr[x][y]>k)
		{
			y--;
		}
		else
		{
			*px = x;
			*py = y;
			return 1;
		}
	}
	return 0;
}
int main()
{
	int arr[3][3] = { 1,2,3,2,3,4,4,5,6 };
	int k;
	scanf("%d", &k);
	int x = 3;
	int y = 3;
	int ret = find_num(arr, &x, &y, k);
	if (ret==1)
	{
		printf("找到了%d %d\n",x,y);
	}
	else
	{
		printf("没有找到");
	}
	return 0;
}

字符串左旋 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* rolatr_left_string1(char* p, int num)
{
	char* start = p;
	int i = 0;
	int length = strlen(p);
	for (i = 0; i < num; i++)//循环一次,左移一次
	{
		//将元素的第一位数据储存下来
		char tmp = *p;
		//将后面的元素都前移动一位
		for (int j = 0; j < length - 1; j++)
		{
			*(p + j) = *(p + j + 1);
		}
		//将tmp储存到字符串的最后一个空间
		*(p + length - 1) = tmp;

	}
	return start;
}
int main()
{
	char p[100] = "AABCD";
	rolatr_left_string2(p, 2);
	printf("%s", p);
	return 0;
}

三步逆序法watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_17,color_FFFFFF,t_70,g_se,x_16

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* reserve(char* left,char*right)
{
	assert(left);
	assert(right);
	char* start = left;
	while (left<right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
	return left;
}
//三步逆序法
char* rolatr_left_string2(char* p, int num)
{
	assert(p);
	char* start = p;
	int n = strlen(p);
	reserve(p, p + num - 1);
	reserve(p+num,p+n-1);
	reserve(p, p + n - 1);
	return start;
}
int main()
{
	char p[100] = "AABCD";
	rolatr_left_string2(p, 2);
	printf("%s", p);
	return 0;
}

如何判断一个字符串是不是由一个字符串左旋或者右旋得来的

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

 第一种

#include<stdio.h>
#include<string.h>
#include<assert.h>
//遍历所有可能的字符串进行比较
int if_string_rolate(char* s1, char* s2)
{
	int length = strlen(s1);
	char arr[100];
	for (int i = 0; i < length; i++)
	{
		strcpy(arr, s1);
		if ((strcmp(s2, rolatr_left_string1(arr, i)) == 0))
		{
			return 1;
		}
	}
	return 0;
}
int main()
{
	char s11[] = "AABCD";
	char s21[] = "BCDAA";
	int ret = if_string_rolate(s11, s21);
	printf("%d", ret);
	return 0;
}

第二种

int if_string_rolate1(char* str1, char* str2)
{
	int length = strlen(str1);
	if (length!=strlen(str2))
	{
		return 0;
	}
	char* p = strncat(str1, str1, length);
	char*ret = strstr(str1, str2);
	/*if (ret==NULL)
	{
		return 0;
	}
	else
	{
		return 1;
	}*/
	return ret!=NULL;
}
int main()
{
	char arr[20] = "abcdef";
	/*rolatr_left_string1(arr, 2);
	printf("%s", arr);*/
	char arr1[20] = "bcdefa";
	int ret = if_string_rolate1(arr, arr1);
	if (ret == 1)
	{
		printf("是他的旋转字符串");
	}
	else
	{
		printf("不是他的旋转字符串");
	}
	return 0;
}

找单身狗游戏 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bqT6YeM5LiN5Lya5oqV5LiJ5YiG,size_20,color_FFFFFF,t_70,g_se,x_16

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void find(int arr[], int sz,int *x,int *y)
{
	//将所以数据异或,得到两个单独存在的数字的异或结果
	int i = 0;
	int ret = 0;
	for ( i = 0; i <sz; i++)
	{
		ret ^= arr[i];
	}
	//计算出ret哪一位为1
	int pos = 0;
	for ( i = 0; i <32; i++)
	{
		if ((ret >> i & 1) == 1)
		{
			pos = i;
			break;
		}
	}
	//把ret位为1的放在一个组,为0的放在另外一个组
	for ( i = 0; i < sz; i++)
	{
		if ((arr[i] >> pos & 1) == 1)
		{
			*x ^= arr[i];
		}
		else
		{
			*y ^= arr[i];
		}
	}
}
int main()
{
	int arr[] = { 1,2,2,1,3,4,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int x = 0;
	int y = 0;
	find(arr, sz,&x,&y);
	printf("%d %d", x, y);
}

;