1

最終的にファイル拡張子を引数として受け入れ、現在のディレクトリにあるその種類のファイルの数を返す 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");
}

複製を変更せずに出力します(変更と2番目の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

同じディレクトリの出力 (上記のコードと 2printf秒):

Strings: (null) (null)

何か間違っていることでも?コンパイラの問題ですか?現在、Windows (MinGW) で GCC 4.4.3 を使用しています。

ご助力ありがとうございます。

ところで、Windows 環境で POSIX 関数を使わずにファイルやディレクトリを操作する方法はありますか?

4

1 に答える 1

3

Windows システムでは、「ネイティブ」API は POSIX ではなく Win32 です。Win32 では、FindFirstFile()FindNextFile( ) を試してください。

コードに関しては、最初の行は、への最初の呼び出しがtest()NULL ポインターを使用していることを示しています (これは、strrch()関数が のファイル名に対して返すものです".")。strdup()クラッシュしないほど親切ですNULLが、 を返しますNULL。次に、存在しない「文字列」を変更します。これは NULL ポインターの逆参照であり、この時点ですべてが実行されます。Unix システムでは、これはセグメンテーション違反を伴うアプリケーションの即時終了を意味します。Windows では、これはおそらく OS ブランドに依存します。

于 2010-03-30T12:22:16.250 に答える