You are viewing our Forum Archives. To view or take place in current topics click here.
[C++]Listing current items in directory
Posted:

[C++]Listing current items in directoryPosted:

ip
  • Winter 2018
Status: Offline
Joined: Dec 30, 201211Year Member
Posts: 3,778
Reputation Power: 3016
Status: Offline
Joined: Dec 30, 201211Year Member
Posts: 3,778
Reputation Power: 3016
Using [ Register or Signin to view external links. ] and my code is horrible. Newish to C++ so don't harp on me too bad. Here's what I have currently.


const char const* ConfigFiles[25] = { }; // This is just a test for the array
bool isSelected = false;
if ( SUCCEEDED( SHGetFolderPathA( NULL, CSIDL_APPDATA, NULL, 0, path ) ) )
{
    folder = std::string( path ) + "\\hl2\\";
    file = std::string( path ) + "\\hl2\\" + configBuffer + ".config";
                   
    DIR* dirFile = opendir( folder.c_str() );
    if( dirFile )
    {
        struct dirent* hFile;
        errno = 0;
        while((hFile = readdir(dirFile )) != NULL )
        {
            if ( !strcmp( hFile->d_name, "." ) ) continue;
            if ( !strcmp( hFile->d_name, ".." ) ) continue;
            if ( strstr( hFile->d_name, ".config" ) )
            {
                ConfigFiles[counter] = hFile->d_name;
                counter++;
            }           
        }
    }
}
for(int i = 0; i < counter; i++ ) {
    ImGui::Selectable( ConfigFiles[ i ], isSelected );
}


This is what pops up when I create the first config file.
[ Register or Signin to view external links. ]

And the second file created as well.
[ Register or Signin to view external links. ]

Proof that both the files are created.
[ Register or Signin to view external links. ]

Is there something that I'm doing completely wrong here? Or is it my brain that is causing it because I'm stupid? Any help would be appreciated.
#2. Posted:
tortuga
  • Blind Luck
Status: Offline
Joined: Dec 25, 200914Year Member
Posts: 2,314
Reputation Power: 1686
Status: Offline
Joined: Dec 25, 200914Year Member
Posts: 2,314
Reputation Power: 1686
I'm afraid I don't understand -- what are you trying to do? From your pictures, it looks like you're already listing the current items in the directory.
#3. Posted:
ProJimmyRustler
  • TTG Senior
Status: Offline
Joined: Jul 14, 201410Year Member
Posts: 1,720
Reputation Power: 71
Status: Offline
Joined: Jul 14, 201410Year Member
Posts: 1,720
Reputation Power: 71
My C++ is a little rusty, but I feel like the problem is coming from your for loop that I assume populates your "config" list:

for(int i = 0; i < counter; i++ ) {
    ImGui::Selectable( ConfigFiles[ i ], isSelected );
}


Out of curiosity, are you able to just declare ImGui::Selectable( ConfigFiles[0], isSelected); and ImGui::Selectable( ConfigFiles[2], isSelected); to see if you would get the out put you wanted?

I know this doesn't solve the problem, but it could give an idea of where the error is.

Assuming the for loop is what outputs the list of items for ImGui items in that list, it is very odd that you are getting testconfig2.config twice. It could have something to do with how the ImGui::Selectable is handled.
#4. Posted:
ip
  • Summer 2020
Status: Offline
Joined: Dec 30, 201211Year Member
Posts: 3,778
Reputation Power: 3016
Status: Offline
Joined: Dec 30, 201211Year Member
Posts: 3,778
Reputation Power: 3016
tortuga wrote I'm afraid I don't understand -- what are you trying to do? From your pictures, it looks like you're already listing the current items in the directory.
Sorry I didn't put that much information into the post, it was 3 am and my brain was dead. Yes, I have listing the directory files correct but after I create one configuration file (which lists it correctly), as soon as I create another one it automatically renames both of the files within the list to the last created config file.
#5. Posted:
tortuga
  • Fairy Master
Status: Offline
Joined: Dec 25, 200914Year Member
Posts: 2,314
Reputation Power: 1686
Status: Offline
Joined: Dec 25, 200914Year Member
Posts: 2,314
Reputation Power: 1686
ip wrote
tortuga wrote I'm afraid I don't understand -- what are you trying to do? From your pictures, it looks like you're already listing the current items in the directory.
Sorry I didn't put that much information into the post, it was 3 am and my brain was dead. Yes, I have listing the directory files correct but after I create one configuration file (which lists it correctly), as soon as I create another one it automatically renames both of the files within the list to the last created config file.

Oh I see it now! Thanks for the clarification.

The code snippet you have above looks right and should store the names of your config files in that ConfigFiles array. What happens when you already have some config files in your directory; does running your code list them all just fine?

Can you post the code that takes in the name of the new file and how it's supposed to interact with the above code? There's probably some pointer mishap going on there.
#6. Posted:
ip
  • Winter 2018
Status: Offline
Joined: Dec 30, 201211Year Member
Posts: 3,778
Reputation Power: 3016
Status: Offline
Joined: Dec 30, 201211Year Member
Posts: 3,778
Reputation Power: 3016
tortuga wrote
Oh I see it now! Thanks for the clarification.

The code snippet you have above looks right and should store the names of your config files in that ConfigFiles array. What happens when you already have some config files in your directory; does running your code list them all just fine?

Can you post the code that takes in the name of the new file and how it's supposed to interact with the above code? There's probably some pointer mishap going on there.
So this is what I have so far as for saving the config files on the press of the button.
if ( ImGui::Button( "Save config" ) ) {
            config.Save( configBuffer );
}


This is my save function.
void CConfig::Save(const char* c_Config )
{
    static CHAR path[ MAX_PATH ];
    std::string folder, file;

    if ( SUCCEEDED( SHGetFolderPathA( NULL, CSIDL_APPDATA, NULL, 0, path ) ) )
    {
        folder = std::string( path ) + "\\hl2\\";
        file = std::string( path ) + "\\hl2\\" + c_Config + ".config";
    }

    CreateDirectoryA( folder.c_str( ), NULL );

    for ( auto value : ints )
        WritePrivateProfileStringA( value->category.c_str( ), value->name.c_str( ), std::to_string( *value->value ).c_str( ), file.c_str( ) );

    for ( auto value : floats )
        WritePrivateProfileStringA( value->category.c_str( ), value->name.c_str( ), std::to_string( *value->value ).c_str( ), file.c_str( ) );

    for ( auto value : bools )
        WritePrivateProfileStringA( value->category.c_str( ), value->name.c_str( ), *value->value ? "true" : "false", file.c_str( ) );
}
#7. Posted:
tortuga
  • Wizard
Status: Offline
Joined: Dec 25, 200914Year Member
Posts: 2,314
Reputation Power: 1686
Status: Offline
Joined: Dec 25, 200914Year Member
Posts: 2,314
Reputation Power: 1686
Hey sorry for getting back to you late. Don't know if you've already figured it out, but yeah I can't tell what's wrong. Your pointer manipulation seems fine in both functions.

Can you try printing the value of `hFile->d_name` before adding that string to the `ConfigFiles` array from the first snippet you posted? And then print the array after the function is done. If the output is similar to what you see in your GUI, then there's definitely an issue with the way you might be handling your pointers, but I can't see it! Is the first snippet really where we're listing all of the files?
#8. Posted:
ObscureCoder
  • Resident Elite
Status: Offline
Joined: Jun 29, 201311Year Member
Posts: 211
Reputation Power: 13
Status: Offline
Joined: Jun 29, 201311Year Member
Posts: 211
Reputation Power: 13
I don't know much of how dirent.h works on Windows but some general notes should be:

1) There's a chance readdir() is returning static memory, which would imply that you're perhaps inserting the exact same pointer into each element of ConfigFiles[25] every entry iteration. So, the pointer stays the same, the d_name content just changes (which would explain why the you're printing out the same thing twice; the pointers are probably the same; both referencing the most recent d_name content, that being whatever string is repeated). As I've said though, I don't use the dirent.h API so it may be some other issue.

2) There's no point in you using dirent.h since you undermined the whole POSIX compliance part when you used the deprecated SHGetFolderPathA function (if you're only targeting Windows, you can just use the WinAPI directory functions).

3) I'd personally just use the <experimental/filesystem> from the C++17's STL and a std::vector comprised of std::strings.

4) If you wanna keep doing what you're doing, I recommend just storing a std::vector of std::strings. Since, that way they'll make a copy when you conversion construct them from a const char*. Just make sure you have well defined lifetime dependencies since using c_str() with imgui on a std::string could cause issues if the lifetime of your std::string doesn't equate (or exceed, preferably) the lifetime of whatever you're passing the return of c_str() to (that said, I'm not sure if imgui makes copies of strings).

Some more general notes would be:
1) Please just use nullptr in C++.
2) For intent, you can limit the scope of firFile by checking its validity implicitly during a declaration in an if statement. Like this: if(DIR* dirFile = opendir(folder.c_str())) {}
3) while((hFile = readdir(dirFile )) != NULL ) - that comparison to NULL is redundant; it will implicitly be true if it's not NULL.
4) Please use a dynamically allocating container for your config files entries, you didn't even range-check counter before using it.
5) Your syntax for a const pointer is actually invalid. It should be: const char* const.
Jump to:
You are viewing our Forum Archives. To view or take place in current topics click here.