c语言 findfirst函数

99ANYc3cd6
预计阅读时长 25 分钟
位置: 首页 C语言 正文

findfirst 并不是标准 C 语言库(如 ANSI C/C89, C99, C11, C17, C23)的一部分,它是特定于某些操作系统或编译器的函数,最著名的就是 Borland C++ (Turbo C++) 在 DOS 环境下提供的。

c语言 findfirst函数
(图片来源网络,侵删)

尽管如此,由于其简单易用,许多其他非标准的库(例如一些 Windows 的旧版 API 或跨平台库)也提供了类似功能的函数,理解 findfirst 的工作原理对于学习文件操作和了解不同 C 语言的实现方式非常有帮助。


findfirst 的核心概念

findfirst 函数用于在指定的目录中查找第一个符合特定模式的文件或目录,它通常与 findnext 函数配对使用:

  • findfirst: 开始一次查找,返回第一个匹配项。
  • findnext: 继续查找,返回下一个匹配项。

这个过程会一直持续,直到没有更多匹配项或发生错误。


Borland C++ (Turbo C++) 的实现

这是 findfirst 最经典和最广为人知的实现,它工作在 DOS 环境下。

c语言 findfirst函数
(图片来源网络,侵删)

1 头文件

在使用 findfirstfindnext 时,需要包含以下头文件:

#include <dir.h>   // 主要的头文件
#include <dos.h>   // 有时也需要
#include <stdio.h>  // 用于 printf 等标准 I/O

2 核心结构体:ffblk

findfirstfindnext 函数通过一个名为 ffblk 的结构体来传递文件信息。

struct ffblk {
    char ff_reserved[21];  // 保留,内部使用
    char ff_attrib;        // 文件属性
    int ff_ftime;          // 文件时间 (打包的)
    int ff_fdate;          // 文件日期 (打包的)
    long ff_fsize;         // 文件大小 (字节)
    char ff_name[256];     // 文件名 (包括扩展名)
};

关键成员解释:

  • ff_attrib: 文件属性,是一个位掩码,常用的值定义在 <dos.h> 中:
    • FA_RDONLY: 只读文件
    • FA_HIDDEN: 隐藏文件
    • FA_SYSTEM: 系统文件
    • FA_LABEL: 卷标 (不是一个文件)
    • FA_DIREC: 目录
    • FA_ARCH: 存档文件
  • ff_fsize: 文件大小,以字节为单位。
  • ff_name: 文件名,是一个以 null 结尾的字符串。

3 函数原型

int findfirst(const char *pattern, struct ffblk *ffblk, int attrib);
int findnext(struct ffblk *ffblk);

4 参数说明

findfirst 函数参数:

c语言 findfirst函数
(图片来源网络,侵删)
  • pattern: 查找模式,它是一个字符串,可以包含通配符 (匹配任意数量的字符) 和 (匹配单个字符)。
    • "*.c": 查找所有 C 源文件。
    • "a??.txt": 查找以 'a' 开头,后面跟两个任意字符,扩展名为 .txt 的文件。
    • "C:\\DATA\\*.dat": 在 C:\DATA 目录下查找所有 .dat 文件。
  • ffblk: 指向 ffblk 结构体的指针,函数会将找到的第一个文件的信息填充到这个结构体中。
  • attrib: 要查找的文件属性,你可以使用 (位或) 组合多个属性,如果想查找所有文件(包括隐藏和系统文件),通常传入 0,如果你想只查找目录,可以传入 FA_DIREC

findnext 函数参数:

  • ffblk: 指向同一个 ffblk 结构体的指针。findnext 会用下一个匹配文件的信息来更新它。

5 返回值

两个函数都返回一个 int 值,表示操作是否成功:

  • 0: 成功。
  • 非零值 (-1): 失败,可以通过 doserrno (定义在 <dos.h>) 获取具体的错误码。

完整示例代码 (Borland C++ / Turbo C++)

下面的示例演示了如何查找当前目录下所有的 .c 文件,并打印它们的名称和大小。

#include <stdio.h>
#include <dir.h>
#include <string.h>
int main() {
    struct ffblk ffblk; // 用于存储文件信息的结构体
    int done;            // 用于存储 findfirst/next 的返回值
    // 开始查找所有 .c 文件
    // 第三个参数 0 表示查找所有类型的文件(无论属性)
    done = findfirst("*.c", &ffblk, 0);
    // findfirst 成功 (返回 0),说明找到了至少一个匹配的文件
    if (done == 0) {
        printf("找到以下 .c 文件:\n");
        printf("----------------------------------------\n");
        // 循环处理所有找到的文件
        // 当 done == 0 时,表示还有文件可以处理
        while (done == 0) {
            printf("文件名: %-20s 大小: %ld 字节\n", ffblk.ff_name, ffblk.ff_fsize);
            // 尝试查找下一个匹配的文件
            done = findnext(&ffblk);
        }
        printf("----------------------------------------\n");
        printf("查找完毕,\n");
    } else {
        printf("当前目录下没有找到 .c 文件,\n");
    }
    return 0;
}

现代 C 语言的替代方案:<dirent.h>

在现代操作系统(如 Linux, macOS, Windows 的 POSIX 子系统)上进行 C 语言编程时,应该使用标准化的目录操作头文件 <dirent.h>,它提供了更强大、更可移植的接口。

1 核心结构体:struct dirent

struct dirent {
    ino_t          d_ino;       // inode 编号 (Linux/Unix 特有)
    off_t          d_off;       // 在目录文件中的偏移量 (Linux/Unix 特有)
    unsigned short d_reclen;    // 目录记录的长度
    unsigned char  d_type;      // 文件类型 (DT_REG, DT_DIR, DT_LNK 等)
    char           d_name[256]; // 文件名,以 null 
};

2 核心函数

  • DIR *opendir(const char *name): 打开一个目录流,返回一个指向 DIR 结构体的指针。
  • struct dirent *readdir(DIR *dirp): 从打开的目录流中读取下一个目录项。
  • int closedir(DIR *dirp): 关闭目录流。

3 <dirent.h> 示例

下面的示例实现了与上面 findfirst 示例完全相同的功能,但使用了标准 <dirent.h> 接口,可以在 Linux 和 macOS 上编译运行。

#include <stdio.h>
#include <string.h>
#include <dirent.h> // 标准目录操作头文件
int main() {
    DIR *dp;                  // 目录指针
    struct dirent *entry;     // 目录项指针
    char *dirname = ".";      // 当前目录
    const char *ext = ".c";   // 要查找的文件扩展名
    // 打开目录
    dp = opendir(dirname);
    if (dp == NULL) {
        perror("无法打开目录");
        return 1;
    }
    printf("找到以下 %s 文件:\n", ext);
    printf("----------------------------------------\n");
    // 读取目录中的每一个条目
    while ((entry = readdir(dp)) != NULL) {
        // 检查文件名是否以 .c 
        if (strstr(entry->d_name, ext) != NULL) {
            printf("文件名: %-20s\n", entry->d_name);
            // 注意:readdir 本身不提供文件大小信息,
            // 需要使用 stat() 函数来获取。
        }
    }
    printf("----------------------------------------\n");
    printf("查找完毕,\n");
    // 关闭目录
    closedir(dp);
    return 0;
}

Windows 平台的替代方案:<io.h>

在 Windows 平台上进行原生 C/C++ 开发时,可以使用另一个非标准但非常普遍的头文件 <io.h>,它提供了类似 findfirst 的功能,并且是 Windows 推荐的旧式文件查找方式。

1 核心结构体:_finddata_t

struct _finddata_t {
    unsigned    attrib;   // 文件属性
    __time64_t  time_create;    // 创建时间
    __time64_t  time_access;    // 最后访问时间
    __time64_t  time_write;     // 最后写入时间
    _fsize_t    size;      // 文件大小
    char        name[260]; // 文件名
};

2 核心函数

  • long _findfirst(const char *filespec, struct _finddata_t *fileinfo): 查找第一个匹配的文件。
  • int _findnext(long handle, struct _finddata_t *fileinfo): 查找下一个匹配的文件。
  • int _findclose(long handle): 关闭查找句柄。

3 <io.h> 示例

#include <stdio.h>
#include <io.h>      // Windows 文件查找头文件
#include <stdlib.h>  // 用于 _MAX_PATH
int main() {
    struct _finddata_t c_file;
    long hFile;
    int result = 1;
    // 查找第一个 .c 文件
    // _MAX_PATH 是一个定义好的最大路径长度常量
    if ((hFile = _findfirst("*.c", &c_file)) == -1L) {
        printf("找不到任何 .c 文件\n");
    } else {
        printf("找到以下 .c 文件:\n");
        printf("----------------------------------------\n");
        // 循环打印所有找到的文件
        while (result == 0) {
            printf("文件名: %-20s 大小: %d 字节\n", c_file.name, c_file.size);
            result = _findnext(hFile, &c_file);
        }
        printf("----------------------------------------\n");
        printf("查找完毕,\n");
        // 关闭查找句柄
        _findclose(hFile);
    }
    return 0;
}

总结与对比

特性 findfirst (Borland C) <dirent.h> (标准 POSIX) <io.h> (Windows)
平台 DOS (过时) Linux, macOS, Windows (WSL/Cygwin) Windows (原生)
标准性 非标准 标准 非标准 (但广泛使用)
头文件 #include <dir.h> #include <dirent.h> #include <io.h>
核心结构 struct ffblk struct dirent struct _finddata_t
主要函数 findfirst, findnext opendir, readdir, closedir _findfirst, _findnext, _findclose
优点 非常简单直观 跨平台,功能强大,现代标准 在 Windows 上高效,功能丰富
缺点 仅限 DOS,已过时 API 稍复杂 (opendir/readdir) 仅限 Windows,可移植性差
  • 如果你正在学习历史代码或在 DOS 环境下编程,你需要了解 findfirst
  • 如果你正在为现代、跨平台的 Unix-like 系统(Linux, macOS)编写代码,必须使用 <dirent.h>
  • 如果你正在编写 Windows 原生应用程序,并且不关心跨平台性,<io.h> 是一个非常好的选择,比 findfirst 更现代、更强大。
-- 展开阅读全文 --
头像
织梦value=k多选框
« 上一篇 2025-12-31
织梦和discuz哪个文件
下一篇 » 2025-12-31
取消
微信二维码
支付宝二维码

目录[+]