1> 逆序
所谓逆序,就是将数据进行首尾交换,例如,数组原型:1,2,3,4,5。逆序后的数组为:5,4,3,2,1
总结套路:
1、需要进行首尾交换的次数是 MAX/2 (MAX表示数组的长度)
2、交换双方:arr[i] <==> arr[MAX-1-i]
示例:
#include <stdio.h>
#define MAX 10
int main(int argc, char const * argv[])
{
int score[MAX]={0};
for(int i=0;i<MAX;i++)
{
printf("请输入第%d个学生的成绩:",i+1);
scanf("%d",&score[i]);
}
printf("数组中的元素分别是:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
//将数组进行逆序
for(int i=0;i<MAX/2;i++) //只需遍历前一半数组
{
//交换三部曲
int temp=score[i];
score[i]=score[MAX-1-i];
score[MAX-1-i]=temp;
}
//输出逆序后的数组
printf("逆序后的结果为:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
return 0;
}
运行结果:
2> 挑选数据
示例:
#include <stdio.h>
#define MAX 10
int main(int argc, char const * argv[])
{
int score[MAX]={0};
for(int i=0;i<MAX;i++)
{
printf("请输入第%d个学生的成绩:",i+1);
scanf("%d",&score[i]);
}
printf("数组中的元素分别是:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
//想要将大于90的数据,挑选出来放入新数组
int brr[MAX]={0};
int k=0; //遍历新数组的循环变量
for(int i=0;i<MAX;i++) //遍历原数组
{
//设定筛选条件
if(score[i]>=90)
{
brr[k]=arr[i];
k++; //继续记录下一个数组元素
}
}
//输出新数组的内容
printf("满足条件的元素分别是:");
for(int i=0;i<k;i++)
{
printf("%d\t",brr[i]);
}
putchar(10);
return 0;
}
运行结果:
3> 排序
1、排序的概念:将一组数据按照关键字进行升序或降序的方式重新排列的过程称为排序
冒泡排序
1、冒泡排序:将较大或者较小的数据,经由交换后,慢慢“浮到”数组顶端,如同水中的气泡一样,故名冒泡排序
原理:不断进行相邻的两个数据进行比较,如果满足条件,则进行交换,每一轮都会将一个最值数据"浮到"对应位置
对于每一轮重复上述操作,直到所有数据排序结束
示例:
#include <stdio.h>
#define MAX 10
int main(int argc, char const * argv[])
{
int score[MAX]={0};
for(int i=0;i<MAX;i++)
{
printf("请输入第%d个学生的成绩:",i+1);
scanf("%d",&score[i]);
}
printf("数组中的元素分别是:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
//将成绩数组进行升序排序
//由于趟数跟元素无关,所以从1开始
for(int i=1;i<MAX;i++)
{
for(int j=0;j<MAX-i;j++)
{
if(score[j]>score[j+1]) //降序为 score[j]<score[j+1]
{
//交换三部曲
int temp=score[j];
score[j]=score[j+1];
score[j+1]=temp;
}
}
}
//输出排序后的数组
printf("排序后的结果为:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
return 0;
}
运行结果:
选择排序
2、选择排序:将要排序的序列分为已排序序列和待排序序列
不断从待排序序列中找到最值,放入已排序序列的最后位置,随着待排序序列不断减少,已排序序列不断增长
直到待排序序列没有元素,排序结束
示例:
#include <stdio.h>
#define MAX 10
int main(int argc, char const * argv[])
{
int score[MAX]={0};
for(int i=0;i<MAX;i++)
{
printf("请输入第%d个学生的成绩:",i+1);
scanf("%d",&score[i]);
}
printf("数组中的元素分别是:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
//使用选择排序完成降序排序
int maxi=0; //记录最值的下标
for(int i=0;i<MAX;i++) //遍历整个数组
{
//将待排序序列的第一个当做最值
maxi=i;
//遍历所有的元素,跟当前的最值进行判断
for(int j=i+1;j<MAX;j++)
{
if(score[maxi]<score[j]) //升序为 score[maxi]>score[j]
{
maxi=j; //更新最值所在的下标
}
}
//程序执行至此,表示后面部分的最值已经被定位
//判断找到的最值,是否是待排序列的第一个
//如果不是,则进行交换
if(maxi != i)
{
//交换三部曲
int temp=score[i];
score[i]=score[maxi];
score[maxi]=temp;
}
}
//输出排序后的数组
printf("排序后的结果为:");
for(int i=0;i<MAX;i++)
{
printf("%d\t",score[i]);
}
putchar(10);
return 0;
}
运行结果:
二维数组
1.1引入目的
1> 当写程序时,需要同时定义多个相同类型的一维数组时,可以选择二维数组来完成
2.2二维数组的概述
1> 定义格式:
数据类型 数组名[常量1][常量2];
常量1:表示定义数组时数组的行数,也可以理解成一维数组的个数
常量2:表示定义数组时的列数,也可以理解成每个一维数组的长度
2>使用格式:
1、数组名[行标]:表示下标为"行号"的那个一维数组的数组名
2、数组名[行标][列标]:表示下标为 [行标][列标] 的一个变量
举个例子:
int arr[3][4]; //该句定义了一个3*4的二维数组,也可以理解成定义了3个长度为4的一维数组
arr[0]: 表示第一个一维数组的数组名
arr[1]: 表示第二个一维数组的数组名
arr[2]: 表示第三个一维数组的数组名
arr[0][0]: 表示第一行第一列的一个变量
arr[0][0]、arr[0][1]、arr[0][2]、arr[0][3]
arr[1][0]、arr[1][1]、arr[1][2]、arr[1][3]
arr[2][0]、arr[2][1]、arr[2][2]、arr[2][3]
3、定义数组时,中括号中的数字表示定义二维数组的行数和列数,而使用数组元素时,中括号中的数字表示的是坐标
4、无论是行标还是列表,都是从0开始,到对应数据减1的位置
例如:int arr[M][N];
行标范围:【0,M-1】
列标范围:【0,N-1】
3> 二维数组初始化
1、按行初始化:定义数组时,每一个一维数组的值使用一个花括号括起来
int arr[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,9,9,9} };
2、按行部分初始化:每个一维数组中,可以不填满,没有初始化的部分用0补齐
int arr[3][4] = { {1,2}, {8}}; //1,2,0,0 8,0,0,0 0 ,0, 0, 0
3、按数组排列初始化:数组存储数据时,默认是按顺序存储,第一行存储满了,存第二行 int arr[3][4] = { 1,2,3,4,5,6,7,8, 9}; //1,2,3,4 5,6,7,8, 9,0,0,0
4、特殊初始化:定义二维数组并初始化时,可以不指定第一维的大小,由初始化总个数除以列数向上取整,得到行数
int arr[][4] = { 1,2,3,4,5,6}; // 1,2,3,4 5,6,0,0
5、注意:定义二维数组时,无论任何时候,第二维都不能省略
二维数组的相关操作
1> 输入输出
对于二维数组而言,是有行有列的元素集合,需要使用双重循环来进行定位横标和纵标
在双重循环中,找到任意一个元素 arr[i][j] 来对其进行输入输出
示例:
#include <stdio.h>
#define M 3
#define N 4
int main(int argc, char const * argv[])
{
//定义一个二维数组
int arr[M][N]={0};
//对数组进行输入输出,通过双重循环找到任意一个数据
for(int i=0;i<M;i++) ///外行
{
for(int j=0;j<N;j++) //内行
{
//在此处可以找到arr[i][j]
printf("请输入第%d行%d列的元素:",i+1,j+1);
scanf("%d",&arr[i][j]);
}
printf("\n");
}
//将上述数组进行输出
printf("数组元素分别是:\n");
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("%d\t",arr[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
2> 求和、均值、最值
2、求每一行的和:将每一行的数据进行累加,求出结果后,可以放入一个新数组
3、求整体最值:先将第一个当做最值,然后遍历所有的元素,进行比较,给定比较条件后,适当更新最值
4、求每一行的最值:在外层循环内,先将当前行的第一个当做最值,然后遍历当前行的所有数据,进行比较和更新
3> 转置
3、转置核心代码:brr[j][i] = arr[i][j]
示例:
#include <stdio.h>
#define M 3 //二维数组的行数
#define N 4 //二维数组的列数
int main(int argc, char const * argv[])
{
//定义一个二维数组
int arr[M][N]={0};
//对数组进行输入输出,通过双重循环找到任意一个数据
for(int i=0;i<M;i++) ///外行
{
for(int j=0;j<N;j++) //内行
{
//在此处可以找到arr[i][j]
printf("请输入第%d行%d列的元素:",i+1,j+1);
scanf("%d",&arr[i][j]);
}
printf("\n");
}
//将上述数组进行输出
printf("数组元素分别是:\n");
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("%d\t",arr[i][j]);
}
printf("\n");
}
//将二维数组中的每一行的和求出后,放入到一个一位数组中
int sum[M]={0};
for(int i=0;i<M;i++) ///外行
{
for(int j=0;j<N;j++) //内行
{
sum[i]+=arr[i][j];
}
}
printf("每一行的和分别是:");
for(int i=0;i<M;i++)
{printf("%d\t",sum[i]);
}
putchar(10);
//将二维数组中的每一行的和求出后,放入到一个一位数组中
int max=arr[0][0];
int maxi=0;
int maxj=0;
for(int i=0;i<M;i++) ///外行
{
//找到当前行的任意一个元素
for(int j=0;j<N;j++) //内行
{
//跟当前的最值进行比较
if(max<arr[i][j])
{
max=arr[i][j];
maxi=i;
maxj=j;
}
}
}
printf("最大值信息:arr[%d][%d] = %d\n",maxi,maxj,max);
//求每一行的和并输出
for(int i=0;i<M;i++) //外行
{
//将当前行的第一个当当做最值
max=arr[i][0];
//找到当前行的任意一个元素
for(int j=0;j<N;j++)
{
//跟任意一个元素进行比较
if(max<arr[i][j])
{
max=arr[i][j];
}
}
//输出当前行的最值
printf("第%d行的最大值为:%d\n",i+1,max);
}
//将上面的二维数组进行转换
int brr[N][M]={0};
for(int i=0;i<M;i++) //外行
{
//找到当前行的任意一个元素
for(int j=0;j<N;j++)
{
//在此处找到了任意一个元素 arr[i][j]
brr[j][i]=arr[i][j];
}
}
printf("上述二维数组转置后的结果如下:\n");
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
printf("%d\t",brr[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
练习:
使用二维数组存储杨辉三角
代码:
#include <stdio.h>
#define MAX 10 //杨辉三角的最大阶数
int main(int argc, char const * argv[])
{
//定义一个二维数组
int arr[MAX][MAX]={0};
//定义变量接受用户输入的阶数
int N=0;
//输入阶数
printf("请输入杨辉三角的阶数:");
while(1)
{
scanf("%d",&N);
//对输入的数据进行判断
if(N<1 || N>MAX)
{
printf("输入有误,请重新输入:");
continue;
}
break;
}
//处理杨辉三角
for(int i=0;i<N;i++)
{
for(int j=0;j<=i;j++)
{
//对位置区域进行判断
if(j==0 || i==j)
{
arr[i][j]=1; //第一列和对角线元素都为1
}
else
{
arr[i][j]=arr[i-1][j]+arr[i-1][j-1];
}
}
}
//输出结果
printf("%d阶杨辉三角如下:\n",N);
for(int i=0;i<N;i++)
{
for(int j=0;j<=i;j++)
{
printf("%d\t",arr[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
字符数组
1>所谓字符数组,就是存放字符的数组
2>但是,字符数组主要解决字符串的问题,这是字符数组引入的目的
3>字符串:用双引号括起来的0个或多个字符称为字符串, 字符串默认有结束标识 '\0'
4>C语言中,没有专门用于处理字符串的变量,所有有关字符串的操作,都要基于字符数组来完成
一维字符数组
1>定义格式:char 数组名[常量];
1、单字符处理字符数组
全部初始化:char arr[5] = {'h', 'e', 'l', 'l', 'o'};
部分初始化:char arr[5] = {'h', 'e', 'l'}; //没有初始化的部分用 0('\0') 补齐
特殊初始化:char arr[] = {'h', 'e', 'l', 'l', 'o'}; //此时字符数组的长度为 5
2、字符串的形式初始化
整体初始化:char arr[10] = {"hello"}; //或者 char arr[6] = "hello";
特殊字符串初始化: char arr[] = "ni hao"; //此时,数组的实际长度7 但是,字符串实际长度为6
3> 字符数组的输入输出
1、单字符的输入输出:跟整形数组一致,需要使用循环找到任意一个元素对其进行操作
2、字符串的输入输出:需要将字符数组看成一个整体,不需要使用循环完成
3、对于字符串的输入输出,有两组函数可供使用
格式化输入输出:printf、scanf 使用的格式控制符为:%s
专门针对于字符串的输入输出函数:puts、gets
int puts(const char *s);
功能:向终端上打印一个字符串,会将字符串上的结束标识 '\0' 置换成 '\n'输出
参数:要输出的字符串起始地址(字符数组的名字)
返回值:成功调用返回成功输出的字符个数,失败返回 EOF(-1)并置位错误码
char *gets(char *s);
功能:从终端上获取一个字符串,放入到s指向的数组容器中
参数:要存放字符的字符数组名
返回值:就是数组的起始地址
示例:
#include <stdio.h>
int main(int argc, const char *argv[])
{
//定义一个字符数组并初始化
char arr[6] = {'h', 'e', 'l', 'l', 'o'}; //单字符初始化
char brr[6] = "hello"; //使用字符串初始化
//输出字符数组中的内容
printf("arr数组中的元素:");
for(int i=0; i<6; i++)
{
printf("%c\t", arr[i]);
}
puts(""); //输出一个换行
printf("brr数组中的元素:");
for(int i=0; brr[i]!='\0'; i++)
{
printf("%c\t", brr[i]);
}
puts(""); //输出一个换行
//字符串初始化
char crr[] = "I love China";
printf("sizeof(crr) = %ld\n", sizeof(crr)); //13
int len = 0; //记录字符串实际长度的变量
for(int i=0; crr[i]!='\0'; i++)
{
len++;
}
printf("len = %d\n", len);
/***************使用字符串的格式完成输入输出****************/
char drr[20] = "";
char err[20] = "";
printf("请输入两个字符串:");
scanf("%s%s", drr, err); //输入的两个字符串可以使用
//回车、空格、tab键隔开
getchar(); //吸收回车
printf("drr = %s, err = %s\n", drr, err);
//使用gets和puts完成字符串输入输出
printf("请输入一个字符串:");
gets(drr); //给drr重新赋值,允许输入空格
printf("drr = ");
puts(drr); //输出一个字符串,自动会换行
return 0;
}
运行结果:
4>由于对于字符数组的操作,都是直接使用的是数组名,而数组名又是第一个元素的地址,所以,针对于字符数组处理字符串的不同操作,需要使用不同的函数完成,例如字符串的拷贝、字符串比较、字符串求长度等等
1、求字符串实际长度函数
#include <string.h>
size_t strlen(const char *s);
功能:求给定字符串的实际长度,不包含结束标志 '\0'
参数:要求的字符串的起始地址
返回值:就是字符串实际长度
2、字符串的赋值:对于字符串的初始化可以使用等号完成,但是对于字符串的赋值,不允许使用等号完成
#include <string.h>
char *strcpy(char *dest, const char *src);
功能:将第二个字符串src中的内容连同结束标识'\0'一同拷贝进入第一个字符串dest中
参数1:要被赋值的字符数组名
参数2:要被拷贝的字符串起始地址
返回值:成功拷贝后 dest的起始地址
3、字符串的连接
#include <string.h>
char *strcat(char *dest, const char *src);
功能:将第二个字符串连接到第一个字符串后面,并将结果拷贝放到第一个数组中
参数1:目标数组
参数2:要被连接的数组
返回值:成功连接后,目标数组的起始地址
4、字符串的比较:在C语言中,不允许使用关系运算符来比较两个字符串,只能使用相关函数完成
#include <string.h>
int strcmp(const char *s1, const char *s2);
功能:比较给定的两个字符串的大小:逐个比较相同位置上的两个字符的ascii值,直到出现不相同的字符或者全部到'\0'结束
参数1:要比较的第一个字符串
参数2:要比较的第二个字符串
返回值:
>0:表示第一个字符串大
=0:表示两个字符串相等
<0:表示第一个字符串小
示例:
#include <stdio.h>
int main(int argc, const char *argv[])
{
//定义两个字符数组初始化字符串
char str1[20] = "hello world";
char str2[] = "I Love China";
//测试strlen
int len = strlen(str2); //求字符串2的实际长度
printf("len = %d\n", len); //12
int size = sizeof(str2); //求字符串所占字符数组的长度
printf("size = %d\n", size); //13
size = sizeof(str1); //求字符数组1的大小
printf("size = %d\n", size); //20
//比较两个字符串的大小
if(strcmp(str1, str2) >0)
{
printf("%s大\n", str1);
}
else if(strcmp(str1, str2) < 0)
{
printf("%s小\n", str1);
}
else
{
printf("一样大\n");
}
//完成两个字符串的赋值,将str2赋值给str1
strcpy(str1, str2); // str1 = str2
printf("拷贝后:str1 = %s, str2 = %s\n", str1, str2);
//完成两个字符串的连接, 将str2连接到str1后面
strcat(str1, str2);
printf("连接后:str1 = %s, str2 = %s\n", str1, str2);
return 0;
}
运行结果:
作业:
1、提示并输入一个字符串,统计该字符串中字母、数字、空格以及其他字符的个数
代码:
#include <stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{
char str[]="";
int zm = 0, shz = 0, spaces = 0, others = 0;
printf("请输入一个字符串:");
gets(str); //gets函数读取换行符之前(不包括换行符)的所有字符,
//并在这些字符后添加一个空字符(\0)
//当读取到空字符时表示读取完成
for (int i = 0; str[i]!='\0'; i++) {
if (str[i] == '\n') break; // 如果读取到换行符,结束循环
if (str[i]==32) {
spaces++; // 统计空格
} else if (str[i]>=97&& str[i]<=122 || str[i]>=65 && str[i]<=90) {
zm++; // 统计字母
} else if (str[i]>=48 && str[i]<=57) {
shz++; // 统计数字
} else {
others++; // 统计其他字符
}
}
printf("字母个数:%d\n", zm);
printf("数字个数:%d\n", shz);
printf("空格个数:%d\n", spaces);
printf("其他字符个数:%d\n", others);
return 0;
}
运行结果:
代码:
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[])
{
char str[]="";
int sum = 0, temp;
printf("请输入一个字符串: ");
gets(str);
for(int i = 0; i < strlen(str); i++) {
if(str[i] >= '0' && str[i] <= '9') {
temp = str[i] - '0';
sum += temp;
}
}
printf("数字的总和是: %d\n", sum);
return 0;
}
运行结果:
3、定义一个4*3的二维整形数组,完成对二维数组的输入、输出。并将该二维数组中每一行的最值放入到一个一维数组中,并对该一维数组进行升序排序后输出。
代码:
#include <stdio.h>
#define M 4 //二维数组的行数
#define N 3 //二维数组的列数
int main(int argc, char const * argv[])
{
//定义一个二维数组
int arr[M][N]={0};
//对数组进行输入输出,通过双重循环找到任意一个数据
for(int i=0;i<M;i++) ///外行
{
for(int j=0;j<N;j++) //内行
{
//在此处可以找到arr[i][j]
printf("请输入第%d行%d列的元素:",i+1,j+1);
scanf("%d",&arr[i][j]);
}
printf("\n");
}
//将上述数组进行输出
printf("数组元素分别是:\n");
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("%d\t",arr[i][j]);
}
printf("\n");
}
//将二维数组中的每一行的最值求出后,放入到一个一维数组中
int sum[M]={0};
for (int i = 0; i < M; i++) {
int max = arr[i][0];
for (int j = 1; j < N; j++) {
if (arr[i][j] > max) {
max = arr[i][j];
}
}
sum[i] = max;
}
printf("每一行的最值分别是:\n");
for(int i=0;i<M;i++)
{
printf("%d\t",sum[i]);
}
printf("\n");// 冒泡排序
for(int i=1;i<M;i++)
{
for(int j=0;j<M-i;j++)
{
if(sum[j]>sum[j+1])
{
//交换三部曲
int temp=sum[j];
sum[j]=sum[j+1];
sum[j+1]=temp;
}
}
}
printf("排序后的结果为:");
for(int i=0;i<M;i++)
{
printf("%d\t",sum[i]);
}
putchar(10);
return 0;
}
运行结果:
代码:
#include<stdio.h>
#define MAX 5
int main(int argc,char const *argv)
{
int arr[MAX] = {0} , brr[MAX]={0};
for(int i = 0;i<MAX;i++)
{
printf("请输入第一个数组的第%d个数:",i+1);
scanf("%d",&arr[i]);
}
for(int i = 0;i<MAX;i++)
{
printf("请输入第二个数组的第%d个数:",i+1);
scanf("%d",&brr[i]);
}
printf("这两个数组的交集是:");
for(int i = 0 ; i<MAX ; i++)
{
for(int j = 0 ; j<MAX ; j++)
{
if(arr[i] == brr[j])
{
printf("%d\t",arr[i]);
}
}
}
putchar(10);
return 0;
}
运行结果:
登录:将登录账号和密码跟注册的账号和密码进行匹配,如果相等,则登录成功,否则,登录失败
代码:
#include<stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{
char zhanghao[100]=""; //注册账号
char pwd[100]=""; //注册密码
char arr[100]=""; //登录账号
char brr[100]=""; //登录密码
int i=0,j=0;
printf("请注册您的账号:");
gets(zhanghao);
printf("请输入账号密码:");
gets(pwd);
printf("请登录您的账号:");
gets(arr);
printf("请登录您的密码:");
gets(brr);
if(strcmp(zhanghao,arr)==0&&strcmp(pwd,brr)==0)
{
printf("登录成功\n");
}
else
{
printf("登录失败\n");
}
return 0;
}
运行结果: