当前位置:首页 > 技术 > 正文内容

C语言中数组与指针的综合运用

访客 技术 2026年10月11日 1

C语言中数组与指针是基础且重要的概念,它们在实际编程中经常结合使用。本文通过几个典型示例演示数组元素的访问方式、指针运算、字符串处理以及函数参数传递。

一、数组元素与指针的基本操作

定义整型数组并实现输入、输出、查找最值。本例中函数通过指针参数返回最小值和最大值。

#include <stdio.h>
#define SIZE 5

void read_array(int arr[], int n);
void print_array(int arr[], int n);
void find_min_max(int arr[], int n, int *min, int *max);

int main() {
    int data[SIZE];
    int low, high;

    printf("输入%d个整数:\n", SIZE);
    read_array(data, SIZE);

    printf("数组内容:\n");
    print_array(data, SIZE);

    find_min_max(data, SIZE, &low, &high);
    printf("最小值 = %d, 最大值 = %d\n", low, high);

    return 0;
}

void read_array(int arr[], int n) {
    for (int i = 0; i < n; ++i)
        scanf("%d", &arr[i]);
}

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

void find_min_max(int arr[], int n, int *min, int *max) {
    *min = *max = arr[0];
    for (int i = 1; i < n; ++i) {
        if (arr[i] < *min) *min = arr[i];
        if (arr[i] > *max) *max = arr[i];
    }
}

二、返回指针的函数

改写上一个例子,使函数返回最大值元素的地址。

#include <stdio.h>
#define N 5

void read(int a[], int n);
void write(int a[], int n);
int *max_addr(int a[], int n);

int main() {
    int arr[N];
    int *pmax;

    printf("录入%d个数据:\n", N);
    read(arr, N);

    printf("数据: \n");
    write(arr, N);

    pmax = max_addr(arr, N);
    printf("最大值 = %d\n", *pmax);

    return 0;
}

void read(int a[], int n) {
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);
}

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

int *max_addr(int a[], int n) {
    int max_idx = 0;
    for (int i = 1; i < n; ++i)
        if (a[i] > a[max_idx])
            max_idx = i;
    return &a[max_idx];
}

三、字符串数组与指针的交换

演示字符数组与字符指针在存储和交换时的区别。

#include <stdio.h>
#include <string.h>

int main() {
    char s1[80] = "Learning makes me happy";
    char s2[80] = "Learning makes me sleepy";
    char tmp[80];

    printf("sizeof(s1) = %lu, strlen(s1) = %lu\n", sizeof(s1), strlen(s1));

    printf("交换前:\ns1: %s\ns2: %s\n", s1, s2);
    strcpy(tmp, s1);
    strcpy(s1, s2);
    strcpy(s2, tmp);
    printf("交换后:\ns1: %s\ns2: %s\n", s1, s2);

    // 对比指针版本
    char *p1 = "Learning makes me happy";
    char *p2 = "Learning makes me sleepy";
    char *ptmp;

    printf("\n指针版:\n");
    printf("sizeof(p1) = %lu, strlen(p1) = %lu\n", sizeof(p1), strlen(p1));
    printf("交换前:p1: %s, p2: %s\n", p1, p2);
    ptmp = p1; p1 = p2; p2 = ptmp;
    printf("交换后:p1: %s, p2: %s\n", p1, p2);

    return 0;
}

输出说明:sizeof(s1)返回数组总字节(包括'\0'),strlen仅计算有效字符;指针版sizeof(p1)返回指针本身大小,交换仅交换地址,原字符串不变。

四、二维数组与指针的多种遍历方式

定义一个2x4的二维数组,分别用下标、元素指针和行指针访问。

#include <stdio.h>

int main() {
    int matrix[2][4] = {{1,9,8,4}, {2,0,4,9}};
    int i, j;
    int *p1;       // 元素指针
    int (*p2)[4];  // 行指针,指向含4个int的数组

    // 下标法
    printf("下标法:\n");
    for (i = 0; i < 2; ++i) {
        for (j = 0; j < 4; ++j)
            printf("%d ", matrix[i][j]);
        printf("\n");
    }

    // 元素指针
    printf("元素指针:\n");
    for (p1 = &matrix[0][0], i = 0; p1 < &matrix[0][0] + 8; ++p1, ++i) {
        printf("%d ", *p1);
        if ((i+1) % 4 == 0) printf("\n");
    }

    // 行指针
    printf("行指针:\n");
    for (p2 = matrix; p2 < matrix + 2; ++p2) {
        for (j = 0; j < 4; ++j)
            printf("%d ", *(*p2 + j));
        printf("\n");
    }

    return 0;
}

注意:int (*ptr)[4]是行指针,自增跳过整行;int *ptr[4]是指针数组。

五、字符串替换函数

将字符串中指定字符替换为另一个字符。

#include <stdio.h>
#define SIZE 80

void replace(char *str, char old, char new) {
    while (*str) {
        if (*str == old)
            *str = new;
        str++;
    }
}

int main() {
    char text[SIZE] = "Programming is difficult or not, it is a question.";
    printf("原始: %s\n", text);
    replace(text, 'i', '*');
    printf("替换后: %s\n", text);
    return 0;
}

六、字符串截断函数

从第一个指定字符处将字符串截断(设为'\0')。

#include <stdio.h>
#define N 80

char *trunc_str(char *str, char ch) {
    char *p = str;
    while (*p != '\0' && *p != ch)
        p++;
    if (*p == ch)
        *p = '\0';
    return str;
}

int main() {
    char buf[N];
    char delimiter;
    while (printf("输入字符串: "), gets(buf) != NULL) {
        printf("输入截断字符: ");
        delimiter = getchar();
        getchar();  // 吸收换行
        trunc_str(buf, delimiter);
        printf("结果: %s\n\n", buf);
    }
    return 0;
}

七、身份证号校验

检查字符串是否为合法18位身份证号(前17位数字,末位可为数字或大写X)。

#include <stdio.h>
#include <string.h>

int valid_id(const char *id) {
    int len = strlen(id);
    if (len != 18) return 0;
    for (int i = 0; i < len; ++i) {
        if (id[i] < '0' || id[i] > '9') {
            if (i != 17 || id[i] != 'X')
                return 0;
        }
    }
    return 1;
}

int main() {
    const char *ids[] = {"31010120000721656X",
                         "3301061996X0203301",
                         "53010220051126571",
                         "510104199211197977",
                         "53010220051126133Y"};
    for (int i = 0; i < 5; ++i)
        printf("%s\t%s\n", ids[i], valid_id(ids[i]) ? "True" : "False");
    return 0;
}

八、凯撒加密与解密

对英文字母进行循环移位,编码用后移n位,解码用前移n位。

#include <stdio.h>
#define N 80

void encode(char *str, int n) {
    while (*str) {
        if (*str >= 'a' && *str <= 'z')
            *str = (*str - 'a' + n) % 26 + 'a';
        else if (*str >= 'A' && *str <= 'Z')
            *str = (*str - 'A' + n) % 26 + 'A';
        str++;
    }
}

void decode(char *str, int n) {
    while (*str) {
        if (*str >= 'a' && *str <= 'z')
            *str = (*str - 'a' - n + 26) % 26 + 'a';
        else if (*str >= 'A' && *str <= 'Z')
            *str = (*str - 'A' - n + 26) % 26 + 'A';
        str++;
    }
}

int main() {
    char text[N];
    int shift;
    printf("输入英文文本: ");
    gets(text);
    printf("输入移位量: ");
    scanf("%d", &shift);
    encode(text, shift);
    printf("编码后: %s\n", text);
    decode(text, shift);
    printf("解码后: %s\n", text);
    return 0;
}

九、命令行参数排序与输出

对命令行输入的字符串数组按字典序排序,并输出带"hello, "前缀的结果。

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    // 冒泡排序
    for (int i = 1; i < argc - 1; ++i) {
        for (int j = 1; j < argc - i; ++j) {
            if (strcmp(argv[j], argv[j+1]) > 0) {
                char *temp = argv[j];
                argv[j] = argv[j+1];
                argv[j+1] = temp;
            }
        }
    }

    for (int i = 1; i < argc; ++i)
        printf("hello, %s\n", argv[i]);

    return 0;
}

标签: C语言数组

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。