侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

C语言学习小记(6)-数组

zze
zze
2024-03-12 / 0 评论 / 0 点赞 / 32 阅读 / 10521 字

概述

在C语言中,数组是一种数据结构,用于存储具有相同类型和连续内存地址的元素集合。数组中的每个元素可以通过索引(下标)访问,并且数组的大小在声明时就必须确定。

定义

数组是一系列相同类型的变量有序排列而成的数据集合。

特点

  • 所有元素的类型相同。

  • 元素在内存中是连续存储的。

  • 访问数组元素通过索引完成,索引从0开始。

  • C99标准之前,数组长度必须为编译时常量;C99及以后允许在某些情况下使用变量作为数组长度创建变长数组(VLA)。

使用示例

声明与初始化

// 声明并初始化一个包含5个整数的数组
int arr[5] = {1, 2, 3, 4, 5};

// 或者仅声明而不初始化
int anotherArr[6];
•访问数组元素:// 访问数组的第一个元素(索引为0)
int firstElement = arr[0];

// 修改数组的第四个元素
arr[3] = 10;

一维数组

#include <stdio.h>

int main() {
    int numbers[5] = {10, 20, 30, 40, 50};

    for (int i = 0; i < 5; ++i) {
        printf("Element at index %d is: %d\n", i, numbers[i]);
    }

    return 0;
}

多维数组

C语言还支持多维数组,例如二维数组,可以看作是一个矩阵:

int matrix[3][4]; // 3行4列的整型二维数组

// 初始化二维数组的一部分
matrix[0][0] = 1;
matrix[1][1] = 5;
matrix[2][3] = 9;

// 访问二维数组元素
printf("Element in the second row and third column: %d\n", matrix[1][2]);

注意事项

  • 数组的索引不能越界,即对于长度为N的数组,有效索引范围是从0到N-1。

  • 在C语言中没有内建的数组大小检查,程序员需要确保自己在操作数组时不会超出其边界。

动态数组

虽然C语言标准库不直接提供动态数组功能,但可以通过指针和malloc()、calloc()等动态内存分配函数来实现动态数组的功能。例如:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int size = 10; // 动态决定数组长度
    int *dynamicArray = (int*) malloc(size * sizeof(int)); // 分配内存空间

    if (dynamicArray == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    dynamicArray[0] = 1;
    // 使用和填充动态数组...

    free(dynamicArray); // 不再使用时释放内存

    return 0;
}

字符数组

在C语言中,字符数组是一种专门用来存储字符序列(即字符串)的数据结构。

字符数组是一个由char类型元素组成的数组。

char str[10]; // 定义一个长度为10的字符数组

可以在声明时通过字符串字面量进行初始化,并且系统会自动添加终止符 \0 表示字符串结束。

char s1[] = {'h', 'e', 'l', 'l', 'o'};
char s2[] = "hello";
printf("s1 size: %lu\n", sizeof(s1)); // 5
printf("s2 size: %lu\n", sizeof(s2)); // 6
printf("s1 length: %lu\n", strlen(s1)); // 5 遇 \0 终止计算,这里 s1 没有 \0,所以可能访问非法内存
printf("s2 length: %lu\n", strlen(s2)); // 5 strlen 不会计算 \0

char s3[] = "hello\0world";
printf("s3 length: %lu\n", strlen(s3)); // 5
printf("s3 size: %lu\n", sizeof(s3)); // 12

所以在设置字符数组大小时要同时分配足够容纳字符串以及 \0

#include <stdio.h>

int main() {
    // 声明并初始化一个字符数组
    char name[20] = "Alice";

    // 计算字符串长度
    int length = strlen(name);
    printf("Name length: %d\n", length);

    // 输出整个字符串
    printf("Name: %s\n", name);

    // 修改字符数组的内容
    name[0] = 'A';
    name[5] = '\0'; // 将字符串截断为"Alice"
    name[6] = 'A'; // 输出到 \0 后截断,后面的内容不会输出

    // 再次输出修改后的字符串
    printf("Modified name: %s\n", name);  // Alice

    // 动态读取用户输入并保存到字符数组中
    char input[50];
    printf("Enter your name: ");
    scanf("%49s", input); // 注意限制输入长度防止溢出
    printf("You entered: %s\n", input);

    return 0;
}

示例

例 1:获取最大值和最小值

将用户输入的 10 个数字保存到数组,获取数组中的最大值和最小值。

int arr[10] = {}; // 初始化数组
int len = sizeof(arr) / sizeof(arr[0]); // 数组长度
printf("请输入 %d 个数字: \n", len);
for (int i = 0; i < len; i++)
{
    scanf("%d", &arr[i]);
}

int max, min = 0;
for (int i = 0; i < len; i++)
{
    if (i == 0)
    {
        max = arr[i];
        min = arr[i];
    }
    else
    {
        if (arr[i] > max)
        {
            max = arr[i];
        }

        if (arr[i] < min)
        {
            min = arr[i];
        }
    }
}
printf("max: %d, min: %d\n", max, min);

例 2:反转数组

将用户输入的 10 个数字保存到数组,反转数组元素。

int arr[10] = {};                       // 初始化数组
int len = sizeof(arr) / sizeof(arr[0]); // 数组长度
printf("请输入 %d 个数字: \n", len);
for (int i = 0; i < len; i++)
{
    scanf("%d", &arr[i]);
}

// for (int i = 0; i < len / 2; i++)
for (int i = 0, j = len - 1; i < j; i++, j--)
{
    int left = arr[i];
    int right = arr[len - 1 - i];
    // printf("i = %d, left = %d, right = %d\n", i, left, right);
    arr[i] = right;
    arr[len - 1 - i] = left;
}

for (int i = 0; i < len; i++)
{
    printf("%d ", arr[i]);
}
printf("\n");

例 3:保存输入到字符串

使用 scanf 读取输入到字符串时,遇到空格或回车会终止读取,看如下示例:

char s1[30] = {};
printf("输入字符串: \n");
scanf("%s", s1); // 输入 hello world
printf("输入的内容: %s", s1); // 输入的内容: hello

修改使用 fgets 函数可以解决这个问题:

char s1[30] = {};
printf("输入字符串: \n");
fgets(s1, sizeof(s1), stdin); // 输入 hello world
printf("输入的内容: %s", s1); // 输入的内容: hello world,会保存回车到 s1
s1[strlen(s1) - 1] = 0; // 消除获取到的回车

例 4:实现 strlen 的效果

  • 方式一

char str[] = "hello world";
int len = sizeof(str) / sizeof(str[0]);
int result = 0;
for (int i = 0; i < len; i++)
{
    if (str[i] == '\0')
    {
        break;
    }
    else
    {
        result++;
    }
}

printf("result length: %d", result);
  • 方式二

char str[30] = {};
printf("输入字符串: \n");
fgets(str, sizeof(str), stdin);
str[strlen(str) - 1] = 0;
int idx = 0;
while (str[idx] != '\0')
// while (str[idx])
{
    idx++;
}
while (str[idx] != '\0' && ++idx);
printf("len: %d", idx);

例 5:字符串拷贝

char str1[30] = "";
char str2[30] = "";
printf("输入字符串: \n");
fgets(str1, sizeof(str1), stdin);
str1[strlen(str1) - 1] = 0;
int idx = 0;
while (str1[idx] != '\0')
{
    str2[idx] = str1[idx];
    idx++;
}
str2[idx] = '\0';
printf("str2: %s\n", str2);

例 6:字符串追加

  • 方式一

char str1[128] = "hello";
char str2[128] = "world";

int str1Len = strlen(str1);
for (int i = 0; i < strlen(str2); i++)
{
    str1[str1Len + i] = str2[i];
}
str1[str1Len + strlen(str2)] = '\0';
printf("str1: %s, len: %lu", str1, strlen(str1));
  • 方式二

char str1[128] = "hello";
char str2[128] = "world";

int idx1 = 0, idx2 = 0;
// 找到 str1 结束索引的位置
while (str1[idx1] && ++idx1)
    ;
// 循环 str2
while (str2[idx2])
{
    str1[idx1] = str2[idx2];
    idx1++;
    idx2++;
}
str1[idx1] = '\0';
printf("str1: %s len: %lu", str1, strlen(str1));

字符串中查找字符

char str[128] = "";
printf("请输入一个字符串: \n");
fgets(str, sizeof(str), stdin);
str[strlen(str) - 1] = '\0';

printf("请输入查找的字符: \n");
char c = getchar();

int idx = 0;

while (str[idx] != '\0')
{
    if (str[idx] == c)
    {
        break;
    }
    idx++;
}

if (str[idx] == '\0')
{
    printf("找不到\n");
    return;
}
else
{
    printf("找到了, 索引为: %d\n", idx);
}

插入字符串

char str1[128] = "";
char str2[128] = "";
int pos = 0;
printf("请输入第 1 个字符串: \n");
fgets(str1, sizeof(str1), stdin);
str1[strlen(str1) - 1] = '\0';

printf("请输入第 2 个字符串: \n");
fgets(str2, sizeof(str2), stdin);
str2[strlen(str2) - 1] = '\0';

printf("请输入要插入的位置索引: \n");
scanf("%d", &pos);

if (pos >= strlen(str1) || pos < 0)
{
    printf("指定位置超出 str1 实际内容索引界限\n");
    return;
}

// 让 str1 中间空出 str2 长度的位置
for (int i = strlen(str1) - 1; i >= pos; i--)
{
    str1[strlen(str2) + i] = str1[i];
}

// 在 str1 中插入 str2
for (int i = 0; i < strlen(str2); i++)
{
    str1[pos + i] = str2[i];
}

str1[strlen(str1) + strlen(str2)] = '\0';

printf("str1: %s, sizeof: %lu\n", str1, sizeof(str1));

0

评论区