一.一维数组
一维数组的定义与初始化
在C语言中,一维数组的定义和初始化可以通过以下方式进行:
-
在定义数组的同时进行初始化:
-
int arr[5] = {1, 2, 3, 4, 5}; // 定义一个整型数组,并初始化5个元素
只定义数组,稍后单独初始化:
-
int arr[5]; // 定义一个整型数组,未初始化 arr[0] = 1; // 初始化第一个元素 arr[1] = 2; // 初始化第二个元素 // ...可以逐个初始化其他元素
使用指定值初始化数组:
-
int arr[5] = {0}; // 所有元素初始化为0
部分初始化,剩余元素自动填充为0:
-
int arr[5] = {1, 2}; // 前两个元素初始化为1和2,其余自动初始化为0
如果数组大小未知,可以通过初始化列表的元素个数来推断数组大小:
-
int arr[] = {1, 2, 3, 4, 5}; // 数组大小为5
在C语言中,数组的大小必须在编译时确定,且数组索引是从0开始到数组长度减1。访问未初始化的数组元素会导致未定义行为,而访问超出数组界限的元素也会导致未定义行为。
一维数组元素的引用
在C语言中,一维数组的引用主要通过数组名和下标来实现。
数组元素的基本概念
数组元素是组成数组的基本单元,其标识方法为数组名后跟一个下标。下标表示了元素在数组中的顺序号。数组元素的一般形式为:数组名[下标],其中下标只能为整型常量或整型表达式。如果下标为小数,C编译将自动取整。
引用一维数组的方法
在C语言中,只能逐个地使用数组下标变量,而不能一次引用整个数组。例如,输出有10个元素的数组必须使用循环语句逐个输出各下标变量:
for(i=0; i<10; i++) printf("%d", a[i]);
而不能使用一个语句输出整个数组。
示例代码
以下是一个简单的示例代码,演示如何定义和引用一维数组:
#include <stdio.h>
int main() {
int i, a[10]; // 正确声明一个长度为10的整数数组a
for(i = 0; i < 10; i++) { // 注意循环条件应该是i < 10,而不是i <= 9,虽然在这个特定情况下两者效果相同
a[i] = i; // 将数组的每个元素初始化为其索引值
}
for(i = 9; i >= 0; i--) {
printf("%d\n", a[i]); // 逆序输出数组中的每个元素
}
return 0;
}
一维数组作为两组参数
在C语言中,一维数组可以用作两组参数:数组名和数组首地址。
一维数组的定义和初始化
在C语言中,一维数组的定义方式如下:
数组类型 数组名[常量表达式];
例如:
int arr;
char arr2:ml-citation{ref="1" data="citationList"};
float arr3:ml-citation{ref="2" data="citationList"};
这里的常量表达式
表示数组的长度,即数组中元素的个数。
一维数组用作函数参数
在C语言中,一维数组用作函数参数时,实际上传递的是数组元素的首地址。函数可以接受数组名作为参数,也可以接受指向数组首元素的指针。例如:
void function(int arr[], int len);
void function(int *arr, int len);
这两种形式在编译时是等价的,因为函数会通过指针访问数组元素。函数内部不会检查数组的实际长度,因此调用者需要确保传递正确的长度参数。
一维数组的内存分配和访问
一维数组在内存中是连续存储的,数组的第一个元素的地址是&arr
,第二个元素的地址是&arr:ml-citation{ref="5" data="citationList"}
,以此类推。数组的元素可以通过下标直接访问,下标从0开始计数。例如:
int arr:ml-citation{ref="1" data="citationList"} = {1, 2, 3, 4, 5};
printf("%d\n", arr:ml-citation{ref="6" data="citationList"}); // 输出3
这里arr:ml-citation{ref="6" data="citationList"}
表示访问数组中的第三个元素,其值为3。
二.一维数组的应用
数据元素的复制与选择
#include <stdio.h>
// 函数原型声明
void copy_elements(int *dest, int *src, int n);
void select_elements(int *arr, int n, int flag);
int main() {
int arr[5] = {1, 2, 3, 4, 5}; // 初始化一维数组
int copy[5]; // 用于复制元素的目标数组
// 复制数组元素
copy_elements(copy, arr, 5);
// 根据条件选择数组元素
select_elements(arr, 5, 1); // 假设flag为1,选择所有元素
// 打印结果
printf("原数组: ");
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n复制后数组: ");
for (int i = 0; i < 5; i++) {
printf("%d ", copy[i]);
}
printf("\n");
return 0;
}
// 实现数组元素的复制
void copy_elements(int *dest, int *src, int n) {
for (int i = 0; i < n; i++) {
dest[i] = src[i];
}
}
// 实现根据条件选择数组元素
// 这里假设flag为1时选择所有元素,未实现具体条件选择
void select_elements(int *arr, int n, int flag) {
// 此处省略具体的选择逻辑
}
数据元素的移动
#include <stdio.h>
void move_element(int arr[], int n, int pos_from, int pos_to) {
int temp = arr[pos_from]; // 保存要移动的元素
// 如果目标位置大于源位置,先向后移动后续元素
if (pos_to > pos_from) {
for (int i = pos_from; i < pos_to; i++) {
arr[i] = arr[i + 1];
}
} else { // 如果目标位置小于源位置,先向前移动后续元素
for (int i = pos_from; i > pos_to; i--) {
arr[i] = arr[i - 1];
}
}
// 将元素移动到新位置
arr[pos_to] = temp;
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
// 移动数组中的数据元素,例如将元素3从位置2移动到位置4
move_element(arr, n, 2, 4);
// 打印移动后的数组
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
在这个例子中,move_element
函数接受四个参数:数组 arr
,数组的长度 n
,要移动的数据元素的原始位置 pos_from
,以及要将元素移动到的新位置 pos_to
。函数内部通过循环将元素移动到正确的位置。最后,在 main
函数中调用 move_element
函数,并打印出移动后的数组,以验证结果。
数据元素的查找与统计
在C语言中,我们可以使用不同的方法来查找和统计数组中的元素。以下是一些常见的方法:
-
线性搜索:这是最简单和最基本的方法。我们只是遍历数组,并检查每个元素是否是我们正在寻找的元素。
-
int linear_search(int arr[], int n, int x) { int i; for (i = 0; i < n; i++) if (arr[i] == x) return i; return -1; }
-
二分搜索:这种方法仅适用于已排序的数组。我们取数组的中间元素,如果它等于我们正在寻找的元素,我们完成。如果不是,我们根据中间元素将数组一分为二,然后在左半边或右半边继续进行二分搜索。
-
int binary_search(int arr[], int low, int high, int x) { while (low <= high) { int mid = low + (high - low) / 2; if (arr[mid] == x) return mid; if (arr[mid] > x) high = mid - 1; else low = mid + 1; } return -1; }
统计数组中的元素:我们只是遍历数组,并计算特定元素的出现次数。
-
int count_element(int arr[], int n, int x) { int count = 0; for (int i = 0; i < n; i++) if (arr[i] == x) count++; return count; }
数据元素的修改、删除与插入
在C语言中,数组是一种常用的数据结构,它是固定大小的,一旦定义,你不能在数组的中间修改、删除或插入元素。但是,你可以通过创建新的数组来实现修改、删除和插入操作。
-
修改数组元素:
-
#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; printf("Original array: "); for(int i = 0; i < 5; i++) { printf("%d ", arr[i]); } arr[1] = 10; //修改第二个元素 printf("\nArray after modification: "); for(int i = 0; i < 5; i++) { printf("%d ", arr[i]); } return 0; }
删除数组元素:
-
#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; int element_to_delete = 3; int i, j; for(i = 0; i < 5; i++) { if(arr[i] == element_to_delete) { for(j = i; j < 4; j++) { arr[j] = arr[j+1]; } break; } } printf("Array after deletion: "); for(int i = 0; i < 4; i++) { printf("%d ", arr[i]); } return 0; }
插入数组元素:
-
#include <stdio.h> int main() { int arr[5] = {1, 2, 4, 5}; int index = 2; int element_to_insert = 3; int i; for(i = 4; i >= index; i--) { arr[i] = arr[i-1]; } arr[index] = element_to_insert; printf("Array after insertion: "); for(int i = 0; i < 5; i++) { printf("%d ", arr[i]); } return 0; }
数据的排序
在C语言中,对数组进行排序有多种方法,下面我将列出几种常见的排序方法及其代码实现。
-
冒泡排序
冒泡排序是一种简单的排序算法,它重复地遍历要排序的数组,一次比较两个元素,如果它们的顺序错误就把它们交换过来。重复进行直到没有再需要交换的元素,这意味着数组现在已经排序完成。
void bubble_sort(int arr[], int len) {
int i, j, temp;
for (i = 0; i < len - 1; i++)
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;
}
}
-
选择排序
选择排序是一种简单直观的排序算法,无论什么数据进去都会进行排序,但是速度比冒泡排序快,所以在数据量大的时候可以选择。
void selection_sort(int arr[], int len) {
int i, j, min, temp;
for (i = 0; i < len - 1; i++) {
min = i;
for (j = i + 1; j < len; j++)
if (arr[j] < arr[min])
min = j;
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
-
插入排序
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
void insertion_sort(int arr[], int len) {
int i, j, key;
for (i = 1; i < len; i++) {
key = arr[i];
j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
-
快速排序
快速排序使用分治法(Divide and conquer)策略来把一个序列分为两个子序列。
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
int partition (int arr[], int low, int high) {
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
-
归并排序
归并排序是一种稳定的排序算法,它每次都会归并两个已经排序好的序列。
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l;
int n2 = r - m;
int L[n1
三.二维数组及其应用
二维数组的定义与初始化
二维数组在C语言中是通过一维数组的嵌套来实现的,即一个一维数组的每个元素又被声明为一维数组,从而构成二维数组。二维数组的定义格式如下:
数据类型 数组名[常量表达式1][常量表达式2];
其中,常量表达式1
表示第一维下标的长度,常量表达式2
表示第二维下标的长度。
例:
定义一个3行4列的整型二维数组。
int score[3][4]
二维数组的初始化
二维数组可以在定义时进行初始化,初始化可以是对整个数组进行赋值,也可以是对数组中的部分元素进行赋值。
在定义时初始化:
int a[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
先定义后逐个赋值:
int a[3][4];
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
a[i][j] = (i * 4) + j + 1;
字符串初始化:(适用于元素类型是字符或者是一些小的基本类型)
char a[3][10] = {
"Hello",
"World",
"!"
};
char a[3][10] = {"Hello", "World", "!"};
如果二维数组的某些值是已知的,其余的部分你想用0来初始化,可以使用:
int a[3][4] =
{
{1, 2},
{5},
{}
};
初始化结果为:
1 2 0
5 0 0 0
0 0 0 0
如果你想创建一个二维数组,但是你不知道确切的大小,你可以使用动态分配内存:
(创建一个三行四列的二维数组)
int **a = malloc(sizeof(int*) * 3);
for (int i = 0; i < 3; i++)
a[i] = malloc(sizeof(int) * 4);
注意:在使用动态分配内存的方法时,你需要手动释放内存,否则可能会导致内存泄漏
二维数组元素的引用
在C语言中,二维数组可以看作是数组的数组,即二维数组的每一个元素都是一个一维数组。因此,二维数组的元素可以通过下标来进行引用。
解法一:直接使用下标引用二维数组的元素。
#include <stdio.h>
int main() {
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
int i, j;
for(i = 0; i < 3; i++) {
for(j = 0; j < 4; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
解法二:使用指针引用二维数组的元素。(指针后面会讲,仅作了解)
#include <stdio.h>
int main() {
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
int i, j;
for(i = 0; i < 3; i++) {
for(j = 0; j < 4; j++) {
printf("%d ", *(*(arr + i) + j));
}
printf("\n");
}
return 0;
}
二维数组作为函数参数
在C语言中,二维数组可以作为函数的参数进行传递。这里有两种常见的方法:
使用静态二维数组
在这种情况下,需要在函数声明中指定数组的行和列的大小。
#include <stdio.h>
void print_arr(int arr[2][3]) {
int i, j;
for(i = 0; i < 2; i++) {
for(j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
print_arr(arr);
return 0;
}
-
使用动态分配的二维数组
在这种情况下,可以在函数声明中只指定一个维度,并在函数调用时动态分配数组。
#include <stdio.h>
#include <stdlib.h>
void print_arr(int **arr, int m, int n) {
int i, j;
for(i = 0; i < m; i++) {
for(j = 0; j < n; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int i, j;
int m = 2, n = 3;
int **arr = (int **)malloc(m * sizeof(int *));
for(i = 0; i < m; i++) {
arr[i] = (int *)malloc(n * sizeof(int));
for(j = 0; j < n; j++) {
arr[i][j] = i * n + j + 1;
}
}
print_arr(arr, m, n);
for(i = 0; i < m; i++) {
free(arr[i]);
}
free(arr);
return 0;
}
四.字符数组与字符串
在C语言中,字符串和字符数组是两个常用的数据类型,但它们之间有一些重要的区别。
-
定义方式不同:字符串是字符数组的一种特殊情况,在C语言中,字符串常量是字符数组的一个实例,其特点是以'\0'(空字符)结尾。
例如:
char str[] = "Hello"; // 这是一个字符数组
char *p = "Hello"; // 这是一个字符串常量(字符串字面量)
存储位置不同:字符串常量存储在常量区,而字符数组如果不是全局或静态的,则存储在栈或堆上。
例如:
char str[] = "Hello"; // "Hello"存储在栈上,str[]是数组的副本
char *p = "Hello"; // "Hello"存储在常量区,p是指向它的指针
-
内容不可变性:字符串常量的内容是不可以被修改的,如果尝试修改,程序会发生段错误(segmentation fault)。但是字符数组的内容是可以修改的。
例如:
char str[] = "Hello";
str[0] = 'h'; // 正确,修改数组内容
char *p = "Hello";
p[0] = 'h'; // 错误,尝试修改字符串常量的内容,会导致段错误
-
长度计算方式不同:字符串的长度可以通过strlen()函数计算,字符数组的长度需要手动计算。
例如:
char str[] = "Hello";
int len_str = strlen(str); // 计算字符串长度
char p[] = "Hello";
int len_p = sizeof(p) / sizeof(p[0]); // 计算字符数组长度
-
初始化方式不同:字符串常量初始化通常使用双引号,字符数组可以使用单引号或者双引号,但是需要注意,使用单引号时,字符数组的长度为1,内容为单引号中的字符。
例如:
char str[] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 显式初始化字符数组
char str1[] = "Hello"; // 隐式初始化字符数组
const char *p = "Hello"; // 字符串常量指针
字符数组的定义,初始化,引用
在C语言中,字符数组主要用于存储字符数据,可以是字符串,也可以是单个字符。字符数组的定义、初始化和引用方法如下:
-
定义字符数组:
char charArray[size];
其中,charArray是数组名,size是数组的大小,可以是常量或者常量表达式,字符数组的大小从1开始。
-
初始化字符数组:
char charArray[size] = {'v', 'a', 'l', 'u', 'e', '1'};
或者
char charArray[size] = "value1";
其中,单引号内的是字符,双引号内的是字符串。
-
引用字符数组:
charArray[index];
其中,index是数组的索引,从0开始。
例如:
#include <stdio.h>
int main() {
// 定义字符数组
char charArray[6];
// 初始化字符数组
charArray[0] = 'v';
charArray[1] = 'a';
charArray[2] = 'l';
charArray[3] = 'u';
charArray[4] = 'e';
charArray[5] = '2';
// 或者使用一行代码初始化
// char charArray[6] = "value2";
// 引用字符数组
printf("%c\n", charArray[0]); // 输出v
printf("%s\n", charArray); // 输出value2
return 0;
}
以上代码定义了一个大小为6的字符数组,并对其进行了初始化,然后通过索引引用了数组中的一个元素,并输出了整个数组的内容。