一、数组
数组可以连续存储多个同一类型的数据。
【1】定义
存储类型 数据类型 数组名[数组长度];
int arr[40]; //定义了一个能存40个整形数据的数组
【2】初始化和赋值
数组只能再定义的时候进行整体初始化,定义结束之后,不能给数组中元素整体赋值
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[3]; //能存3个整形数据的数组arr,数组中的元素是随机值
int arr1[4]={12,56,90,1}; //定义了一个整形数组arr1,能存4个整形数据,并完全初始化
int arr2[4]={12,6}; //定义了一个能存4个数据的整型数组,不完全初始化,未初始化的部分都是0
int arr3[4]={0}; //定义了一个整形数组能存4个整形数据,全部初始化为0
int arr4[] = {12,56,90};
//定义了一个整形数组arr4,没有指定长度,系统会根据初始化列标给数组分配空间
//arr4长度是3
int arr5[] = {}; //数组的长度为0
//arr={100}; error,数组只能在定义的时候,进行整体初始化
//访问数组中的元素,通过元素的下标
//数组中元素的下标从0开始
printf("arr1[0]=%d\n",arr1[0]); //12
printf("arr1[1]=%d\n",arr1[1]); //56
printf("arr1[2]=%d\n",arr1[2]); //90
printf("arr1[3]=%d\n",arr1[3]); //1
arr3[2]=100; //给arr3中下标为2的元素赋值为100
return 0;
}
【3】数组中元素的访问
通过下标访问数组中元素,元素的下标从0开始
数组中元素的最大下标=长度-1;
[ ]的两种用法:
- 在定义数组的时候,表示是一个数组
- 在访问数组中元素的时候,表示元素下标
练习:
1、定义一个整型数组,完成数组中元素的循环输入输出。
2、验证数组中元素的地址连续。
#include <stdio.h> #define N 5 int main(int argc, const char *argv[]) { int arr[N],i; //循环变量i需要从0开始 //终端输入 for(i=0;i<N;i++) { scanf("%d",&arr[i]); } //输出 for(i=0;i<N;i++) { printf("arr[%d]=%d\n",i,arr[i]); } for(i=0;i<N;i++) { printf("arr[%d]=%p\n",i,arr[i]); } return 0; }
【4】数组的大小和长度
int arr[4];
sizeof(arr); 求出的是数组所占内存空间的大小
sizeof(int) 长度
int len = sizeof(arr)/sizeof(int); 数组的长度,用数组的大小/单个元素的大小
数组的大小 = 单个元素的大小 * 长度
【5】数组的长度
可以使用变量定义数组的长度,但是不论变量如何修改,数组长度都不变
并且,使用变量定义数组长度时,数组不能初始化。
#include <stdio.h> int main(int argc, const char *argv[]) { int n = 9; int arr[n],i; //虽然使用变量n定义数组的长度,使用变量定义数组的长度定义时不能初始化 //但是arr仍然是一个定长数组. int len = sizeof(arr)/sizeof(int); //求数组长度 printf("数组的长度为%d\n",len); return 0; }
练习:
1、使用数组实现斐波那契的前10项
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[10]={1,1}; //定义了一个长度为10的整型数组,前两个元素为1,后面的元素都是0 int i,len=sizeof(arr)/sizeof(arr[0]); //求数组的长度 //斐波那契数列的赋值 for(i=2;i<len;i++) { arr[i]=arr[i-1]+arr[i-2]; } //输出 for(i=0;i<len;i++) { printf("arr[%d]=%d\n",i,arr[i]); } return 0; }
2、定义数组arr和brr,终端输入arr中的数据,把arr中偶数下标的元素乘2,赋给brr中对应的元素,把arr中奇数下标的元素加一,赋给brr中对应的元素。arr和brr长度为10
#include <stdio.h> #define LEN 10 int main(int argc, const char *argv[]) { int arr[LEN],brr[LEN],i; for(i=0;i<LEN;i++) { scanf("%d",&arr[i]); } printf("**********************\n"); //赋值 for(i=0;i<LEN;i++) { if(i%2==0) { brr[i]=arr[i]*2; } else { brr[i]=arr[i]+1; } } //打印 for(i=0;i<LEN;i++) { printf("%d\n",brr[i]); } return 0; }
3、有数组int arr[]={12,89,100,101,32,76,98};写一个程序,求出数组中元素的最大值及其下标。
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[]={12,89,100,101,32,76,98}; int len = sizeof(arr)/sizeof(arr[0]); //求数组长度 int i,max_index=0; //定义循环变量i和最大值下标 //假定最大值的下标是0 for(i=1;i<len;i++) //循环遍历数组中的每一个元素 { //通过最大值下标取到最大值,再进行比较 if(arr[i]>arr[max_index]) { //如果数组中元素,比假定的最大值还大,就更新最大值下标 max_index = i; } } printf("%d\n",i); //7 printf("最大值下标为%d\t最大值为%d\n",max_index,arr[max_index]); return 0; }
求数组中元素的最大值
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[]={301,89,100,101,32,76,200}; int len = sizeof(arr)/sizeof(arr[0]); //求数组长度 int max = arr[0]; //让假定的最大值,是数组中的数 int i; //由于max假定是数组中的第一个元素,所以第一个元素不需要再参与比较了 for(i=1;i<len;i++) { //如果数组中元素比假定的最大值还大,就更新最大值 if(arr[i]>max) { max = arr[i]; } } printf("%d\n",max); return 0; }
4、编写程序,实现数组中元素的逆置。
1、
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[]={301,89,100,101,32,76,200}; int len = sizeof(arr)/sizeof(arr[0]),i,temp; //循环逆置 for(i=0;i<len/2;i++) { //三杯水交换 temp = arr[i]; arr[i]=arr[len-1-i]; arr[len-1-i]=temp; } //打印输出 for(i=0;i<len;i++) { printf("%d\n",arr[i]); } return 0; }
2、
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[]={301,89,100,101,32,76,200}; int len = sizeof(arr)/sizeof(arr[0]); int i,j,temp; //两个下标,分别指向第一个元素和最后一个元素 //指后面的每次向前移动,指前面的每次向后移动 for(i=0,j=len-1;j>i;i++,j--) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //打印输出 for(i=0;i<len;i++) { printf("%d\n",arr[i]); } return 0; }
【6】冒泡排序
相邻的两个元素之间两两比较并且交换,每一次都会比较一个最大的数放在后面。
//升序
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[]={301,89,100,101,32,76,200};
int len=sizeof(arr)/sizeof(arr[0]),temp,i,j;
//外层循环控制排序趟数
for(i=1;i<len;i++)
{
//控制的是比较的次数
for(j=0;j<len-i;j++) //for(j=0;j<=len-1-i;j++)
{
if(arr[j]>arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//打印输出
for(i=0;i<len;i++)
{
printf("%d\n",arr[i]);
}
return 0;
}
练习:
1、实现数组元素的降序冒泡排序
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[]={301,89,100,101,32,76,200}; int len=sizeof(arr)/sizeof(arr[0]),temp,i,j; //外层循环控制排序趟数 for(i=1;i<len;i++) { //控制的是比较的次数 for(j=0;j<len-i;j++) //for(j=0;j<=len-1-i;j++) { if(arr[j]<arr[j+1]) //决定了排序的结果是升序还是降序 { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } //打印输出 for(i=0;i<len;i++) { printf("%d\n",arr[i]); } return 0; }
【7】选择排序
每次从待排序序列中,选出最大/最小的数,和待排序序列中的第一个数交换
选择排序,找到下标再交换
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[]={89,100,101,32,76}; int len = sizeof(arr)/sizeof(arr[0]); int min_index,i,j,temp; //控制排序的次数 for(i=1;i<len;i++) { min_index = i-1; //假定每次待排序序列中最小元素是待排序序列中的第一个元素 //选择排序找元素下标,根据下标交换数组中元素 for(j=i;j<len;j++) //让j从待排序序列中的第二个元素开始遍历 //因为min_index已经是待排序序列中的第一个元素 { if(arr[min_index]>arr[j]) { min_index = j; //找最小值的下标 } } //判断找到的最小值是否是第一个元素 if(min_index!=i-1) { //三杯水交换 temp = arr[i-1]; arr[i-1] = arr[min_index]; arr[min_index] = temp; } } //打印输出 for(i=0;i<len;i++) { printf("%d\n",arr[i]); } return 0; }
二、一维字符数组
常用于存储字符串
【1】定义
例如:char arr[4]; //定义了一个能存4个字符类型数据的数组arr
【2】字符数组与字符串相结合
#include <stdio.h>
int main(int argc, const char *argv[])
{
char arr[4]; //定义了一个能存4个char类型数据的数组arr
char arr1[4] = {'a','b','c','d'}; //定义了一个能存4个char类型数据的数组arr1并完全初始化
char arr2[4] = {'a','b'}; //定义了一个能存4个char类型数据的数组arr
//不完全初始化,未初始化的部分是'\0'
char str[] = "hello"; //str的大小为6,字符串结尾有一个'\0'
//'h','e','l','l','o','\0'
printf("%s\n",str);
//使用字符串初始化字符数组
char str1[7] = {'\0'};
str[3] = 'i'; //给str中下标为3的元素赋值
printf("%s\n",str);
//循环遍历字符数组中的每个元素,完成输入输出
return 0;
}
【3】字符串的输入输出函数
i)gets()
scanf 不能获取带空格的字符串
gets 可以获取带空格的字符串
函数原型:char *gets(char *s);
gets:功能终端输入带空格的字符串
参数:地址
*使用gets会报警告,这是友好的警告,gets不会检查数组越界,不用管这个警告
ii)puts()
函数原型:int puts(const char *s);
功能:输出字符串
参数:字符串的地址
#include <stdio.h> int main(int argc, const char *argv[]) { char str[] = "hello"; printf("%p\n",str); //数组中首元素的地址 printf("%p\n",&str[0]); /******************************************/ puts(str); printf("%s\n",str); //%s要一个地址,从该地址开始输出,直到'\0'停止 str[3] = '\0'; puts(str); /******************************************/ gets(str); //可以获取带空格的字符串 puts(str); //终端输出字符串 printf("%c",'\0'); return 0; }
【4】字符串函数族的函数
#include <string.h>
i)strlen
函数原型: size_t strlen(const char *s);
参数是地址
功能:求字符串实际的长度
ii)strcpy
函数原型:char *strcpy(char *dest, const char *src);
dest是目标字符串的地址,src是源字符串的地址
dest也要足够大,容纳src的结果
功能:把src中的内容拷贝到dest中
iii)strcat
函数原型:char *strcat(char *dest, const char *src);
功能:把src拼接到dest后面
要求dest足够大
参数:目标字符串和源字符串的地址
#include <stdio.h> #include <string.h> int main(int argc, const char *argv[]) { char str[20] = "hello "; int len=0,i=0; //如果没有走到'\0'就计数,长度++ /* while(str[i]) { i++; len++; } printf("%d\n",len);*/ char str1[10]="world"; strcat(str,str1); puts(str); //hello world return 0 }
练习:
1、自己实现strlen的功能。
#include <stdio.h> int main(int argc, const char *argv[]) { char str[20] = "hello"; int len=0,i=0; //如果没有走到'\0'就计数,长度++ while(str[i]) { i++; len++; } printf("%d\n",len); return 0; }
作业:
1.整理思维导图
2.冒泡排序,从后往前交换
3.自己实现strcpy和strcat函数功能
4.认真复习课上内容,包括两数交换