2011-08-23 2 views
2

Я разрабатываю код, который читает имена файлов с SD-карты (с использованием FatF) и отображает их на экране. Вот snipet того, что я работаю, это выводит файлы на карту, как и ожидалось -Копирование строки из указателя на строку

FRESULT result; 
     char *path = '/'; //look in root of sd card 
     result = f_opendir(&directory, path); //open directory 
     if(result==FR_OK){ 
      for(;;){ 
       result = f_readdir(&directory, &fileInfo); //read directory 
       if(result==FR_OK){ 
        if(fileInfo.fname[0]==0){ //end of dir reached 
         //LCD_UsrLog("End of directory.\n"); 
         break; 
        } 
        if(fileInfo.fname[0]=='.')continue; //ignore '.' files 

        TCHAR *fn_ptr; //file name, why a pointer? 
        fn_ptr=&fileInfo.fname; //get file name    
        LCD_UsrLog("%s\n",fn_ptr); 
        for(delay=0;delay<0x0FFFFF;delay++){ShortDelay();} //delay to display 

       }//end result==fr_ok 
      }//end for 
     }//end result==fr_ok 

Где

typedef char TCHAR 

и

typedef struct { 
DWORD fsize;   /* File size */ 
WORD fdate;   /* Last modified date */ 
WORD ftime;   /* Last modified time */ 
BYTE fattrib;  /* Attribute */ 
TCHAR fname[13];  /* Short file name (8.3 format) */ 

} FILINFO;

Мне нужно скопировать имена файлов в массив для обработки, однако я пробовал несколько способов, но не могу заставить массив работать. Я попытался создать произвольно большой массив TCHAR и разыменовать указатель имени файла, но это печатает мусор.

FRESULT result; 
     char *path = '/'; //look in root of sd card 
     TCHAR fileList[50]; 
     u32 index=0; 
     result = f_opendir(&directory, path); //open directory 
     if(result==FR_OK){ 
      for(;;){ 
       result = f_readdir(&directory, &fileInfo); //read directory 
       if(result==FR_OK){ 
        if(fileInfo.fname[0]==0){ //end of dir reached 
         //LCD_UsrLog("End of directory.\n"); 
         break; 
        } 
        if(fileInfo.fname[0]=='.')continue; //ignore '.' files 

        TCHAR *fn_ptr; //file name, why a pointer? 
        fn_ptr=&fileInfo.fname; //get file name    

        fileList[index]=*fn_ptr; 
        LCD_UsrLog("%s\n",fileList[index]); 
        for(delay=0;delay<0x0FFFFF;delay++){ShortDelay();} //delay to display 
        index++; 
       }//end result==fr_ok 
      }//end for 
     }//end result==fr_ok 

Я подозреваю, что это простая ошибка относительно указателей или надлежащего использования массива символов, но это было 4+ лет, так как я в последний раз коснулся C, и я потерял!

Любая помощь была бы принята с благодарностью.

ответ

1

Первая проблема: в настоящее время ваш список файлов представляет собой массив символов, в то время как он должен быть массивом строк. Так объявим его как

TCHAR* fileList[50]; 

затем выделить строки соответствующей длины для каждого файла (не забывая дополнительное пространство для завершающего 0 гольца). Вам также необходимо явно скопировать имена файлов в ваш список имен, потому что содержимое fileInfo будет перезаписано в каждом цикле цикла, поэтому простое сохранение указателей приведет к тому, что ваш список, содержащий имя последнего файла, будет 50 раз.

В общем, вам нужно что-то вроде этого:

   if(fileInfo.fname[0]=='.')continue; //ignore '.' files 

       fileList[index] = malloc(strlen(fileInfo.fname) + 1); 
       strcpy(fileList[index], fileInfo.fname); 

       LCD_UsrLog("%s\n",fileList[index]); 

(Отказ: Нет гарантий, что это работает, как это, у меня нет возможности проверить, но мы надеемся, что это дает вам идею).

В качестве альтернативы, если вы знаете верхний предел длины имени файла, вы можете объявить массив имен файлов с фиксированной длиной и избавиться от динамического распределения. Но тогда вы должны использовать strncpy вместо strcpy, чтобы быть в безопасности, чтобы предотвратить переполнение буфера. И это также требует прекращения 0 символ должен быть добавлен, снова быть на безопасной стороне:

TCHAR fileList[50][MAX_FILENAME_LENGTH + 1]; 

... 
strncpy(fileList[index], fileInfo.fname, strlen(fileInfo.fname)); 
fileList[index][MAX_FILENAME_LENGTH] = '\0'; 
+0

Это идеальный вариант. Большое спасибо за быстрый ответ. Теперь мне нужно будет решить, как изменить массив fileList, чтобы динамически изменить его размер (это означает, что я скоро вернусь к другому вопросу!) – David

+0

Питер, есть ли преимущество в использовании второго подхода - многомерный массив ? Это значительно затрудняет печать имен файлов, и я пока не вижу никакой пользы (пока). – David

+0

@ David, преимущество в том, что память выделяется в стеке, поэтому автоматически освобождается после выхода из области видимости. Используя динамическое распределение, вам также необходимо вручную освободить память, иначе вы получите утечку памяти. –

0

Вы должны использовать следующий определение массива

TCHAR fileList[50][13]; 

...

   if(fileInfo.fname[0]=='.')continue; //ignore '.' files 

       strncpy(fileList[index], sizeof(fileList[index]), fileInfo.fname); 
       LCD_UsrLog("%s\n",fileList[index]); 

или для динамической памяти. Не забудьте освободить память!

TCHAR* fileList[50]; 

...

   if(fileInfo.fname[0]=='.')continue; //ignore '.' files 

       fileList[index]=strdup(fileInfo.fname); 
       LCD_UsrLog("%s\n",fileList[index]); 

PS:

Смежные вопросы