【问题标题】:Copying a string from a pointer to a string将字符串从指针复制到字符串
【发布时间】:2011-11-01 19:20:31
【问题描述】:

我正在开发一些代码,它从 sd 卡(使用 FatFs)读取文件名并将它们显示到屏幕上。这是我工作的一个片段,这会按预期打印出卡上的文件 -

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

我怀疑这是一个关于指针或正确使用字符数组的简单错误,但自从我上次接触 C 以来已经 4 年多了,我迷路了!

任何帮助将不胜感激。

【问题讨论】:

    标签: c pointers char


    【解决方案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';
    

    【讨论】:

    • 这是完美的。非常感谢您的快速反应。现在我必须弄清楚如何更改 fileList 数组以动态更改它的大小(这意味着我可能很快就会回来回答另一个问题!)
    • Peter,使用第二种方法——多维数组有什么优势吗?这使得打印文件名变得更加复杂,我看不到任何好处(目前)。
    • @David,好处是内存是在堆栈上分配的,因此一旦超出范围就会自动释放。使用动态分配,还需要手动释放内存,否则会出现内存泄漏。
    • 我明白了。在这种情况下,最好使用多维指针数组!谢谢
    【解决方案2】:

    你必须使用下一个数组定义

    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:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-04
      • 2015-01-17
      • 2010-09-27
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多