【C语言】 “函数指针”和“指针函数” 用法和详解(太细了!!!)菜鸟级教程


一、标准 I/O 和系统 I/O的区别

1.高层接口 vs 低层接口

1、标准 I/O
(1)标准 I/O 函数是高层接口,提供了一组方便的函数(如 fopen、fprintf、fread 等)来进行文件的读写操作。
(2)它们抽象了底层系统调用,更容易使用,且具有跨平台性。
2、系统 I/O
(1)系统 I/O 是低层接口,它使用系统调用(如 open、read、write 等)来直接操作文件。
(2)调用提供更底层的控制,但通常需要更多的代码和对操作系统的了解。

2.缓冲

1、标准 I/O:
(1)标准 I/O 函数自动进行缓冲,数据通常首先被读入或写出到一个内部缓冲区,然后根据需要进行实际的 I/O 操作。
(2)可以提高性能,尤其是在频繁的小数据量读写时。
2、系统 I/O:
(1)系统 I/O 通常不提供自动缓冲,你需要自己手动管理缓冲区。
(2)这使得对文件的读写更加直接,但可能需要更多的编程工作。

3.错误处理

1、标准 I/O:
(1)标准 I/O 函数使用 NULL 指针返回错误,可以使用 feof 和 ferror 函数来检查文件尾和错误状态。
(2)错误消息可以通过 perror 函数输出。
2、系统 I/O:
(1)系统 I/O 函数通常返回 -1 来表示错误,可以通过查看 errno 全局变量来获取特定的错误代码,然后使用 perror 或 strerror 函数将错误消息打印出来。

二、"标准I/O"的使用

(1)使用 fopen 函数打开一个文件以供写入,如果文件不存在则创建。如果打开失败,它会使用 perror 函数打印错误消息,并返回错误码 1。
(2)使用 fprintf 函数将文本写入文件。
(3)使用 fclose 函数关闭文件。
(4)使用 fopen 函数再次打开文件以供读取。如果打开失败,它会再次使用 perror 函数打印错误消息,并返回错误码 1。
(5)使用 fgets 函数逐行读取文件内容,直到文件末尾。每一行都会被存储在 buffer 缓冲区中。
(6)使用 printf 函数打印从文件中读取的每一行内容。
(7)使用 fclose 函数关闭文件。
(8)最后,程序返回 0 表示成功结束。

代码如下(示例):

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

int main() {
    // 打开一个文件以供写入,如果文件不存在则创建 ("w" 模式)
    FILE *file = fopen("stdio_example.txt", "w");
    if (file == NULL) {
        perror("无法打开文件"); // 打印错误消息并返回错误码
        return 1;
    }

    // 写入文件
    fprintf(file, "这是标准I/O写入的文本\n");
    fclose(file); // 关闭文件

    // 重新打开文件以供读取 ("r" 模式)
    file = fopen("stdio_example.txt", "r");
    if (file == NULL) {
        perror("无法打开文件"); // 打印错误消息并返回错误码
        return 1;
    }

    char buffer[100];
    // 逐行读取文件内容,直到文件末尾
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("标准I/O读取: %s", buffer); // 打印每行内容
    }
    fclose(file); // 关闭文件

    return 0; // 成功结束程序
}
 输出结果:标准I/O读取: 这是标准I/O写入的文本

三、"系统I/O"的使用

(1)使用 open 系统调用打开一个文件以供写入,如果文件不存在则创建,权限为 0644。如果打开失败,它会使用 strerror 函数打印错误消息和错误号,然后返回错误码 1 表示程序异常结束。
(2)使用 write 系统调用将文本写入文件。如果写入失败,它会使用 strerror 函数打印错误消息和错误号,关闭文件,然后返回错误码 1。
(3)使用 close 系统调用关闭文件。
(4)重新使用 open 系统调用打开文件以供读取(“O_RDONLY” 模式)。如果打开失败,它会使用 strerror 函数打印错误消息和错误号,然后返回错误码 1。
(5)使用 read 系统调用逐块读取文件内容,直到文件末尾。每块内容都被存储在 buffer 缓冲区中。
(6)使用 write 系统调用将读取的内容写入标准输出。如果写入失败,它会使用 strerror 函数打印错误消息和错误号,关闭文件,然后返回错误码 1。
(7)使用 close 系统调用关闭文件。
(8)最后,如果一切正常,程序返回 0 表示成功结束。

代码如下(示例):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main() {
    // 打开一个文件以供写入,如果文件不存在则创建,权限为 0644
    int fd = open("syscalls_example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1) {
        fprintf(stderr, "无法打开文件: %s\n", strerror(errno)); // 打印错误消息和错误号
        return 1; // 返回错误码 1 表示程序异常结束
    }

    // 写入文件
    char *text = "这是系统I/O写入的文本\n";
    ssize_t bytesWritten = write(fd, text, strlen(text)); // 写入文件内容
    if (bytesWritten == -1) {
        fprintf(stderr, "写入文件时发生错误: %s\n", strerror(errno)); // 打印错误消息和错误号
        close(fd); // 关闭文件
        return 1; // 返回错误码 1 表示程序异常结束
    }
    close(fd); // 关闭文件

    // 重新打开文件以供读取 ("O_RDONLY" 模式)
    fd = open("syscalls_example.txt", O_RDONLY);
    if (fd == -1) {
        fprintf(stderr, "无法打开文件: %s\n", strerror(errno)); // 打印错误消息和错误号
        return 1; // 返回错误码 1 表示程序异常结束
    }

    char buffer[100];
    ssize_t bytesRead;
    // 逐块读取文件内容,直到文件末尾
    while ((bytesRead = read(fd, buffer, sizeof(buffer))) > 0) {
        ssize_t bytesWritten = write(STDOUT_FILENO, buffer, bytesRead); // 将读取的内容写入标准输出
        if (bytesWritten == -1) {
            fprintf(stderr, "写入标准输出时发生错误: %s\n", strerror(errno)); // 打印错误消息和错误号
            close(fd); // 关闭文件
            return 1; // 返回错误码 1 表示程序异常结束
        }
    }
    close(fd); // 关闭文件

    return 0; // 成功结束程序
}
 输出结果:这是系统I/O写入的文本

粉丝福利、需求解答

### 构建任务失败解决方案 当遇到 `Execution failed for task ':app:shrinkReleaseRes'` 错误时,这通常意味着资源压缩过程中出现了问题。此错误可能由多种原因引起,包括但不限于配置不正确、依赖冲突或特定于项目的其他因素。 #### 可能的原因分析 1. **ProGuard 或 R8 配置不当** ProGuard R8 是用于优化混淆代码以及减少 APK 大小的工具。如果这些工具的配置存在问题,可能会导致资源无法正常处理[^1]。 2. **重复资源** 如果项目中有多个模块定义了相同的资源名称,可能导致冲突并引发该错误。检查是否存在重名的 drawable、string 等资源文件[^2]。 3. **第三方库兼容性** 某些第三方库可能当前使用的 Gradle 插件版本或其他库存在兼容性问题,从而影响到资源打包过程中的行为[^3]。 4. **Gradle 缓存问题** 有时旧缓存数据会干扰新编译的结果,尝试清理本地仓库重新同步项目可以帮助排除此类潜在障碍[^4]。 #### 推荐的操作方法 为了有效解决问题,建议按照以下步骤逐一排查: ```bash # 清理项目构建目录 ./gradlew clean # 删除 .gradle 文件夹下的所有内容以清除缓存 rm -rf ~/.gradle/caches/ ``` 调整 `build.gradle` 中的相关设置也是一个重要环节: ```groovy android { ... buildTypes { release { minifyEnabled true // 是否启用代码缩减 shrinkResources true // 是否开启资源压缩 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // 尝试禁用 shrinkResources 来测试是否为资源压缩引起的错误 // shrinkResources false } } } ``` 此外,在 `proguard-rules.pro` 文件内添加必要的保留规则,防止关键类被意外移除: ```text -keep class com.example.yourpackage.** { *; } # 替换为你自己的包路径 -dontwarn androidx.**,com.google.** # 忽略警告信息 ``` 最后,确保所使用的 Android Studio 版本是最新的稳定版,并且已经应用了所有的补丁更新。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恒创科技工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值