2010-03-30 7 views
1

Я пытаюсь написать небольшой помощник для Windows, который в конечном итоге примет расширение файла в качестве аргумента и вернет количество файлов такого типа в текущем каталоге.Почему прикосновение к «d_name» вызывает вызовы readdir()?

Для этого я читаю записи файлов в каталогах, и после получения расширения я хотел бы преобразовать его в нижний регистр, чтобы сравнить его с еще не указанным аргументом.

При преобразовании расширения в нижний регистр я обнаружил, что касание даже повторяющейся строки переменной 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 с):

Strings: (null) (null) 

Есть ли что-то не так? Это проблема компилятора? Я использую GCC 4.4.3 в Windows (MinGW) прямо сейчас.

Большое спасибо за помощь.

Кстати, есть ли другой способ работы с файлами и каталогами в среде Windows, не использующей функции POSIX?

ответ

2

В системах Windows «родной» API не является POSIX, а Win32. С Win32 попробуйте FindFirstFile() и FindNextFile().

Что касается вашего кода: ваша первая строка показывает, что первый вызов test() является указателем NULL (это то, что ваши strrch() функция возвращает для имени файла "."). strdup() Довольно любезно не сбой на NULL, но возвращает NULL. Затем вы изменяете строку, которая не существует. Это разыменование указателя NULL, и в этот момент все идет. В системе Unix это подразумевает немедленное завершение приложения с помощью segfault. В Windows это, вероятно, зависит от бренда ОС.

+0

О, спасибо вам большое! Я не понимал этого, если бы он разбился, это было бы более очевидно. –