4.数组dddd

一维数组创建和初始化

数组创建

数组:一组相同类型的集合
type_t arr_name [const_n];
C99标准之前是不支持使用变量的,只能是常量
C99中增加了变长数组的概念,允许数组的大小是变量
要求编译器支持C99标准,但常见的编译器(VS)对C99支持不够好
Linux - Centos 7 gcc编译器
image-20220110223102573

char arr3[10];
float arr4[1];
double arr5[20];

数组初始化

int arr1[10] = {1,2,3};
//不完全初始化,剩余元素默认为0
int arr2[] = {1,2,3,4};
int arr3[5] = {12345}char arr4[3] = {'a',98, 'c'};
//98 是 'b'的ASCII值
char arr5[] = {'a','b','c'};//数组大小3个字节
char arr6[] = "abc";//还有一个\0
//数组大小4个字节

image-20220110223757978

sizeof与strlen

char arr1[] = {‘a’,‘b’,‘c’};
char arr2[] = “abc”;
arr2中放的是abc’\0’

char arr1[] = { 'a', 'b', 'c' };
//arr1有3个元素,数组的大小是3个字节
printf("%d\n", sizeof(arr1));
printf("%d\n", strlen(arr1));//随机值

char arr2[] = "abc";//a b c \0
//arr2有4个元素,数组的大小是4个字节
printf("%d\n", sizeof(arr2));
printf("%d\n", strlen(arr2));//3

sizeof是操作符,计算变量所占空间大小,任何类型都相同
不在乎内存中是否存在\0
strlen是函数,只针对字符串,计算字符串长度,遇到\0停止
不包括\0
数组如果不初始化,那么就会被赋为随机值,不可控

char acX[] = “abcdefg”;
char acY[] = {‘a’,’b’,’c’,’d’,’e’,’f’,’g’};

数组acX长度大于数组acY长度
但如果问字符串acX长度与字符串acY长度比较 则不能确定
因为acY后面没有\0 strlen遇到\0才会停止故求出来的是随机值

一维数组的使用

[] 下标引用操作符

#include <stdio.h>
int main()
{
int arr[10] = {0};//数组的不完全初始化
   //计算数组的元素个数
   int sz = sizeof(arr)/sizeof(arr[0]);
//对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:
int i = 0;//做下标
for(i=0; i<10; i++)//这里写10,好不好?
{
arr[i] = i;
}
//输出数组的内容
for(i=0; i<10; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}
//计算数组元素个数:
int arr[10];
int sz = sizeof(arr)/sizeof(arr[0]);
//40 / 4 = 10

一维数组在内存中的存储

int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = &arr[0];
 //打印数组每个元素的地址
int i = 0;
for (i = 0; i < 10; i++)
  {
	printf("&arr[%d] = %p\n", i, &arr[i]);
	printf("%p\n", p + i);//p+i 是数组中arr[i]的地址
	printf("%p ----- %p\n", p + i, &arr[i]);
	printf("%d ", * (p + i));//1 2 3 4 5 6 7 8 9 10
  }
    //整型指针,+1跳过一个整型元素
return 0;
}

image-20220110225156519

0x0c表示十进制的12
p+i 与&arr[i] 等价

二维数组

二维数组创建

int arr[3][4]; //三行四列,每个元素是int型
char arr[3][5];
double arr[2][4];

其实就是数学里的矩阵

二维数组初始化

int arr[3][4] = { {1,2},{3,4},{5,6} };
//不完全初始化
//1 2 0 0
//3 4 0 0
//5 6 0 0
//二维数组初始化不能省略列,行可以省略

image-20220110225843442

#include<stdio.h>
int main()
{
       int arr[3][4] = { {1,2},{2,2},{3,3,3} };
       int arr[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
       return 0;
}

二维数组使用与存储

#include<stdio.h>
int main()
{
       int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
       int i = 0;
       int j = 0;
       for (i = 0; i < 3; i++)
       {
               for (j = 0; j < 4; j++)
               {
                      printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
               }
       }
       for (i = 0; i < 3; i++)
       {
               for (j = 0; j < 4; j++)
               {
                      printf("arr[%d][%d] = %d\n", i, j, arr[i][j]);
               }
       }
       return 0;
}

二维数组理解为一维数组的数组

在内存中是连续储存的,第二行紧跟着第一行
每一行是一个一维数组
以为是这样存储,但实际是连续存储
image-20220110230226081

数组越界

数组的下标如果小于0,或者大于n-1,就是数组越界访了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
所以程序员写代码时,最好自己做越界的检查。

数组前面后面还是有空间的

#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
   int i = 0;
   for(i=0; i<=10; i++)
  {
       printf("%d\n", arr[i]);//当i等于10的时候,越界访问了
  }
return 0;
}

1
2
3
4
5
6
7
8
9
10
-858993460
数组越界,程序已经错了,但并没有报错,编译器能力有限,有时候识别不出来越界
image-20220111110819712

c语言支持多维数组,但是比较少用

数组作为函数参数

冒泡排序

核心思想:
两两相邻元素进行比较,如果有肯能需要交换

一趟冒泡排序搞定一个数字
让当前待排序数组中的一个元素来到最终应该出现的位置上
10个元素,9躺冒泡排序
image-20220111111334042

#include <stdio.h>
//void bubble_sort(int* arr,int sz) 这样写也可以 
//指针大小是4,不能在函数内算数组元素个数
void bubble_sort(int arr[], int sz)
{
       int i = 0;
       for (i = 0; i < sz - 1; i++)
       {
               //一趟冒泡排序的过程
               int j = 0;
               //一趟冒泡排序比较的对数
               //第二趟比较8对,第三躺比较7对
               for (j = 0; j < sz - 1 - i; j++)
               {
                      if (arr[j] > arr[j + 1])
                      {
                              int tmp = arr[j];
                              arr[j] = arr[j + 1];
                              arr[j + 1] = tmp;
                      }
               }
       }
}
int main()
{
       //数组传参
       int arr[] = { 3,1,5,2,4,9,0,7,6,8 };
       //设计一个函数对arr数组进行排序-冒泡排序
       int sz = sizeof(arr) / sizeof(arr[0]);
       bubble_sort(arr, sz);//数组名代表的就是数组
       //数组传参,实际上传过去的不是整个数组,传过去的是数组首元素地址
       //避免空间浪费,只需要传首元素地址,就能依据地址找到所有元素
       int i = 0;
       for (i = 0; i < 10; i++)
       {
               printf("%d ", arr[i]);
       }
       return 0;
}

数组名是什么?

补充:

  1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数
    组。
  2. &数组名,取出的是整个数组的地址。&数组名,数组名表示整个数组。
#include <stdio.h>
int main()
{
       int arr[] = { 1,2,3,4,5 };
       printf("%p\n", arr);//00AFF92C
       printf("%p\n", &arr[0]);//00AFF92C
       printf("%p\n", &arr);//00AFF92C
       printf("%d\n", sizeof(arr));//20
       printf("%p\n", arr+1);//00AFF930
       printf("%p\n", &arr[0]+1); //00AFF930
    //跳过4字节
       printf("%p\n", &arr+1); //00AFF940
    //跳过一整个数组,20字节
       //sizeof是例外
       return 0;
}




整个数组地址与数组首元素地址相同
数组名 == 数组首元素地址
数组地址从起始位置开始
数组地址和数组首元素地址意义不一样,值是一样的

游戏

三子棋

image-20220111114226776

test.c 游戏的测试逻辑

#define _CRT_SECURE_NO_WARNINGS 
#include"game.h"
void menu()
{
        printf("******************************\n");
        printf("*********   1.play   *********\n");
        printf("*********   0.exit   ********\n");
        printf("******************************\n");
}

void game()
{
        //数据存储到一个字符的二维数组中,玩家下棋'*' 电脑下棋'#'
        char board[ROW][COL] = { 0 };//数组的内容应该是全部空格
        InitBoard(board,ROW,COL);//初始化棋盘
        DisplayBoard(board,ROW,COL);//打印棋盘
        //下棋
        char ret = 0;
        while (1)
        {
                player_move(board,ROW,COL);
                DisplayBoard(board, ROW, COL);
                ret = is_win(board, ROW, COL);
                if (ret != 'C')//C表示游戏继续
                {
                        break;
                }
                computer_move(board, ROW, COL);
                DisplayBoard(board, ROW, COL);
                if (ret != 'C')
                {
                        break;
                }
        }
        if (ret == '*')
        {
                printf("玩家赢\n");
        }
        else if (ret == '#')
        {
                printf("电脑赢\n");
        }
        else
        {
                printf("平局\n");
        }
}

void test()
{
        int input = 0;
        srand((unsigned int)time(NULL));
        do
        {
                menu();//菜单
                printf("请选择:>");
                scanf("%d", &input);
                switch (input)
                {
                case 1:
                        game();
                        break;
                case 0:
                        printf("退出游戏\n");
                        break;
                default:
                        printf("选择错误\n");
                        break;
                }
        } while (input);
}

int main()
{
        test();
        return 0;
}

game.c 游戏的实现逻辑

image-20220111125407020

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
        int i = 0;
        int j = 0;
        for (i = 0; i < row; i++)
        {
                for (j = 0; j < col; j++)
                {
                        board[i][j] = ' ';
                }
        }
}

//版本一 只能打印3x3棋盘

/*
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		//数据
		printf(" %c | %c | %c \n", board[i][0], board[i][0], board[i][1]);
		//分隔行(只需打印2个)
		if(i < row - 1)
			printf("---|---|---\n");
	}
}
*/

//版本二 配合宏定义可以灵活修改
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		//数据 把  %c |看成一组数据,但最后一个|不打印
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if(j < col -1)//最后一个|不用打印
				printf("|");
		}
        
		printf("\n"); //打印完一行换行
        
		//分隔行 把---|看成一组数据 最后一个|不打印 
		if (i < row - 1)//最后一行分隔行也无需打印
		{
			for (j = 0; j < col; j++)
			{
					printf("---");
					if (j < col - 1)
						printf("|");
			}
		}
		printf("\n"); //打印完一行换行
	}
}


void player_move(char board[ROW][COL], int row, int col)
{
        printf("玩家下棋:>");
        int x = 0;
        int y = 0;
        while (1)
        {
                scanf("%d %d", &x, &y);
                if (x >= 1 && x <= row && y >= 1 && y <= col)//坐标合法性判断
                {
                        if (board[x - 1][y - 1] == ' ')//坐标占用判断
                        {
                                board[x - 1][y - 1] = '*';
                                break;
                        }
                        else
                        {
                                printf("该坐标被占用,请重新输入\n");
                        }
                }
                else
                {
                        printf("坐标非法,请重新输入\n");
                }
        }
}

void computer_move(char board[ROW][COL], int row, int col)
{
        int x = 0;
        int y = 0;
        printf("电脑下棋:>\n");
        while (1)
        {
                x = rand() % ROW;//0 - 2
                y = rand() % COL;//0 - 2
                if (board[x][y] == ' ')
                {
                        board[x][y] = '#';
                        break;
                }
        }
}


int is_full(char board[ROW][COL],int row,int col )
{
        int i = 0;
        int j = 0;
        for (i = 0; i < row; i++)
        {
                for (j = 0; j < col; j++)
                {
                        if (board[i][j] == ' ')
                        {
                                return 0;
                        }
                }
        }
        return 1;//满了
}

//版本1 is_win被写死了,只能判断ROW COL为3的情况
/*char is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	
	//三行判断
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		{
			return board[i][1];
		}
	}
	
	//三列判断
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[1][i];
		}
	}
	
	//判断对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	//判断平局
	if (1 == is_full(board, row, col))
	{
		return 'Q';
	}
	//游戏继续
	return 'C';
}*/


//版本2 is_win灵活变动
char is_win(char board[ROW][COL], int row, int col)
{
        int i = 0;
        int j = 0;
        int a = 0;
        //判断行
        for (i = 0; i < row; i++)
        {
                a = 0;
                for (j = 0; j < col - 1; j++)
                {
                        if (board[i][j] == board[i][j + 1] && board[i][j] == '*')
                        {
                                a++;
                        }
                        if (board[i][j] == board[i][j + 1] && board[i][j] == '#')
                        {
                                a--;
                        }
                        if (a == col - 1)
                        {
                                return '*';
                        }
                        if (a == -col + 1)
                        {
                                return '#';
                        }
                }
        }

        //判断列
        for (i = 0; i < col; i++)
        {
                a = 0;//a需要清零
                for (j = 0; j < row - 1; j++)
                {
                        if (board[j][i] == board[j + 1][i] && board[j][i] == '*')
                        {
                                a++;
                        }
                        if (board[j][i] == board[j + 1][i] && board[j][i] == '#')
                        {
                                a--;
                        }
                        if (a == row - 1)
                        {
                                return '*';
                        }
                        if (a == -row + 1)
                        {
                                return '#';
                        }
                }
        }

        //判断左对角线
        for (i = 0, j = 0; i < row - 1; i++, j++)
        {
                if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '*')
                {
                        a++;
                }
                if (board[i][j] == board[i + 1][j + 1] && board[i][j] == '#')
                {
                        a--;
                }
                if (a == row - 1)
                {
                        return '*';
                }
                if (a == -row + 1)
                {
                        return '#';
                }
        }

        //判断右对角线
        for (i = 0, j = col - 1; i < row - 1; i++, j--)
        {
                if (board[i][j] == board[i + 1][j - 1] && board[i][j] == '*')
                {
                        a++;
                }
                if (board[i][j] == board[i + 1][j - 1] && board[i][j] == '#')
                {
                        a--;
                }
                if (a == row - 1)
                {
                        return '*';
                }
                if (a == -row + 1)
                {
                        return '#';
                }
        }

        //判断平局
        if (1 == is_full(board, row, col))
        {
                return 'Q';
        }
        //游戏继续
        return 'C';
}

game.h 游戏实现函数的声明

#pragma once
#define ROW 5
#define COL 5
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void player_move(char board[ROW][COL], int row, int col);
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col);

//判断输赢
//玩家赢了 -'*'
//电脑赢了 -'#'
//平局 - 'Q'
//游戏继续 - 'C'
char is_win(char board[ROW][COL], int row, int col);

细节

  1. 棋盘数据打印是把 %c |看成一组数据但最后一个|不打印
    分隔行 把—|看成一组数据但最后一个|不打印且最后一行分隔行也无需打印
  2. 把要用到的头文件及函数都在头文件中声明,这样在.c文件中就只需引用自己创建的头文件,避免了头文件的重复定义
  3. 用时间戳生成随机数的时候,先使用srand函数设置种子,注意srand函数不要放在实现函数的内部,不然会导致随机数生成的很近,srand函数每次游戏只需重新设置一次
    image-20220111120333716

扫雷

9x9 二维数组存储
char board / int board 似乎都行?
先布置累
排查雷
如果用0/1表示有雷无雷 可能会产生冲突
用* #也可以 但符号太多比较麻烦
再弄一个棋盘,放排查出的雷的信息
没排查过的位置放*
所以选char board

防范数组越界,把数组再多开辟一圈就行 11x11数组 用的只是9x9
image-20220111142105836

数字3+‘0’ -> ‘3’

注意不要形成死递归

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
       printf("***********************\n");
       printf("*****  1. play     ****\n");
       printf("*****  0. exit     ****\n");
       printf("***********************\n");
}
void game()
{
       //创建数组
       char mine[ROWS][COLS] = { 0 };//存放布置好的雷信息
       char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
       //初始化mine数组-全字符'0'
       InitBoard(mine,ROWS,COLS,'0');
       //初始化show数组-全字符'*'
       InitBoard(show,ROWS,COLS,'*');
       //打印棋盘,只需打印9x9就行了
       //DisplayBoard(mine, ROW, COL);
       //DisplayBoard(show, ROW, COL);
       //布置雷
       SetMine(mine, ROW, COL);
       DisplayBoard(show, ROW, COL);
       //DisplayBoard(mine, ROW, COL);
       //排雷
       FindMine(mine, show, ROW, COL);
}
void test()
{
       int input = 0;
       srand((unsigned int)time(NULL));
       do
       {
               menu();
               printf("请选择:>\n");
               scanf("%d", &input);
               switch (input)
               {
               case 1:
                      //扫雷
                      game();
                      break;
               case 0:
                      printf("退出游戏\n");
                      break;
               default:
                      printf("选择错误,请重新选择\n");
                      break;
               }
       } while (input);
}
int main()
{
       test();
       return 0;
}

game.h

#pragma once
//头文件包含:符号的声明.函数的声明
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 5
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
 
void InitBoard(char board[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++)
		{
			board[i][j] = set;
		}
	}
}
 
//棋盘的打印
void DisplayBoard(char board[ROWS][COLS], int row, int col)
    //虽然只打印9*9,但传过去的数组依旧是11*11
{
	//1-9开始
	int i = 0;
	//打印列号
	for (i = 0; i <= col; i++) //i从0开始,避免列号错位(多多尝试就好)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);//打印行号
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}
 
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;//布置10个雷
	while (count)
	{
		//随机产生的x y坐标是1-9
		int x = rand() % row + 1;
		int y = rand() % col + 1;
 
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
 

//无需写到头文件,因为不想暴露它 +static保护更加彻底 只能在game.c用
static int get_mine_count(char mine[ROWS][COLS], int x, int y) 
{
	//mine里放的是字符 需要减去'0'
	return mine[x - 1][y] + mine[x - 1][y - 1]
		+ mine[x][y - 1] + mine[x + 1][y - 1]
		+ mine[x + 1][y] + mine[x + 1][y + 1]
		+ mine[x][y + 1] + mine[x - 1][y + 1]
		- 8 * '0';
	//因为设计时11*11 所以x+1 y+1不会越界
}
 
//递归展开一片雷
void Open_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (get_mine_count(mine, x, y) == 0)
	{
		show[x][y] = ' ';
		//判断坐标是否越界以及雷是否已经被排除
		if (show[x - 1][y - 1] == '*')
			Open_Mine(mine, show, x - 1, y - 1);
		if (show[x - 1][y] == '*')
			Open_Mine(mine, show, x - 1, y);
		if (show[x - 1][y + 1] == '*')
			Open_Mine(mine, show, x - 1, y + 1);
		if (show[x][y - 1] == '*')
			Open_Mine(mine, show, x, y - 1);
		if (show[x][y + 1] == '*')
			Open_Mine(mine, show, x, y + 1);
		if (show[x + 1][y - 1] == '*')
			Open_Mine(mine, show, x + 1, y - 1);
		if (show[x + 1][y] == '*')
			Open_Mine(mine, show, x + 1, y);
		if (show[x + 1][y + 1] == '*')
			Open_Mine(mine, show, x + 1, y + 1);
	}
	else
	{
		show[x][y] = get_mine_count(mine, x, y) + '0';
	}
}
 
//遍历show,以便判断是否排雷完毕
int Travel(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int win = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
			{
				win++;
			}
		}
	}
	return win;
}
 
 
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    //在mine数组中排雷,信息放到show数组中去
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (1)
	{
		printf("请输入要排查的雷的坐标:>\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//坐标合法性排查
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
				//计算x y坐标周围有几个雷
				//show 里面放的是字符 数字3 + '0' 就变成'3'
				//字符'0' 48  '2' -> 50 = '0' + 2
				Open_Mine(mine, show, x, y);
				DisplayBoard(show, row, col);
				
			}
		}
		else
		{
			printf("输入坐标非法,请重新输入\n");
		}
		win = Travel(show, row, col);
		if (win == EASY_COUNT)
			break;
	}
	//EASY_COUNT 设置小一点方便检验是否排雷成功
	if (win == EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, row, col);
	}
}

扩展:
image-20220111145200966

练习

1.交换2数组

#include <stdio.h>
int main()
{
       int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
       int arr2[] = { 10,9,8,7,6,5,4,3,2,1 };
       int sz = sizeof(arr1) / sizeof(arr1[0]);
       for (int i = 0; i < sz; i++)
       {
               int tmp = arr1[i];
               arr1[i] = arr2[i];
               arr2[i] = tmp;
       }
       return 0;
}

image-20220111211528782

2.数组操作

创建一个整形数组,完成对数组的操作
实现函数init() 初始化数组为全0
实现print() 打印数组的每个元素
实现reverse() 函数完成数组元素的逆置

#include<stdio.h>
void init(int arr[10], int sz)
{
       int i = 0;
       for (i = 0; i < sz; i++)
       {
               arr[i] = 0;
       }
}
void print(int arr[10], int sz)
{
       int i = 0;
       for (i = 0; i < sz; i++)
       {
               printf("%d ", arr[i]);
       }
       printf("\n");
}
void reverse(int arr[10], int sz)
{
       int left = 0;
       int right = sz - 1;
       while (left < right)
       {
               int tmp = arr[left];
               arr[left] = arr[right];
               arr[right] = tmp;
               left++;
               right--;
       }
}
int main()
{
       int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
       int sz = sizeof(arr) / sizeof(arr[0]);
       print(arr, sz);
       reverse(arr, sz);
       print(arr, sz);
       init(arr, sz);
       print(arr, sz);
       return 0;
}

3.字符串逆序

编写一个函数 reverse_string(char* string)(递归实现)
实现:将参数字符串中的字符反向排列,不是逆序打印。
要求:不能使用C函数库中的字符串操作函数。
比如 :
char arr[] = “abcdef”;
逆序之后数组的内容变成:fedcba

递归实现:

image-20220111203930683

#include <string.h>

int my_strlen(char* s)
{
	int count = 0;
	while (*s != '\0')
	{
		count++;
		s++;
	}
	return count;
}


//[a b c d e f g \0]
//递归版本
void reverse_string(char* arr)
{
	int len = my_strlen(arr);
	char tmp = *arr;//a
	*arr = *(arr + len - 1);//找到了g
	*(arr + len - 1) = '\0';//先把g的内容赋值为\0才能识别为字符串
	if(my_strlen(arr+1)>1)//递归必须要有结束条件
		reverse_string(arr+1);//arr+1找到b的地址
	*(arr + len - 1) = tmp;//再把a放回到g的位置
}


//参数用指针的形式
void reverse_string(char* str)
{
	char* left = str;//a的地址
	char* right = str + my_strlen(str) - 1;
	while (left<right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

//参数是数组的形式
void reverse_string(char arr[])
{
	int left = 0;
	int right = my_strlen(arr)-1;

	//交换
	while (left<right)
	{
		char tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}


int main()
{
	char arr[] = "abcdefg";
	reverse_string(arr);
	printf("%s\n", arr);//fedcba
	return 0;
}

image-20220111203156679

4.计算每位数之和

//写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和
//例如,调用DigitSum(1729),则应该返回1 + 7 + 2 + 9,它的和是19
//输入:1729,输出:19

int DigitSum(size_t n)
{
	if (n <= 9)
		return n;
	else
		return DigitSum(n / 10) + n % 10;
}

int main()
{
	size_t num = 0;
	scanf("%u", &num);
	int ret = DigitSum(num);
	printf("%d\n", ret);

	return 0;
}

5.求n^k

double Pow(int n, int k)
{
	if (k == 0)
		return 1;
	else if (k > 0)
		return n * Pow(n, k - 1);
	else
		return 1.0 / Pow(n, -k);
}

int main()
{
	int n = 0;
	int k = 0;
	scanf("%d %d", &n, &k);

	double ret = Pow(n, k);

	printf("%lf\n", ret);

	return 0;
}

要注意考虑k<0的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值