c复习day04

数组

  • 定义:把若干个相同类型的变量,存放在一块连续的内存中
  • 其中的每一个变量叫做元素,也是数组的最小单位
  • 数组中的元素从0开始,其中每一个元素都是一个变量
  • 构造类型:将基本类型构建成为的类型
    • 数组:相同类型的数据存放在一个集合中,这种的构造类型数组
    • 结构体:将不同类型的数据放在一个集合中

定义数组

1
2
3
4
5
6
#include <stdio.h>
int main(void)
{
int num[10];
return 0;
}
  • 数组中的元素个数由[]中的数值决定
  • 每个元素的类型由数组前面的类型觉得
  • 定义数组的时候[]中的值,只能是常量
  • 使用时候,[]中的值可以是变量
  • 数值数组不能整体操作 ,如果我们想要全部打印出来可以使用循环
  • 如果数组中的元素没有初始化,是随机值

数组的初始化

1
2
3
4
5
6
#include <stdio.h>
int main(void)
{
int num[10] = {1,3,4,5,6,7,7,8,9,3};
int mun[4] = {1,3};
}
  • 如果数组只初始化部分的元素,其他的元素初始化为0
1
2
3
int num[3] = {0}; // 初始化所有的元素为0
int num[];//这样定义是错误的,没有告诉编译器有几个元素
int num[];//如果[] 中没有数据,这个数组的元素的个数,由元素的个数决定

数组的大小

  • 获取数组中元素的个数
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main(void)
{
int num[10];
printf("%d",sizeof(num));
printf("%d",sizeof(num)/sizeof(num[0]));
//通过使用处于一个元素的大小,可以求出数组中的元素的个数
return 0

}
  • 这样我们在for循环中就可以直接写数组的长度来作为,循环的结束条件

数据在内存中的地址

数据在内存中如何存储
  • 启动一个程序系统会给这个程序分配一快内存空间,内存的最小单位是一字节
  • 内存中的每一个字节都会由一个编号,这个标号我们把他叫做内存地址
  • 比如我们定义一个char类型的变量就会占用一个字节,会由一个定义
  • 如果我们定义一个int 类型的变量,会占用4个字节,数据在内存中的地址是他的起始地址

数组的地址和数组名

  • 列子:在内存中我们定义一个int数组,其中包含5个元素:int a[5];
  • 数组名a代表数组,也代表第0个元素的地址
  • 所以说数组名是一个常量,是一个地址,不能被赋值
  • &a : 整个数组的地址
  • 在数值上 取地址&a[0],a,&a 相等
    • &a[0]+1 取地址 a + 1 元素的地址加1 跨过一个元素
    • a + 1 元素的地址加1 跨过一个元素
    • &a + 1: 整个数组的地址加1 ,跨过整个数组
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main()
{
int a[5];
printf("%u\n",&a[0]);
printf("%u\n",a);
printf("%u\b",&a);
printf("--------\n");
printf("%u\n",&a[0]+1);
printf("%u\n",a+1);
printf("%u\b",&a+1);
return 0;
}

数组练习求数组最大值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 #include <stdio.h>
int main()
{
int a[10] = {2,34,5,6,67,7,78,56,7,8};
int max = a[0];
for(int i= 0;i < 10;i++)
{
if a[i] > max;
{
max = a[i];
}
}
printf("%d\n",max);
return 0;
}

数组逆序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int temp = 0;
int i = 0;
int j = sizeof(a) / sizeof(a[0]) - 1;
while (i < j)
{
//前后交换
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
for(i = 0;i < 10;i++)
{
printf("%d ",a[i]);
}
return 0;
}

数组排序-冒泡排序的原理

  • 相邻两个元素比较,前面的比后面的大,两元素交换
  • 例如我们有 :4,76,8,9,3
  • 第一轮比较4次:4,8,9,3,76
  • 第二轮比较3次:4,8,3,9,76
  • 第三轮比较2次:4,3,8,9,76
  • 第四轮比较1次:3,4,8,9,76
  • 一共有n个元素,一共比较n-1轮,每比较一轮,下一轮少比较一次
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include <stdio.h>
    int main()
    {
    int a[5] = {2,5,7,3,-2};
    int n = sizeof(a) / sizeof(a[0]);

    for (int i = 0; i < n - 1; i++)
    {
    //因为每次比较的次数都要减一,刚好每次i+1
    for (int j = 0; j < n - 1 - i ; j++)
    {
    if(a[j] > a[j + 1])
    {
    int tmp = a[j + 1];
    a[j + 1] = a[j];
    a[j] = tmp;

    }
    }
    }
    for (i = 0; i < n;i++)
    {
    printf("%d ",a[i]);
    }

    return 0;
    }

二维数组

  • int a[2] [4]定义了一个二维数组,二位数组中有两个一维数组,每个一维数组有四个元素
a[0] [0] a[0] [1] a[0] [2] a[0] [3]
a[1] a[0] a[1] a[1] a[1] a[2] a[1] a[3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int [3][4];

for (int i = 0 ; i < 3 ; i++)
{
for (int j = 0;j < 4;j++)
{
printf("%d ",a[i][j]);
}
printf("\n");
}
}
  • 如果我们需要输出二维数组,需要使用双重循环

二位数组的初始化

1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
int a[3][4] = {{1,3,5,6},{1,3,5,6},{3,46,78,9}};
int a[3][4] = {1,3,5,6,1,3,5,6,3,46,78,9};
int a[3][4] = {1,3,5};

}
  • 给二位数组的部分元素初始化,其他元素为0

  • 定义数组中的列必须要写,可以省略行的下标

求二位数组的行和列

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
int a[3][4];
int n = sizeof(a) / sizeof(a[0][0]);//求元素的个数
int line = sizeof(a) / sizeof(a[0]);//行数 :二位数组总大小除以一行的大小
int clu = sizeof(a[0]) / sizeof(a[0][0]);//列:行大小除以一个的大小
printf("%d\n",n);
printf("%d\n",line);
printf("%d\n",clu)
return 0;
}

二位数组的行数需要使用总大小除以行的大小

二位数组的列数需要使用行的大小除以一个元素的大小即可

二位数组的数组名称

  • int a[2] [3]
  • a[0] [0] :第零行第零个元素

  • &a[0] [0]:第零行第零个元素的地址 = 01

  • a[0] :代表第0行一维数组的数组名,a[0] = &a[0] [0] = 01

  • &a[0] 代表第0行的地址 01

  • a:二位数组数组名,代表二位数组,代表着首行的地址&a[0]

  • &a:二位数组的地址

关于各项加一其代表的意义
  • &a[0] [0] +1 元素地址加1,跨过一个元素

  • a[0] + 1 元素地址加1,跨过一个元素

  • &a[0] + 1 行地址加1,跨过一行

  • a + 1 行地址加1 ,跨过一行

  • &a +1 二位数组地址加1,跨过整个数组

    代码的验证
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>
    int main()
    {
    int a[3][4];
    printf("%u\n",&a[0][0]);
    printf("%u\n",a[0]);
    printf("%u\n",&a[0]);
    printf("%u\n",a);
    printf("%u\n",&a);

    printf("--------\n");

    printf("%u\n",&a[0][0]+1);
    printf("%u\n",a[0]+1);
    printf("%u\n",&a[0]+1);
    printf("%u\n",a+1);
    printf("%u\n",&a+1);


    return 0;

二维数组的练习

1
float a[5] [3] = {{80,75,54},{32,45,78},{34,54,78},{23,43,6},{34,56,76}};
  • 求各科成绩的平均分

  • 统计各科不及格的人数

代码演示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
int main()
{
float a[3][3] = {{12,34,54},{13,54,65},{25,65,76}};
float avg[3] = {0};
int num[3] = {0};
float sum;

for ( int i = 0; i < 3; i++)
{
sum = 0.0;
for (int j = 0; j < 3; j++)
{
sum += a[j][i];
if (a[j][i] < 60)
{
num[i]++;
}
}
avg[i] = sum/3;
}
for (int i = 0; i < 3; i++)
{
printf("%.2f\n",avg[i]);
printf("%d\n",num[i]);
}

return 0;

}

多维数组

  • int a [2] [3] [4]:定义了一个三维数组,有两个二维数组,每个二维数组有三个一维数组,每个一维数组有四个元素
  • 关于初始化和打印和二维数组类似

字符数组

  • 每个元素是char类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{
char a[5] = {'a','b','c'};
char b[5] = "abcd";//定义了一个字符数组后面含有\0
char c[] = "world";//数组中含有6个元素
char d[100] = "abcd";//定义了一个字符数组,有一百个元素
char e[100] = "\0";//将数组的第0个元素是\0,其他元素就是\0
char f[100] = {0};//将一个字符数组清零
for (int i = 0; i < sizeof(a) / sizeof(a[0]);i++)
{
printf("%d\n",a[i]);
}
return 0;
}
  • 本质上里面存储的是accil码值

  • 初始化部分元素其他元素为0

  • 我们是用%s来打印字符串

  • 如果我们使用%s来打印字符数组,我们需要在后面加上\0

  • 如果没有\0就是普通的字符数组,含有\0也叫字符串

  • 字符串就是字符数组中有\0字符的数组

  • 因为有\0的字符数组 操作起来方便

字符数组的初始化

1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
char a[] = {'a','b','c'};
printf("%d\n",sizeof(a));
printf("%s\n",a);
return 0;
}
  • 如上的代码因为没有\0所以会出现乱码的情况

  • 所以我门更加常用的的是使用双引号来直接赋值字符串

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
char a[] = {'a','b',0,'c'};
char b[] = {'a','b','0','c'};
char c[] = {'a','b','\0','c'};

printf("%s\n",a);
printf("%s\n",b); //乱码
printf("%s\n",c);
return 0;
}
  • 没有\0就会一直向后面打印,出现乱码

scanf输入字符串

  • 使用%c只能读取一个字符

  • 所以如果我梦想要实现输入字符串,就需要先定义一个数组

  • 因此我们能就需要是用%s来获取一个字符串,\n后结束

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
//数组清零
char num[100] = "";
//从键盘获取一个字符串,遇到\n后结束
scanf("%s",num);
//%s要的是打印字符数组的首元素地址
printf("%s",num);
return 0;
}
  • 需要注意的一点:遇到\n后会结束,遇到空格也会结束

  • 如果我们的数组大小小于输入的字符,机会造成内存污染

gets

  • gets是一个库函数
1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
char num[134] = "";
gets(num);//参数是存放读取字符串的地址
printf("%s",num);
return 0;
}
  • gets遇到\n会结束但是遇到空格不会结束

  • gets也会造成内存污染

fgets

  • 库函数:从键盘读取一个字符串

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdio.h>
    #include <string.h>
    int main()
    {
    char num[134] = "";
    fgets(num,sizeof(num),stdin);
    int x = strlen(num);
    num[x-1] = 0;
    int i = 0;
    while (num[i] != '\0')
    {
    i++;
    }

    printf("%s\n",num);
    return 0;
    }
  • 最大可以读取sizeof(num) -1 个元素

  • fgets会把回车读取,如果我门不想让函数输出那个回车我们可以使用strlen来获取字符数组的长度,将最后一个元素改为0即可

  • 相对于scanf和gets 更加的安全,但是会读取回车

  • 我们不仅可以使用strlen来获取最后一个元素来改为0,我们也可以使用循环来找到\0的位置,将前面的回车改为\0也可以达到相同的结果

strlen

  • 库函数:求字符数组的字符个数
  • 参数是要的是字符数组的首元素的地址

字符数组的输出

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main()
{
char arr[1024] = "helloworld";
printf("%s\n",arr);
puts(arr);
fputs(arr,stdout);

return 0;
}
  • fputs:第一个参数是数组的首元素地址,stdout是标准输出(屏幕)

字符串的追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>

int main()
{
char str1[128] = "hello";
char str2[128] = "geek";
int i = strlen(str1);
int j = 0;
while (str2[j] != 0)
{
str1[i] = str2[j];
i++;
j++;
}
printf("%s\n",str1);
return 0;
}
  • 以上的代码实现了将str2追加到str1的后面

猜数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
//设置随机数种子
//获得随机数
//获得当前时间
int t = time(NULL);
srand(t);
int a = rand();
printf("%d\n",a);
return 0;
}

课后练习

字符串大小写转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <string.h>
int main()
{
char buf[64] = "";
fgets(buf,sizeof(buf),stdin);

for (int i = 0; i < strlen(buf); i++)
{
if (buf[i] >= 'a' && buf[i] <= 'z')
{
buf[i] -= 32;

}
else if (buf[i] >= 'A' && buf[i] <= 'Z')
{
buf[i] += 32;
}
printf("%c",buf[i]);
}
return 0;

}
字符串比较
1

你的支持是我最大的动力!
0%