【ONE·C || 函数与数组】

news2024/9/26 5:14:07

总言

  C语言:函数、数组初步认识。

文章目录

  • 总言
  • 1、函数
    • 1.1、是什么
      • 1.1.1、基本介绍
      • 1.1.2、库函数使用演示(strcpy、memset)
      • 1.1.3、自定义函数使用演示
    • 1.2、函数参数、传值调用和传址调用
    • 1.3、相关练习
      • 1.3.1、写一个函数:可以判断一个数是不是素数
      • 1.3.2、写一个函数:判断一年是不是闰年
      • 1.3.3、写一个函数:实现一个整形有序数组的二分查找
      • 1.3.4、写一个函数:每调用一次这个函数,就会将 num 的值增加1
    • 1.4、函数的嵌套调用和链式访问
      • 1.4.1、函数嵌套调用
      • 1.4.2、函数链式访问(printf返回值介绍)
    • 1.5、函数声明和定义
    • 1.6、函数递归
      • 1.6.1、概念与递归的必要条件
      • 1.6.2、相关练习演示
        • 1.6.2.1、接受一个整型值(无符号),按照顺序打印它的每一位
        • 1.6.2.2、编写函数不允许创建临时变量,求字符串的长度
        • 1.6.2.3、求n的阶乘(不考虑溢出)
        • 1.6.2.4、求第n个斐波那契数(不考虑溢出)
  • 2、数组
    • 2.1、一维数组
      • 2.1.1、一维数组创建
      • 2.1.2、一维数组初始化
      • 2.1.3、一维数组使用与存储
    • 2.2、二维数组
      • 2.2.1、二维数组创建与初始化
      • 2.2.2、二维数组的基本使用
      • 2.2.3、二维数组在内存中的存储
    • 2.3、数组越界
    • 2.4、数组作为函数参数
      • 2.4.1、数组名初步认识
      • 2.4.2、冒泡排序设计1.0

  
  

1、函数

1.1、是什么

1.1.1、基本介绍

  1)、C语言中函数的分类

库函数
自定义函数

  库函数: 早期的C语言是没有库函数的,此时由于各有各的方法实现,会带来如下问题:功能类似,但代码冗余、开发效率低、不标准。因此把一些常用的功能实现为函数,集成为库,由C语言提供。
  
  自定义函数: 由我们自己设计实现的函数,即为自定义函数,能满足我们个人需求。自定义函数和库函数一样,有函数名,返回值类型函数参数

ret_type fun_name(para1, * )
{
 statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1    函数参数
{} 函数体

  
  
  

1.1.2、库函数使用演示(strcpy、memset)

  1)、库函数strcpy使用演示
在这里插入图片描述

  演示要求:拷贝字符串,并验证结尾字符"\0"也一并拷贝了。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdefg";
	char arr2[20] = "xxxxxxxxxxx";
	strcpy(arr2, arr1);

	return 0;
}

在这里插入图片描述

  
  
  2)、库函数memset使用演示
在这里插入图片描述

  演示要求:将数组前五个元素值设置为“X”

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "hello world!";
	memset(arr, 'X', 5);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述
  
  
  

1.1.3、自定义函数使用演示

  1)、写一个函数:可以找出两个整数中的最大值

int get_max(int x, int y)
{
	return (x > y) ? (x) : (y);
}


int main()
{
	int num1 = 0;
	int num2 = 0;
	scanf("%d %d",&num1,&num2);
	int max = get_max(num1, num2);
	printf("max = %d\n", max);
	return 0;
}

  
  
  2)、写一个函数:可以交换两个整形变量的内容

#include <stdio.h>
void Swap1(int x, int y)//传值
{
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}
void Swap2(int* x, int* y)//传引用
{
	int tmp = 0;
	tmp = *x;
	*x = *y;
	*y = tmp;
}
int main()
{
	int num1 = 1;
	int num2 = 2;
	Swap1(num1, num2);
	printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
	Swap2(&num1, &num2);
	printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
	return 0;
}

在这里插入图片描述
  
  
  

1.2、函数参数、传值调用和传址调用

  1)、基本介绍

实际参数(实参):真实传给函数的参数
形式参数(形参):是指函数名后括号中的变量

  实参:
    ①可以是常量、变量、表达式、函数等。
    ②无论实参是何种类型的量,在进行函数调用时都必须有确定的值,以便把这些值传送给形参。
  
  形参:
    ①形式参数只有在函数被调用的过程中才实例化(分配内存单元)
    ②形式参数在函数调用完成之后就自动销毁。
  
  
  
  2)、传值调用和传址调用

**传值调用:**
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

**传址调用:**
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

  
  
  

1.3、相关练习

1.3.1、写一个函数:可以判断一个数是不是素数

#include<math.h>
int is_prime(int val)
{
	//试除法
	//2~n-1  \  2~sqrt(n)
	for (int i = 2; i < sqrt(val); ++i)
	{
		if(val % i == 0)//说明有别的因数
		{
			return 0;
		}
	}
	return 1;
}

int main()
{
	//任务目标:判断100~200间的素数
	for (int i = 101; i <= 200; i+=2)//首先排除偶数
	{
		if (is_prime(i) == 1)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

在这里插入图片描述

  
  
  
  

1.3.2、写一个函数:判断一年是不是闰年

int is_leap_year(int year)
{
	//四年一闰,百年不闰;
	//四百年一闰;
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		return 1;
	}
	return 0;
}

int main()
{
	//任务目标:打印1000~2000年之间的闰年

	//产生年份
	for (int y = 1000; y <= 2000; ++y)
	{
		//判断
		if (is_leap_year(y) == 1)
		{
			printf("%d ", y);
		}
	}
	printf("\n");

	return 0;
}

在这里插入图片描述
  
  
  

1.3.3、写一个函数:实现一个整形有序数组的二分查找

int binary_search(int arr[],int key,int len)
{
	int left = 0;
	int right = len - 1;
	while (left <= right)
	{
		int mid = left + (right - left) / 2;

		if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else
		{
			return mid;

		}
	}
	return -1;
}


int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//有序数组
	int key = 0;
	printf("输入要查找的数字:");
	scanf("%d", &key);
	int len = sizeof(arr) / sizeof(arr[1]);
	int ret=binary_search(arr, key, len);
	if (-1 == ret)
	{
		printf("找不到\n");
	}
	else {
		printf("找到了,下标为:%d\n", ret);

	}
	return 0;
}

  一个问题:binary_search能否不传递实参len,而是选择在函数体内计算int len = sizeof(arr) / sizeof(arr[1]);

binary_search(arr, key);

  回答:arr数组传参,传递的不是整个数组,而是数组首元素地址。int arr[]本质上是int* arr
  
  
  

1.3.4、写一个函数:每调用一次这个函数,就会将 num 的值增加1

void test(int* num)
{
	(*num)++;//优先级问题
}

int main()
{
	int num = 0;
	int n = 5;//调用次数
	while (n)
	{
		test(&num);//传址
		n--;
	}
	printf("%d\n", num);
	return 0;
}

在这里插入图片描述
  
  
  

1.4、函数的嵌套调用和链式访问

1.4.1、函数嵌套调用

  1)、是什么
  函数和函数之间可以根据实际的需求进行组合,也就是互相调用的。

void new_line()
{
    printf("hehe\n");
}
void three_line()
{
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        new_line();
    }
}
int main()
{
    three_line();
    return 0;
}

  衍生思考:函数是否能嵌套定义?

int main()//函数一
{
    void three_line()//函数二
    {
        int i = 0;
        for (i = 0; i < 3; i++)
        {
            void new_line()//函数三
            {
                printf("hehe\n");
            }
        }
    }    
    return 0;
}

  回答:不能。
  
  

1.4.2、函数链式访问(printf返回值介绍)

  1)、是什么
  把一个函数的返回值作为另外一个函数的参数,称之为链式访问。

#include<string.h>
int main()
{
	int len = strlen("abcdef");
	printf("%d\n", len);

	printf("%d\n", strlen("abcdef"));
	return 0;
}

在这里插入图片描述
  
  
  2)、其它一些例子
  如下,以下结果是什么?

int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	return 0;
}

在这里插入图片描述
在这里插入图片描述
  
  
  
  

1.5、函数声明和定义

  函数声明:

1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
3. 函数的声明一般要放在头文件中的。

  
  函数定义:

函数的定义是指函数的具体实现,交待函数的功能实现。

  
  演示举例:

//函数声明
int get_max(int x, int y);
int get_max(int , int );//可以把形参名字省略


int main()
{
	int num1 = 10;
	int num2 = 20;
	int max = get_max(num1, num2);
	printf("max = %d\n", max);
	return 0;
}


//函数定义
int get_max(int x, int y)
{
	return (x > y) ? (x) : (y);
}

  
  
  

1.6、函数递归

1.6.1、概念与递归的必要条件

  1)、是什么
  说明:递归即函数调用其本身,其主要思想在于把大事化小,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。类似于一个深层的嵌套(俄罗斯套娃)。

  以下为一个演示例子:main函数自己调用其本身

//main函数自己调用自己
#include<stdio.h>
int main(void)
{
	printf("hehe\n");
	main();
	return 0;
}

在这里插入图片描述
  如上图,虽然是实现了递归,但其结果为程序终止,通过调试发现,造成程序终止的原因是栈溢出。
  
  
  2)、递归的两个使用条件
  1、递归存在限制条件,符合限制条件后,递归停止。
  2、每次递归调用,都要朝这一限制条件发展
  
  
  

1.6.2、相关练习演示

1.6.2.1、接受一个整型值(无符号),按照顺序打印它的每一位

例如:
输入:1234,输出 1 2 3 4.

  1)、假如采用非递归法,实现如下:
  要正位打印每一个数,可将其不同数位上的数一一剥离。通常来说十进制下,/10、%10能做得到。但如果直接运用,得到的则是4321逆序,所以我们可以将剥离下的每个位数先存放在数组中,再逆序打印。

int main()
{
	unsigned int num = 0;

	scanf("%u", &num);

	int digit = 0;//统计num位数
	int arr[10] = { 0 };//存储num每个位数,10为32位下无符号整型最大位数
	while (num)
	{
		arr[digit] = num % 10;
		num /= 10;
		digit++;
	}
	for (int i = digit - 1; i >= 0; i--)//倒序打印
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

  
  2)、假如采用递归,实现如下:
  在递归方式中,对于1234仍旧采用/10、%10的方法,只是我们将数字分为两部分,对末位数,将其剥离打印,对非末位数,再次调用函数剥离。故有:
  f(1234)=f(123)+4
  f(123)=f(12)+3
  f(12)=f(1)+2
  

void print(unsigned int num)
{
	if (num > 9)//说明num目前大于个位
	{
		print(num / 10);
	}
	printf("%d ",(num % 10));
}


int main()
{
	unsigned int num = 0;
	scanf("%u", &num);
	print(num);
	return 0;
}

  上述print中,if条件语句printf打印二者顺序至关重要,其决定着输出结果顺序问题。由于一上来就满足if语句,所以进入递归调用函数,直到来到终止条件时,执行printf语句,然后再层层递归返回,完成相应递归层中没有执行的函数语句。

在这里插入图片描述

  
  
  

1.6.2.2、编写函数不允许创建临时变量,求字符串的长度

  1)、使用库函数的情况如下:
  arr存储的是a、b、c、d、e、f、\0strlen求得'\0'前字符长度。

#include <stdio.h>
#include <string.h>
int main(void)
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	return 0;
}

  
  
  2)、创建临时变量的情况如下:

int mystrlen(char* arr)
{
	int count = 0;
	while (*arr != '\0')
	{
		count++;
		arr++;
	}
	return count;
}
int main(void)
{
	char arr[] = "abcdef";
	printf("%d", mystrlen(arr));
	return 0;
}

  
  
  3)、不允许创建临时变量的情况如下
  f("abc")=1+f("bc")
  f("bc")=1+f("c")
  f("c")=1+f(‘\0')
  f(‘\0')=0
  既有:f("abc")=1+f("bc")=1+1+f("c")=1+1+1+f(‘\0')=3

#include <stdio.h>
int mystrlen(char* arr)
{
	if (*arr == '\0')
		return 0;
	return 1 + mystrlen(++arr);
}
int main(void)
{
	char arr[] = "abcdef";
	printf("%d", mystrlen(arr));
	return 0;
}

  
  
  

1.6.2.3、求n的阶乘(不考虑溢出)

  1)、使用非递归的方法

//非递归方式:
#include<stdio.h>
int main(void)
{
	int n;
	scanf("%d", &n);

	int sum = 1;
	while (n > 0)
	{
		sum *= n;
		n--;
	}
	return 0;
}

  
  
  2)、使用递归的方法

//用递归的方式:
int factorial(int n)
{
	if (n <= 1)
		return 1;
	else
		return n * factorial(n - 1);
}
int main(void)
{
	int n;
	scanf("%d", &n);
	printf("%d", factorial(n));
	return 0;
}

  
  
  

1.6.2.4、求第n个斐波那契数(不考虑溢出)

  1)、使用递归的方法

//以递归方式实现:
#include<stdio.h>
int fib(int n)
{
	if (n <= 2)
		return 1;
	return fib(n - 1) + fib(n - 2);
}
int main(void)
{
	int n;
	scanf("%d", &n);
	printf("%d", fib(n));
	return 0;
}

  
  
  2)、使用非递归的方法
  非递归的方法能解决此处的递归效率问题。

//以非递归的方式实现:
#include<stdio.h>
int fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;//此处为c赋值为1不影响后续计算,且能解决第一、第二个斐波那契数
	while (n - 2)//头俩项不需要计算,从第三项开始,第三项需要循环1次,第四项循环2次,以此类推,第n项循环n-2次。
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main(void)
{
	int n;
	scanf("%d", &n);
	printf("%d", fib(n));
	return 0;
}

  
  
  
  
  

2、数组

2.1、一维数组

2.1.1、一维数组创建

  1)、基本介绍
  数组:一组相同类型元素的集合。

type_t   arr_name   [const_n];
//type_t 数组的元素类型
//arr_name 数组名
//const_n 常量表达式,用来指定数组的大小

  
  2)、演示实例

  一般情况如下:

int arr1[10];

  关于数组元素大小是否能用变量的说明:
  C99标准之前,不支持使用变量,只能是常量。C99中,新增了变长数组的概念,允许数组的大小是变量,而且要求编译器支持C99标准

int count = 10;
int arr2[count];

  同样的,即使用const修饰变量后为数组定义大小,因其是常变量,也要求编译器支持C99标准。

const int count = 10;
int arr2[count];

  需要注意:

  1、const修饰的count,在C语言中属于常变量,在C++中属于常量。因此假若我们用.cpp文件来实现,在VS中是能运行成功的。

  2、变长数组不能初始化。因为元素个数的不确定性,初始化数组是无意义的。比如,变长数组中元素个数是根据scanf函数来自设的,则初始化变长数组便是无意义之事。

int count = 10;
scanf("%d",&count);
int arr2[count];

  
  

2.1.2、一维数组初始化

  数组的初始化,是指在创建数组的同时给数组的内容一些合理初始值。
  

  1)、整型数组初始化相关演示

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化
	int arr2[10] = { 1,2,3,4};//不完全初始化
	return 0;
}

在这里插入图片描述
  
  假如数组不初始化,其内部放置的是随机值,根据编译器而定,有的会是0xcccccccc,有的会是0xcdcdcdcd,不唯一,局部变量同理。但要注意,全局变量不初始化时默认值为0静态变量同理

int a;//全局变量
int main()
{
	int arr3[10];//不初始化
	int b;//局部变量
	static int c;//静态变量
	printf("%d\n", a);
	printf("%d\n", c);
	return 0;
}

  原因:内存空间被划分为不同区域,对于全局变量、静态变量,其放置在静态区,默认初始化为0;对于局部变量,一些形式参数,其放置在栈区,默认不初始化时为随机值。
在这里插入图片描述

  
  2)、字符型数组初始化相关演示

int main()
{
	char ch1[] = { 'a','b','c','d' };
	char ch2[] = { 'a',98,'c','d' };//字符b的ASCII码值为98
	char ch3[] = "abcd";//'a','b','c','d','\0'
	char ch4[6]= { 'a','b','c','d' };//不完全初始化,默认0,对应ASCII为'\0'
	return 0;
}

在这里插入图片描述
  致于此处涉及的strlen相关介绍,我们在初识C语言那一章节中有讲述。

  
  
  

2.1.3、一维数组使用与存储

  1)、如何访问一维数组元素:下标引用操作符
  数组是使用下标来访问的,下标从0开始。

#include <stdio.h>
int main()
{
    int arr[10] = { 0 };//数组的不完全初始化
    int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的元素个数
    int i = 0;//做下标
    for (i = 0; i < sz; i++)//遍历赋值
    {
        arr[i] = i;
    }
    for (i = 0; i < sz; ++i)//遍历打印
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

  arr[i]:需要注意的是,虽然我们说,在非C99标准下,不能使用变量来定义数组大小,但从未规定,在使用下标引用操作符访问数组时,我们不能使用变量。[ ]左操作数是数组名,右操作数是下标大小。
在这里插入图片描述

  
  
  2)、一维数组在内存中的存储

#include <stdio.h>
int main()
{
    int arr[10] = { 0 };
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);

    for (i = 0; i < sz; ++i)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);
    }
    return 0;
}

在这里插入图片描述

  观察可得:
  1、一维数组在内存中连续存放。
  2、随着数组下标的增长,地址是由低到高变化的。(这样做就方便使用指针来操作)

int*p=arr;//数组首元素
p+1;//int* ,+1 得下一个元素,依此类推

  
  为什么地址间相差4的原因:
  整型元素内存大小是4字节,而一个字节有一个地址,四个字节就占据了四个地址,即用四个地址表示一个整型元素。
  
  
  
  

2.2、二维数组

2.2.1、二维数组创建与初始化

  1)、二维数组创建

//数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];

  2)、二维数组初始化

//数组初始化
int arr[3][4] = {1,2,3,4};
//1、先放行,行满跳下一列,值不够时默认为0
//2、不完全初始化,默认为0。
int arr[3][4] = {{1,2},{4,5}};
//1、若规定了行列具体元素,可用花括号分隔
int arr[][4] = {{2,3},{4,5}};
//1、二维数组如果有初始化,行可以省略,列不能省略

  对于省略行的情况,一行溢出的数组元素可以换行排列。但如果省略行列,如下述情况,数组可能为arr[1][10]arr[2][5]arr[5][2], arr[10][1],故同时省略行和列是非法的。

int arr[ ][ ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 

  
  
  

2.2.2、二维数组的基本使用

  二维数组的使用也是通过下标的方式。[][]指定行、列。

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

在这里插入图片描述

  问题:
  类似于int arr[][4],是否能算处单独的行、列?

//行:
    int row = sizeof(arr) / sizeof(arr[0]);//整个数组大小/任意一行大小
//列:
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);//某一行整体元素大小/该行单个元素大小

在这里插入图片描述

  
  
  

2.2.3、二维数组在内存中的存储

#include <stdio.h>
int main()
{

    int arr[][4] = { {1,2,3},{2,3,4},{3,4,5},{4,5,6} };
    int row = sizeof(arr) / sizeof(arr[0]);//整个数组大小/任意一行大小
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);//某一行整体元素大小/该行单个元素大小
    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

在这里插入图片描述
  由上述结果可知,这也是为什么二维数组初始化时行可以省略,列不能省略的原因。因为二维数组连续存放,不知道行但知道了列,也能在内存区域中划分处二维数组具体行列大小。
  
  另外,需要注意的是,对于二维数组,可以将每行视作一维数组。其数组名称为arr[0]arr[1]arr[2]arr[3]
  对每行元素的访问,相当于arr[0][j]arr[1][j]arr[2][j]arr[3][j]
  即二维数组是一维数组的数组:二维数组arr[4][4]的元素个数有有三个,每个元素都是一个一维数组(以int为类型,元素个数为4个的数组)
  
  
  
  

2.3、数组越界

  基本描述:
在这里插入图片描述
  如下述代码:

#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 ", arr[i]);//当i等于10的时候,越界访问了
    }
    return 0;
}

在这里插入图片描述
  需要注意的是,二维数组也存在越界。那么,二维数组越界在内存中的显示?
  由于二维数组在内存中同一维数组一样是连续排列的,而且是每行排列完后接着下一行。由此可知,若二维数组越界,对于最后一行最后元素,越界会访问到数组外的内存空间,对于数组内部,越界会访问到后续行中元素。
  
  
  

2.4、数组作为函数参数

2.4.1、数组名初步认识

  数组名是数组首元素地址。
  但有两个例外:
  1、sizeof(数组名),此时数组名表示整个数组,计算的是整个数组的大小。
  2、&数组名。此处数组名表示整个数组,取出的是整个数组的地址。

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

    printf("\nsizeof(arr):%d\n\n",sizeof(arr));

    printf("arr:    %p\n", arr+1);
    printf("arr[0]: %p\n", &arr[0]+1);
    printf("&arr:   %p\n", &arr+1);

    return 0;
}

在这里插入图片描述

  
  
  
  

2.4.2、冒泡排序设计1.0

void bubble_sort(int arr[], int size)
{
	//总趟数
	for (int i = 0; i < size - 1; ++i)
	{
		int flag = 1;//用于判断数组本身是否已经有序

		//单趟数
		for (int j = 0; j < size - 1 - i; ++j)
		{
			
			if (arr[j] > arr[j + 1])//排升序
			{
				flag = 0;
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		if (flag == 1)//说明没有进入单趟交换
		{
			break;
		}
	}

}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };

	//要求:写一个冒泡排序,将数组arr排为升序。
	int size = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, size);
	for (int i = 0; i < size; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

  
  
  
  
  
  
  
  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/170466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

集成学习-理论概述

1、集成学习概述集成学习(ensemble learning)本身不是一个单独的机器学习算法&#xff0c;而是通过构建并结合多个机器学习器来完成学习任务。集成学习的特点&#xff1a;集成方法是一种将几种机器学习技术组合成一个预测模型的元算法&#xff0c;以减小方差&#xff08;baggin…

python-文件和异常

1. 从文件中读取数据1.1. 读取整个文件在同目录下创建textA文本文件123 456 789a. open函数&#xff1a;要以任何方式去使用文件&#xff0c;都需要先打开文件&#xff0c;它接受一个参数——要打开文件的名称。 open()返回一个表示文件的对象。b. 关键字with在不再需要访问文件…

可以自动生成日报的清单工具

用过了很多todolist工具&#xff08;Microsoft_ _To D、oodoist、滴答清单、印象笔记、有道笔记、&#xff09; 最终稳定一直在用的就这一个“闪点清单” 我的核心诉求就两点 1. 可以实时记录任务&#xff0c;并标记是否完成 2. 可以按天、周导出&#xff0c;自动整合成日报…

《计算机构造与解释》读书笔记(4)

文章目录1. 写在最前面2. 并发&#xff1a;时间是一个本质问题2.1 并发系统中时间的性质2.1.1 并发程序的正确行为2.2 控制并发的机制2.2.1 对共享变量的串行访问2.2.2 Schema 里的串行化2.2.3 使用多重共享资源的复杂性2.2.4 串行化实现2.2.5 死锁2.2.6 并发性、时间和通信3. …

Linux学习记录——구 进程概念的基础理解

文章目录一、操作系统概念理解二、进程的基本理解1、什么是进程&#xff1f;2、进程的属性1、指令查看进程2、目录查看进程3、进程与进程之间1、父子进程概念2、创建子进程---fork的基础使用方法3、fork原理的初级理解1、fork的操作2、fork如何看待代码和数据3、fork如何看待两…

【Docker概念和实践 2】虚拟机 ubuntu18上安装docker

一、说明 已经安装了N遍Docker了&#xff0c;逐步成了一套习惯&#xff0c;这里专门记录之&#xff1b;总之&#xff0c;安装前必须回答得问题是&#xff1a;何种操作系统、何种版本、是否虚拟机、云数据源等问题。一个环境如果装得好&#xff0c;就不需要重装&#xff0c;如果…

C语言刷题之摩尔投票法

目录 1.引入 2.摩尔投票算法 3.基本步骤 摩尔投票法分为两个阶段&#xff1a; 1.抵消阶段 2.检验阶段 4.代码实现 5.扩展沿伸 6.总结 1.引入 我们来看一个问题&#xff1a; 假设有一个无序数组长度为n&#xff0c;要求找出其中出现次数超过n/2的数&#xff0c;要求时间复…

vue3-环境搭建(docker版本)

序 大大小小项目经历无数&#xff0c;之前都是写的vue2的项目&#xff0c;因为项目需要&#xff0c;边学边用vue3&#xff0c;也算能转的开&#xff0c;但心里一直想系统的理顺一下vue3。 看了看极客时间&#xff0c;掘金小课&#xff0c;都没有能达到心里预期的“系统学习”…

免费内网穿透软件一步设置实现外网访问

在工作和生活中&#xff0c;有很多类似内网搭建服务器和外网连接内网的需求&#xff0c; 例如在任何地方都能访问自己家里的主机电脑笔记本上的应用&#xff0c;让出差外网和任何地方都能访问到公司内部局域网的服务器……这些需求我们可以统一用一个方案解决&#xff0c;那就是…

网络编程UDP+TCP

日升时奋斗&#xff0c;日落时自省 目录 1、网络编程基本概念 2、UDP数据报套接字编程 2.1、UDP相关API 2.1.1、DatagramSocket API 2.1.2、DatagramPacket API 2.2、UDP版本服务器 2.3、UDP版本客户端 2.4、UDP连接操作 2.5、翻译业务 2.6、总结 3、TCP流套接字编程 …

【项目实战】一文入门项目中Lombok的常用注解

一、Lombok介绍 1.1 Lombok是什么&#xff1f; 一个Java库&#xff0c;用于简化Java代码。 Lombok是一个非常神奇的 java 类库&#xff0c;会利用注解自动生成 java Bean 中烦人的 Getter、Setting&#xff0c;还能自动生成 logger、ToString、HashCode、Builder 等 java特色…

【GD32F427开发板试用】开发一款网络音乐播放器

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;守勤 资源介绍 非常荣幸能够参与到这次GD32F427开发板试用的活动中来&#xff0c;开发板的设计非常简洁&#xff0c;板载了一颗GD32F103C8T6和…

Python中的递归及案例演示

目录 一.什么是递归 二.案例 递归找文件 步骤 os模块中的三个方法 演示 最终代码 三.总结 一.什么是递归 递归在编程中是一种非常重要的算法 递归:即方法(函数)自己调用自己的一种特殊编程写法 如&#xff1a; 函数调用自己&#xff0c;即称之为递归调用。 二.案例 递…

C++ 引用! 他是坤坤也是鸡哥

&#x1f451;专栏内容&#xff1a;C学习笔记⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;日拱一卒&#xff0c;功不唐捐 目录一、前言二、引用1、引用的概念2、引用的声明3、引用的特性Ⅰ、 引用在定义时必须初始化Ⅱ、 一个变量可以有多个引用Ⅲ、引…

深度学习PyTorch 之 DNN-多分类

前面讲了深度学习&PyTorch 之 DNN-二分类&#xff0c;本节讲一下DNN多分类相关的内容&#xff0c;这里分三步进行演示 结构化数据 我们还是以iris数据集为例&#xff0c;因为这个与前面的流程完全一样&#xff0c;只有在模型定义时有些区别 损失函数不一样 二分类时用的损…

Pollard Rho算法

生日悖论 假设一年有nnn天&#xff0c;房间中有kkk人&#xff0c;每个人的生日在这nnn天中&#xff0c;服从均匀分布&#xff0c;两个人的生日相互独立 问至少要有多少人&#xff0c;才能使其中两个人生日相同的概率达到ppp 解&#xff1a;考虑k≤nk\le nk≤n 设kkk个人生日互…

Spring框架介绍及使用

文章目录1.概述1.1 Spring是什么1.2 Spring 的优势1.3 spring 的体系结构2. IoC 的概念和作用2.1 什么是程序的耦合2.2 IoC容器3. AOP的概念和作用超链接&#xff1a; Spring重点内容学习资料1.概述 1.1 Spring是什么 Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源…

使用docker-compose搭建Prometheus+Grafana监控系统

一、角色分配 Prometheus 采集数据Grafana 用于图表展示redis_exporter 用于收集redis的metricsnode-exporter 用于收集操作系统和硬件信息的metricscadvisor 用于收集docker的相关metrics 二、安装Docker 可以参考&#xff1a;https://ximeneschen.blog.csdn.net/article/d…

JVM调优实战:to-space exhausted Evacuation Failure

一次线上dubbo问题的定位&#xff0c;进行JVM调优实战。问题线上dubbo接口provider抛出异常&#xff1a;org.apache.dubbo.rpc.RpcException: Failfast invoke providers ... RandomLoadBalance select from all providers ... use dubbo version 2.7.16, but no luck to perfo…

vulnhub DC系列 DC-8

总结&#xff1a;exim4提权 目录 下载地址 漏洞分析 信息收集 网站爆破 后台webshell 提权 下载地址 DC-8.zip (Size: 379 MB)Download: http://www.five86.com/downloads/DC-8.zipDownload (Mirror): https://download.vulnhub.com/dc/DC-8.zip使用方法:解压后&#xff…