---
title: C语言学习-2
published: 2022-11-22
description: ''
image: 'https://t.alcy.cc/fj'
tags: [C语言, 笔记]
category: '笔记'
draft: false 
lang: ''
---

<meta name="referrer" content="no-referrer"/>

**学习目标：**

- 1、一维数组、二维数组、字符数组的定义、引用、初始化
- 2、利用数组批量处理数据。

## 一、数组的概念

1.数组是一组有序数据的集合

2.数组中每一个元素都属于同一个数据类型

## 二、一维数组

### 1、定义

- 类型关键字数组名[常量表达式]
  - 类型关键字：int、float等
  - 数组名：遵循标识符命名规则
    - 不允许使用C语言中的关键字
    - 由字母、数字、下划线组成，且首字母必须为字母或下划线，不能为数字
  - []不是【】
  - 常量表达式
    - inta[5]
    - inta[3+2]
    - inta[N]//N是提前声明的符号常量

### 2、引用

数组名[下标]

例：a[4]//引用数组中第五个元素

### 3、初始化

- 在定义数组时，对数组元素赋初值
- int a[6]={1,2,3,4,5,6};
- 可只给一部分数组元素赋初值，未赋值部分默认为0
- int a[6]={1,2,3};
- 未赋初值的数组，各元素值不确定（取决于不同的编译器）

![1.jpg](https://s1.vika.cn/space/2022/12/01/1f523d8a397748c7ae677d10ba23bf32)
![2.jpg](https://s1.vika.cn/space/2022/12/01/eec040da2c894d8282429cfddaccdb6d)

- 初始化的数据个数确定时可以省略数组长度。
  - 例：inta[]={1,2,3};
- 数组中全部元素初始化为0。
  - 例：inta[6]={0};

### 4、一维数组使用示例//输出斐波那契数列前30个数

```c
#include <stdio.h>
int main()
{
    int f[30]={1,1}
    int i;
    printf("%d\t%d\t",f[0],f[1]);
    for(i=2;i<30;i++)
        {
            if(i%5==0)
                printf("\n");
            f[i]=f[i-1]+f[i-2];
            printf("%d\t",f[i]);
        }
    return 0;
}
```

### 5、排序算法

参考：[https://www.cnblogs.com/onepixel/p/7674659.html ](https://www.cnblogs.com/onepixel/p/7674659.html)

交换排序：所谓交换，就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置，交换排序的特点是：将键值较大的记录向序列的尾部移动，键值较小的记录向序列的前部移动。

```c
for(j=0;j<5;j++)
{
    for(i=j+1;i<6;i++)
    {
        if(a[j]>a[i])
        {t=a[j];a[j]=a[i];a[i]=t;}
        }
    }
}
```

#### 选择排序

- 原理：假设长度为n的数组arr，要按照从小到大排序，那么先从n个数字中找到最小值min1，如果最小值min1的位置不在数组的最左端(也就是min1不等于arr[0])，则将最小值min1和arr[0]交换，接着在剩下的n-1个数字中找到最小值min2，如果最小值min2不等于arr[1]，则交换这两个数字，依次类推，直到数组arr有序排列。
- 步骤：
  1.首先在未排序序列中找到最小（大）元素，存放到排序序列的起始位置。
  2.再从剩余未排序元素中继续寻找最小（大）元素，然后放到已排序序列的末尾。
  3.重复第二步，直到所有元素均排序完毕。

```c
for(j=0;j<5;j++)
{
    for(k=j;i=j+1;i<6;i++)
        if(a[k]>a[i])
            k=i;
    if(k!=j)
        {t=a[k],a[k]=a[j];a[j]=t}
}
```

#### 冒泡排序：

- 原理：假设长度为n的数组arr，要按照从小到大排序。则冒泡排序的具体过程可以描述为：首先从数组的第一个元素开始到数组最后一个元素为止，对数组中相邻的两个元素进行比较，如果位于数组左端的元素大于数组右端的元素，则交换这两个元素在数组中的位置。这样操作后数组最右端的元素即为该数组中所有元素的最大值。接着对该数组除最右端的n-1个元素进行同样的操作，再接着对剩下的n-2个元素做同样的操作，直到整个数组有序排列。
- 步骤：
  1、比较相邻的元素。如果第一个比第二个大，就交换他们两个。
  2、对每一对相邻元素做同样的工作，从开始第一对到结尾的最后一对。在这一点，最后的元
  素应该会是最大的数。
  3、针对所有的元素重复以上的步骤，除了最后一个。
  4、持续每次对越来越少的元素重复上面的步骤，直到没有任何一对数字需要比较。

```
for(j=0;j<5;j++)
    for(i=0;i<5-j;i++)
        if(a[i]>a[i+1])
        {......}
```

## 三、二维数组

### 1、定义

note blue modern
类型关键字 数组名[常量表达式1][常量表达式2]
endnote

例：

```c
int a[3][4];
float b[5][10];
```

### 2、引用

note blue modern
数组名[下标1][下标2]
endnote

例：

```
a[0][0]     a[0][1]     a[0][2]     a[0][3]
a[1][0]     a[1][1]     a[1][2]     a[1][3]
a[2][0]     a[2][1]     a[2][2]     a[2][3]
```

### 3、初始化

#### 1、分行初始化

```c
int a[2][3]={{1,2,3},{4,5,6}}
```

#### 2、按存放数据整体初始化

```c
int a[3][2]={1,2,3,4,5,6}
```

#### 3、部分元素初始化

```c
int a[3][3]={{1},{},{4,5,6}}
```

#### 4、省略第一维初始化

```c
int a[][3]={{1},{},{4,5,6}}
```

### 4、输入输出

#### 1、输入

```c
for(i=0;i<3;i++)
    for(j=0,j<4;j++)
        scanf("%d",&a[i][j]);
```

#### 2、输出

```c
for(i=0;i<3;i++)
{
	for(j=0,j<4;j++)
    	printf("%d",a[i][j]);
	printf("\n");
}
```

## 四、字符数组

**1、C语言中没有表示字符串的类型，也没有字符串变量，字符串用字符数组来存放。**
**2、字符型数据以字符的ASCII码存放在存储单元中，一般占一个字节。**

### 1、定义

```c
char c[10],a[5];
```

### 2、初始化

- 字符常量初始化

  ```c
  char c[6]={'H','a','p','p','y','!'};             //sizeof(c)=6
  char c[]={'H','a','p','p','y','!'};              //提供初值个数与定义数组长度相同，可省略长度
  char c[]={'H','a','p','p','y','!','\0'};           //sizeof(c)=7
  ```

- 字符串常量初始化

  ```c
  char c[]={"Happy!"};             //sizeof(c)=7因为字符串末尾自动加一个'\0'
  char c[]="Happy";
  
  //等同于charc[]={'H','a','p','p','y','!','\0'};
  //不同于charc[]={'H','a','p','p','y','!'};
  ```

- 关于’\0’

note blue modern
C系统在用字符数组存储字符串常量时，会自动在末尾加一个’\0’作为结束符

字符数组并不要求它的最后一个字符为’\0‘，因此charc[6]={‘H’,’a’,’p’,’p’,’y’,’!’};完全合法

由于系统在处理在字符串常量时会自动加’\0’，为了一致及方便，通常处理时，人为的也加上’\0’
endnote

### 3、引用

- 单个元素的引用

note blue modern
允许引用单个字符元素，输入或输出一个字符。
endnote

```c
char c[7]= "happy!";
scanf("%c",&c[2]);               // 对c[2]元素赋一个字符
printf("%c",c[3]);               // 输出c[3]元素p
```

note blue modern
以字符串形式进行输入输出
endnote

```c
char c[7];
scanf("%s",c);              //注意此处不加&因为在C语言中，数组名代表第一个数组元素的地址
printf("%s",c);             //输出该字符串
printf("%o",c);             //八进制形式输出数组c的起始地址，即第一个数组元素的地址
```

note blue modern
如果利用一个scanf函数输入多个字符串，应在输入时，以空格隔开
endnote

```c
char a[5],b[5],c[5];
scanf("%s%s%s",a,b,c);              // 输入How are you分别将三个单词赋给a,b,c三个数组，注意：
// 输入格式控制中间没有空格
printf("%s%s%s",a,b,c);             // 输出How are you
```

### 4、使用字符串处理函数

- put(字符数组)
  将一个字符串输出到终端
  作用等效于printf("%s",c);也可以输出转义字符
  ![3.jpg](https://s1.vika.cn/space/2022/12/01/1aede231c9b74806b62f3f93416083af)
- gets(字符数组)
  从终端输入一个字符串到字符数组，并且得到一个函数值，该函数值为字符数组的起始地址。
  相比于scanf("%s",c);可以返回数组的地址值

![4.jpg](https://s1.vika.cn/space/2022/12/01/4fee6e5fd444452a8746f3b3725475b3)

- puts与gets函数都仅仅只能处理一个字符串
- strcat(字符数组1,字符数组2)
  把字符串2接到字符串1后面，结果放到字符数组1中，函数调用后得到的函数值为字符数组1的地址

note red modern
注：字符数组1的长度必须足够大，以便容纳连接后的新字符串。
字符数组定义及初始化时，长度不能省略。
endnote

- strcpy(字符数组1,字符串2)
  将字符串2复制到字符数组1中去

note red modern
注：字符数组1的长度不小于字符串2的长度；
字符数组1必须写成数组名形式，字符串2可以是字符数组名，也可以是字符串常量
endnote

- **strncpy(str1,str2,2)**

将str2中最前面的两个字符复制到str1中

- **strcmp(字符串1,字符串2)**

比较字符串1和字符串2

若相等，函数值为0；

若字符串1>字符串2，函数值为一个正整数；

若字符串1<字符串2，函数值为一个负整数。

- **strlen(字符数组)**

测试字符串实际长度

- **strlwr(字符串)**

将字符串中大写字母换成小写字母

- **strupr(字符串)**

将字符串中的小写字母换成大写字母