• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 296
  • Last Modified:

Return filenames to ListBox from array

I got some code from here and modified it to implement it myself in an MFC project I have.  I can't seem to get it to return the file names to my listbox.  What it seems to be doing is sending the address in memory of the pointer of the last file it looks at rather than returning the correct filenames.  Any ideas?

void Readcfgini()
{
      char **dirarray;
      char *scandir;

      scandir = "C:\\UI Code and Executable\\UIMFC\\UIMFC\\Debug\\programs";
      dirarray = 0;
      dirarray = ScanDir( scandir , 0);

      CString temp;
      for(int i=0;i<sizeof(dirarray);i++){

                  /*(int k[sizeof(dirarray)],j;
                  for(j=0;j<sizeof(dirarray);j++)
                  {
                        k[j]=(int)dirarray[j];
                        //cout<<i[j]<<" "; //output the ascii chars
                        temp.Format("%d", k[j]);
                  }*/


            temp.Format("%d", dirarray);
            m_list.AddString(temp);
}



}

char ** ScanDir(char* dirname, int indent)
{
    BOOL            fFinished;
    HANDLE          hList;
    TCHAR           szDir[MAX_PATH+1];
    WIN32_FIND_DATA FileData;
    char ** names = NULL;
    int count = 0 , maxnames = 0;


    // Get the proper directory path
    sprintf(szDir, "%s\\*", dirname);

    // Get the first file
    hList = FindFirstFile(szDir, &FileData);
    if (hList == INVALID_HANDLE_VALUE)
    {
        return NULL;     // No files, return empty list
    }
    else
    {
        // Traverse through the directory structure
        fFinished = FALSE;
        while (!fFinished)
        {
            // Make sure we have enough room in array to add another name
            if (count >= maxnames)
                 names = (char **)realloc(names, (maxnames+=1024)*sizeof(char*));

            // Check the object is a directory or not
            if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                if ((strcmp(FileData.cFileName, ".") != 0) &&
(strcmp(FileData.cFileName, "..") != 0))
                {
                      names[count] = (char *)malloc(strlen(FileData.cFileName)+2);
                      strcpy(names[count], FileData.cFileName);
                      // add a trailing slash to indicate directory
                      strcat(names[count], "\\");
                      count++;
                }
            }
            else
                        names[count++] = (FileData.cFileName);                  

            if (!FindNextFile(hList, &FileData))
            {
                if (GetLastError() == ERROR_NO_MORE_FILES)
                {
                    fFinished = TRUE;
                }
            }
        }
    }

    return names;
}
0
vivekpara
Asked:
vivekpara
  • 3
  • 2
  • 2
2 Solutions
 
vivekparaAuthor Commented:
I think its THIS line that is incorrect in some way...but I'm not sure how:

names[count++] = (FileData.cFileName);  

Or it could be something in my Readcfgini function that is returning the data to the listbox.

Sigh!
0
 
jkrCommented:
It is indded incorrect, since it only copies a pointer to the struct entry that is reused in the loop, thus having all pointers point to the string that was read last.. Try

names[count++] = strdup(FileData.cFileName);  

(you might need to #include <string.h>).

Apart from that, since you mentioned MFC, you'd better use a CStringList for that, e.g.

 CStringList names;

 names.AddTail(CString(FileData.cFileName));
0
 
jkrCommented:
BTW, http://www.codeproject.com/dialog/searchfolders.asp ("Browse Folder dialog, search folder and all sub folders using C/C++") seems to really cover your issue.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
itsmeandnobodyelseCommented:
jkr has it right. You need an allocation for names[count] and a string copy. Instead of strdup you also could repeat the sequence you have in the if branch:
 
       names[count] = (char *)malloc(strlen(FileData.cFileName)+1);
       strcpy(names[count++], FileData.cFileName);

If you later want to change to C++ operator new (replacing malloc) and/or  C++ containers like CStringList, CStringArray or std::vector<string>, you shouldn't forget to replace strdup as well, as strdup uses malloc.
                     
Regards, Alex
0
 
vivekparaAuthor Commented:
I'm trying it, but it seemed easier to recode than to use the old stuff now.  Now how do I return file names in this new code, though?  What I need is a way to store it in the stringarray and then be able to loop through my collection to read each of the files.   I think my sizeof line will not work properly...but I'm not sure.  Also, my knowledge of handles is useless...so if you have any suggestions on how to use them properly...please interject.

      CStringArray astrPaths;
      LPCTSTR name = "C:\\UI Code and Executable\\UIMFC\\UIMFC\\Debug\\programs\\*.cfg";
      WIN32_FIND_DATA data;
      HANDLE fileHandle = FindFirstFile(name, &data);

      for(int i=0;i<sizeof(fileHandle);i++)
            {
            
            if(fileHandle == INVALID_HANDLE_VALUE) {

                  if(GetLastError() == ERROR_FILE_NOT_FOUND)
                  {
                  }
                  else
                  {
                        //astrPaths.Add((LPCTSTR)fileHandle);
                  }
            }
      }
0
 
itsmeandnobodyelseCommented:
    CStringArray astrPaths;
     LPCTSTR name = "C:\\UI Code and Executable\\UIMFC\\UIMFC\\Debug\\programs\\*.cfg";
     WIN32_FIND_DATA data;
     HANDLE fileHandle = FindFirstFile(name, &data);

     while (fileHandle != INVALID_HANDLE_VALUE)
     {
             astrPaths.Add(data.cFileName);
             if (!FindNextFile(fileHandle, &data))
                   break;
     }
     DWORD err;
     if((err = GetLastError()) != ERROR_NO_MORE_FILES)
     {
           cout << "error = " << err << endl;
           return;
     }


Regards, Alex


0
 
vivekparaAuthor Commented:
This is what I ended up with:

void Readcfgini()
{
      
     CStringArray astrPaths;
     LPCTSTR name = "C:\\UI Code and Executable\\UIMFC\\UIMFC\\Debug\\programs\\*.txt";
     WIN32_FIND_DATA data;
     HANDLE fileHandle = FindFirstFile(name, &data);

     while (fileHandle != INVALID_HANDLE_VALUE)
     {
             astrPaths.Add(data.cFileName);
             m_list.AddString(data.cFileName);
                  
             if (!FindNextFile(fileHandle, &data))
                   break;
     }
     DWORD err;
     if((err = GetLastError()) != ERROR_NO_MORE_FILES)
     {
           return;
     }


}
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

  • 3
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now