1

What my code is suppose to achieve is to read in the file names after given a file path input and output (switch 1: the files under the same folder)(switch 2: all the file names under the directory including sub-directories), and to not store the folder names into vector (1.png 2.png 3.png but not ChildFolder).

If you need extra information regarding the folder structures it is provided in my previous question.

#define IDC_RADIO1                      1000
#define IDC_RADIO2                      1001
#define IDC_EDIT1                       1002
#define IDC_BUTTON1                     1003
#define IDC_LIST1                       1004

This window app have 2 radiobox, 1 editbox for user to input path name, 1 button to start the whole process, and 1 listbox to display the files read

Main function starts below:

void CMFCApplication3Dlg::OnBnClickedButton1()
{
    string a;
    vector<string> caseOne,
                   caseTwo;

The bottom two lines of code is where I have issues

The a = "C:\Users\User... code works but the output seems to have a array element logic problem going on where the output in the listbox is Nothing,1.png,2.png instead of 1.png,2.png Edit Note :this part works now

The code directory_iterator list(str); seems to have a memory problem caused by
a = enterPath.GetBuffer(); and I don't know what to do to fix it.

ErrorMessage Unhandled exception at 0x7525B502 in MFCApplication3.exe: Microsoft C++ exception: std::filesystem::filesystem_error at memory location 0x0133E438.

The screen shot is provided below

I would ideally delete a = "C:\Users\User... and use a = enterP.. if it works

    a = "C:\\Users\\User\\Desktop\\ParentFolder";//This line is used to test code, will move on to having user input to IDC_EDIT1

    //a = enterPath.GetBuffer();//Code I want to use

    path str = a;
    directory_iterator list(str);
    CListBox* listBox = (CListBox*)GetDlgItem(IDC_LIST1);

    UpdateData(TRUE);//update the data
    int checkRadio = GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO2);
    switch (checkRadio)
    {
    case IDC_RADIO1:
        list = directory_iterator(a);                          //reset directory_iterator evertime button clicked to read new file
        for (auto& it : list) {                                //go through the directory_iterator list
            string filename1 = it.path().filename().string();  //get file names then convert filename into string format
            if (filename1.find(".") < filename1.length()/*or != string::npos*/ ) {    // find file name to rule out folders cause files contain '.'

                caseOne.push_back(filename1);       //putting the filenames into the vector
                CString fileunderPath;              //bottom 3 lines of code convert string to CString
                fileunderPath = filename1.c_str();
                listBox->AddString(fileunderPath);
            }
        }
        break;

    //same problem that should be resolved if case 1 is fixed
    case IDC_RADIO2://NOTE: NEED TO ADD CLEAR LISTBOX FUNCTION and vector
        list = directory_iterator(a);
        for (auto& dirEntry : recursive_directory_iterator(a)) {
            string filename2 = dirEntry.path().filename().string();
            if (filename2.find(".") != string::npos) { // find file name to rule out folders cause files contain '.'
                caseTwo.push_back(filename2);
            }
        }
        break;
    }
    UpdateData(FALSE);//finish updating the data

}

Edit:

This is what I want to achieve(UI screenshot)

Working version where I predetermine the folder path for user

This is what I want user to enter

Error message I got

What the folder content looks like

A child folder of the parent folder

The complete code of button 1

I also found a new bug I didn't notice before,The output is png.1 png.2 instead of 1.png 2.png, this should not have happened since I made it work without problem when I used cout<<; a while back Working version where I predetermine the folder path for user

Mochideer
  • 35
  • 8
  • If "." is not found `find` returns `string::npos` which is `-1`. – 001 Dec 20 '21 at 15:48
  • Also I think you rather want `a = enterPath.GetString()` than `a = enterPath.GetBuffer()`. – Jabberwocky Dec 20 '21 at 15:50
  • Also: what is `if (filename2.find(".") < filename2.length())` supposed to do? The comment `// find file name to rule out folders cause files contain '.'` is not very clear. Otherwise I don't see anything obviously wrong here. What exactly is the _"memory problem"_ you mention? Also _"but the output seems to have a array element logic problem going on where the output in the listbox is Nothing,1.png,2.png instead of 1.png,2.png"_ what problem? You need to show an example of actual and desired behaviour. – Jabberwocky Dec 20 '21 at 15:58
  • BTW: Just `string a = enterPath;` should work fine. Anyway, you need to clarify the question and possibly show more relevant code. – Jabberwocky Dec 20 '21 at 16:06
  • Showing the __complete__ `OnBnClickedButton1` function may also help – Jabberwocky Dec 20 '21 at 16:56
  • @Jabberwocky So I changed **filename1.find(".") < filename1.length() ** to **filename1.find(".") == 1**, and it works also , I don't really remember what my thought process was but now im swiching it for readability, the purpose of the code is to make the output change from **1.png 2.png ChildFolder --into-> 1.png 2.png** – Mochideer Dec 21 '21 at 01:39
  • @Jabberwocky Upon futher inspection filename1.find(".") == 1 only seem to return files with only one letter before '.' , so it will return 1.png or a.jpg but not 12.png of sadasd.png – Mochideer Dec 21 '21 at 07:05
  • 1
    The `directory_iterator` constructor throws an exception (as [documented](https://en.cppreference.com/w/cpp/filesystem/directory_iterator/directory_iterator)) when passing in invalid data. Which clearly, you are. The code you're running and the code you're showing aren't the same thing. Unrelated (probably), calling `GetBuffer` on a `CString` is not something you want. It is **not** a conversion operator. – IInspectable Dec 21 '21 at 07:06
  • Thanks you for the edits, but please __don't post pictures of source code__, is close to useless. – Jabberwocky Dec 21 '21 at 07:42

1 Answers1

1

After some research,I changed my code and finally got it working

//Answer
string a;
CString stri;//Read text from edit control box and convert it to std::string
GetDlgItem(IDC_EDIT1)->GetWindowText(stri);
a = CT2A(stri);

//This code is something I also tried but the string a it passed back is ""
/*CString b;
b = enterPath;//a control variable I added from IDC_EDIT1
a = CT2A(b);*/

Regarding the filename1.find(".") < filename1.length() it works becasue find() passes back the first location of the find character

so < filename1.length() means the return of the find() cannot be longer than the string it self, and when nothing is found it returns -1 the if statement still runs but passes nothing to the AddString.(That why it felt like a band aid fix)

So the better way to write the if statement is either

if(filename1.find(".") != -1)
//or
if(filename1.find(".") != string::npos)//npos is -1

and since I found a better way to distinguish file names from folder in the #include filesystem, I ended up deleting the code above anyway

because for some reason I thought folder names can't have"." in them

//code I switched to 
if(is_regular_file(it))
Mochideer
  • 35
  • 8