为什么触摸“d_name”会调用readdir()失败?

时间:2010-03-30 12:09:33

标签: c windows file filesystems directory-structure

我正在尝试为Windows编写一个小帮助程序,最终将接受文件扩展名作为参数,并在当前目录中返回该类文件的数量。

为此,我正在读取目录中的文件条目,在获得扩展名后,我想将其转换为小写,以便将其与尚未添加的指定参数进行比较。

将扩展名转换为小写时,我发现触摸d_name变量的重复字符串会导致奇怪的行为,就像不再调用readdir一样。

这是我正在使用的代码(注释代码是初步的)和给定目录的输出:

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

char * strrch(char *string, size_t elements, char character) {
    char *reverse = string + elements;
    while (--reverse != string)
        if (*reverse == character)
            return reverse;
    return NULL;
}

void test(char *string) {
    // Even being a duplicate will make it fail:
    char *str = strdup(string);
    printf("Strings: %s %s\n", string, str);
    *str = 'a';
    printf("Strings: %s %s\n", string, str);

    //unsigned short int i = 0;
    //for (; str[i] != '\0', str++; i++)
    //   str[i] = tolower((unsigned char) str[i]);
    //puts(str);
}

int main(int argc, char **argv) {
    DIR *directory;
    struct dirent *element;   

    if (directory = opendir(".")) {
        while (element = readdir(directory))
            test(strrch(element->d_name, element->d_namlen, '.'));
        closedir(directory);
        puts(NULL);
    } else
        puts("Couldn't open the directory.\n");
}

输出而不修改副本(修改和第二个printf调用评论):

Strings: (null) (null)
Strings: . .
Strings: .exe .exe
Strings: .pdf .pdf
Strings: .c .c
Strings: .ini .ini
Strings: .pdf .pdf
Strings: .pdf .pdf
Strings: .pdf .pdf
Strings: .flac .flac
Strings: .FLAC .FLAC
Strings: .lnk .lnk
Strings: .URL .URL

输出相同的目录(上面的代码,2 printf s):

Strings: (null) (null)

有什么不对吗?这是一个编译问题吗?我现在在Windows(MinGW)中使用GCC 4.4.3。

非常感谢你的帮助。

顺便问一下,在不使用POSIX功能的Windows环境中,还有其他方法可以处理文件和目录吗?

1 个答案:

答案 0 :(得分:2)

在Windows系统上,“本机”API不是POSIX而是Win32。使用Win32,尝试FindFirstFile()FindNextFile()

至于你的代码:你的第一行显示第一次调用test()时带有一个NULL指针(这就是你的strrch()函数返回的文件名".")。 strdup()非常友好,不会在NULL上崩溃,但会返回NULL。然后修改不存在的“字符串”。这是一个NULL指针取消引用,此时任何事情都会发生。在Unix系统上,这意味着立即终止应用程序,并发生段错误。在Windows上,这可能取决于操作系统品牌。